@@ -9,16 +9,18 @@ namespace BluetoothHeartrateModule
9
9
public class BluetoothHeartrateProvider : HeartrateProvider
10
10
{
11
11
private Dictionary < string , string ? > deviceNames = new ( ) ;
12
+ private GattDeviceService ? heartRateService ;
12
13
private GattCharacteristic ? heartRateCharacteristic ;
13
14
private HashSet < string > missingCharacteristicDevices = new ( ) ;
14
15
private bool processingData = false ;
15
16
BluetoothLEDevice ? currentDevice ;
16
17
private readonly BluetoothHeartrateModule module ;
17
- public override bool IsConnected => currentDevice != null && heartRateCharacteristic != null ;
18
+ public override bool IsConnected => currentDevice != null && heartRateCharacteristic != null && currentDevice . ConnectionStatus == BluetoothConnectionStatus . Connected ;
18
19
19
20
public BluetoothHeartrateProvider ( BluetoothHeartrateModule module )
20
21
{
21
22
this . module = module ;
23
+
22
24
}
23
25
24
26
public override void Initialise ( )
@@ -35,15 +37,7 @@ public override void Initialise()
35
37
}
36
38
37
39
module . watcher . Received += Watcher_Received ;
38
- module . watcher . Stopped += Watcher_Stopped ;
39
- switch ( module . watcher . Status )
40
- {
41
- case BluetoothLEAdvertisementWatcherStatus . Stopped :
42
- case BluetoothLEAdvertisementWatcherStatus . Created :
43
- module . watcher . Start ( ) ;
44
- Log ( "Watching for devices" ) ;
45
- break ;
46
- }
40
+ module . StartWatcher ( ) ;
47
41
}
48
42
49
43
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
@@ -59,24 +53,50 @@ private void Reset()
59
53
if ( module . watcher != null )
60
54
{
61
55
module . watcher . Received -= Watcher_Received ;
62
- module . watcher . Stopped -= Watcher_Stopped ;
63
56
}
64
57
deviceNames . Clear ( ) ;
65
58
missingCharacteristicDevices . Clear ( ) ;
66
59
ResetDevice ( ) ;
67
60
processingData = false ;
68
61
}
69
62
70
- private void ResetDevice ( )
63
+ private async void ResetDevice ( )
71
64
{
65
+ if ( heartRateService != null )
66
+ {
67
+ try
68
+ {
69
+ heartRateService . Dispose ( ) ;
70
+ }
71
+ catch ( ObjectDisposedException )
72
+ {
73
+ // Ignore if object is already disposed
74
+ }
75
+ heartRateService = null ;
76
+ }
72
77
if ( heartRateCharacteristic != null )
73
78
{
74
- heartRateCharacteristic . ValueChanged -= HeartRateCharacteristic_ValueChanged ;
79
+ try
80
+ {
81
+ heartRateCharacteristic . ValueChanged -= HeartRateCharacteristic_ValueChanged ;
82
+ }
83
+ catch ( ObjectDisposedException )
84
+ {
85
+ // Ignore if object is already disposed
86
+ }
75
87
heartRateCharacteristic = null ;
76
88
}
77
89
if ( currentDevice != null )
78
90
{
79
- currentDevice . Dispose ( ) ;
91
+ try
92
+ {
93
+ currentDevice . ConnectionStatusChanged -= Device_ConnectionStatusChanged ;
94
+ currentDevice . Dispose ( ) ;
95
+ }
96
+ catch ( ObjectDisposedException )
97
+ {
98
+ // Ignore if object is already disposed
99
+ }
80
100
currentDevice = null ;
81
101
}
82
102
}
@@ -128,13 +148,15 @@ private async void Watcher_Received(BluetoothLEAdvertisementWatcher sender, Blue
128
148
var currentDeviceName = deviceNames [ advertisementMac ] ?? "Unknown" ;
129
149
Log ( $ "Found device named { currentDeviceName } for MAC { advertisementMac } ") ;
130
150
module . SetDeviceName ( currentDeviceName ) ;
151
+ currentDevice . ConnectionStatusChanged += Device_ConnectionStatusChanged ;
131
152
}
132
153
133
154
var missungUnknown = ! missingCharacteristicDevices . Contains ( deviceMacSetting ) ;
134
155
var services = await currentDevice . GetGattServicesForUuidAsync ( GattServiceUuids . HeartRate , BluetoothCacheMode . Uncached ) ;
135
156
if ( services . Services . Count > 0 )
136
157
{
137
- var firstService = services . Services [ 0 ] ;
158
+ IEnumerable < GattDeviceService > cleanupServices = services . Services ;
159
+ var firstService = cleanupServices . First ( ) ;
138
160
if ( missungUnknown )
139
161
{
140
162
Log ( "Found heartrate service" ) ;
@@ -144,6 +166,7 @@ private async void Watcher_Received(BluetoothLEAdvertisementWatcher sender, Blue
144
166
{
145
167
if ( heartRateCharacteristic == null )
146
168
{
169
+ heartRateService = firstService ;
147
170
heartRateCharacteristic = characteristics . Characteristics [ 0 ] ;
148
171
Log ( "Found heartrate measurement characteristic" ) ;
149
172
@@ -162,16 +185,19 @@ private async void Watcher_Received(BluetoothLEAdvertisementWatcher sender, Blue
162
185
}
163
186
OnConnected ? . Invoke ( ) ;
164
187
Log ( "Connection successful" ) ;
188
+ module . StopWatcher ( ) ;
189
+ cleanupServices = services . Services . Skip ( 1 ) ;
165
190
}
166
191
else
167
192
{
168
193
Log ( $ "Failed to enable heart rate notifications. Status: { status } ") ;
169
194
}
170
195
}
171
196
}
172
- else
197
+
198
+ if ( cleanupServices . Any ( ) )
173
199
{
174
- foreach ( var service in services . Services )
200
+ foreach ( var service in cleanupServices )
175
201
service . Dispose ( ) ;
176
202
}
177
203
}
@@ -201,10 +227,13 @@ private void HeartRateCharacteristic_ValueChanged(GattCharacteristic sender, Gat
201
227
OnHeartrateUpdate ? . Invoke ( data [ 1 ] ) ;
202
228
}
203
229
204
- private void Watcher_Stopped ( BluetoothLEAdvertisementWatcher sender , BluetoothLEAdvertisementWatcherStoppedEventArgs args )
230
+ private async void Device_ConnectionStatusChanged ( BluetoothLEDevice sender , object args )
205
231
{
206
- Log ( "Watcher stopped" ) ;
207
- OnDisconnected ? . Invoke ( ) ;
232
+ if ( sender . ConnectionStatus == BluetoothConnectionStatus . Disconnected )
233
+ {
234
+ Log ( "Current device disconected" ) ;
235
+ OnDisconnected ? . Invoke ( ) ;
236
+ }
208
237
}
209
238
}
210
239
}
0 commit comments