4
4
//
5
5
6
6
using System ;
7
- using System . Diagnostics ;
8
7
using System . Threading ;
9
8
10
9
using nanoFramework . Device . Bluetooth ;
14
13
/// Bluetooth Sample 2 is a custom service which shows the use of:
15
14
///
16
15
/// - Adding security to characteristics
17
- /// - 1st characteristic you can read without pairing but will need to be paired to write
18
- /// - 2nd characteristic you can write without pairing but will need to be paired to Read
19
- /// - Both characteristic read/write same value.
16
+ /// - 1st characteristic you can read & write without pairing
17
+ /// - 2nd characteristic you can read & write but will required device to paired so encryption is enabled. If you try to access this characteristic
18
+ /// a pairing will be forced. You can use a just works type of pairing for this.
19
+ /// - 3nd characteristic you can read & write but will required device to paired and authenticated. If you try to access this characteristic
20
+ /// a pairing will be forced. A pin number of 654321 will need to be entered to pair succesfully.
21
+ ///
22
+ /// - All characteristics read/write same value.
20
23
///
21
24
/// You will be able to connect to the service and read values or subscribe to Notified ever 10 seconds.
22
- /// Suitable Phone apps: "LightBlue" or "nRF Connect"
25
+ /// Suitable Phone apps: "LightBlue" or "nRF Connect". If using a smaller then six digits for pin then use leading zeroes in these apps.
23
26
/// </summary>
24
27
namespace BluetoothLESample2
25
28
{
26
29
public class Program
27
30
{
28
31
static GattLocalCharacteristic _readWriteCharacteristic1 ;
29
32
static GattLocalCharacteristic _readWriteCharacteristic2 ;
33
+ static GattLocalCharacteristic _readWriteCharacteristic3 ;
30
34
31
35
// value used to read/write
32
- static Int32 _value ;
36
+ static Int32 _value = 57 ;
37
+
38
+ // Default pin
39
+ const int PASSKEY = 654321 ;
33
40
34
41
public static void Main ( )
35
42
{
36
- Debug . WriteLine ( "Hello from Bluetooth Sample 2" ) ;
43
+ Console . WriteLine ( ) ;
44
+ Console . WriteLine ( "Hello from Bluetooth Sample 2" ) ;
37
45
38
46
Guid serviceUuid = new Guid ( "A7EEDF2C-DA8C-4CB5-A9C5-5151C78B0057" ) ;
39
- Guid writeCharUuid1 = new Guid ( "A7EEDF2C-DA8D-4CB5-A9C5-5151C78B0057" ) ;
40
- Guid writeCharUuid2 = new Guid ( "A7EEDF2C-DA8E-4CB5-A9C5-5151C78B0057" ) ;
47
+ Guid plain_CharUuid1 = new Guid ( "A7EEDF2C-DA8D-4CB5-A9C5-5151C78B0057" ) ;
48
+ Guid encrypt_CharUuid2 = new Guid ( "A7EEDF2C-DA8E-4CB5-A9C5-5151C78B0057" ) ;
49
+ Guid auth_CharUuid3 = new Guid ( "A7EEDF2C-DA8F-4CB5-A9C5-5151C78B0057" ) ;
50
+
51
+ // BluetoothLEServer is a singleton object so gets its instance. The Object is created when you first access it
52
+ // and can be disposed to free up memory.
53
+ BluetoothLEServer server = BluetoothLEServer . Instance ;
54
+
55
+ // Give device a name
56
+ server . DeviceName = "Sample2" ;
57
+
58
+ // Set up an event handler for handling pairing requests
59
+ server . Pairing . PairingRequested += Pairing_PairingRequested ;
60
+ server . Pairing . PairingComplete += Pairing_PairingComplete ;
61
+
62
+ // Set up event for a session status change, client connects/disconnects
63
+ server . Session . SessionStatusChanged += Session_SessionStatusChanged ;
64
+
65
+ // The IOCapabilities define the input /output capabilities of the device and the type of pairings that is available.
66
+ // See Bluetooth pairing matrix for more information.
67
+ // With NoInputNoOutput on both ends then only "Just works" pairing is available and only first 2 characteristics will be accesable.
68
+ server . Pairing . IOCapabilities = DevicePairingIOCapabilities . NoInputNoOutput ;
69
+
70
+ // By making it a display we force an Authenication, Remove following comment to try this out
71
+ server . Pairing . IOCapabilities = DevicePairingIOCapabilities . DisplayOnly ;
72
+
73
+ // Start the Bluetooth server.
74
+ server . Start ( ) ;
41
75
42
76
//The GattServiceProvider is used to create and advertise the primary service definition.
43
77
//An extra device information service will be automatically created.
@@ -55,13 +89,13 @@ public static void Main()
55
89
#region Characteristic 1
56
90
// Add Read Characteristic for data that changes to service
57
91
// We also want the connected client to be notified when value changes so we add the notify property
58
- GattLocalCharacteristicResult characteristicResult = service . CreateCharacteristic ( writeCharUuid1 ,
92
+ GattLocalCharacteristicResult characteristicResult = service . CreateCharacteristic ( plain_CharUuid1 ,
59
93
new GattLocalCharacteristicParameters ( )
60
94
{
61
95
CharacteristicProperties = GattCharacteristicProperties . Read | GattCharacteristicProperties . Write ,
62
96
UserDescription = "My Read/Write Characteristic 1" ,
63
97
ReadProtectionLevel = GattProtectionLevel . Plain ,
64
- WriteProtectionLevel = GattProtectionLevel . EncryptionRequired
98
+ WriteProtectionLevel = GattProtectionLevel . Plain
65
99
} ) ;
66
100
;
67
101
@@ -74,23 +108,22 @@ public static void Main()
74
108
// Get reference to our read Characteristic
75
109
_readWriteCharacteristic1 = characteristicResult . Characteristic ;
76
110
77
- // Set up event handlers for read/write
111
+ // Set up event handlers for read/write #1
78
112
_readWriteCharacteristic1 . WriteRequested += _writeCharacteristic_WriteRequested ;
79
113
_readWriteCharacteristic1 . ReadRequested += _readWriteCharacteristic_ReadRequested ;
80
114
#endregion
81
115
82
- #region Characteristic 1
116
+ #region Characteristic 2 - Encryption required
83
117
// Add Read Characteristic for data that changes to service
84
118
// We also want the connected client to be notified when value changes so we add the notify property
85
- characteristicResult = service . CreateCharacteristic ( writeCharUuid2 ,
119
+ characteristicResult = service . CreateCharacteristic ( encrypt_CharUuid2 ,
86
120
new GattLocalCharacteristicParameters ( )
87
121
{
88
122
CharacteristicProperties = GattCharacteristicProperties . Read | GattCharacteristicProperties . Write ,
89
123
UserDescription = "My Read/Write Characteristic 2" ,
90
124
ReadProtectionLevel = GattProtectionLevel . EncryptionRequired ,
91
- WriteProtectionLevel = GattProtectionLevel . Plain
125
+ WriteProtectionLevel = GattProtectionLevel . EncryptionRequired
92
126
} ) ;
93
- ;
94
127
95
128
if ( characteristicResult . Error != BluetoothError . Success )
96
129
{
@@ -101,26 +134,89 @@ public static void Main()
101
134
// Get reference to our read Characteristic
102
135
_readWriteCharacteristic2 = characteristicResult . Characteristic ;
103
136
104
- // Set up event handlers for read/write
137
+ // Set up event handlers for read/write #2
105
138
_readWriteCharacteristic2 . WriteRequested += _writeCharacteristic_WriteRequested ;
106
139
_readWriteCharacteristic2 . ReadRequested += _readWriteCharacteristic_ReadRequested ;
107
140
#endregion
108
141
142
+ #region Characteristic 3 - Authentication & Encryption required
143
+ // Add Read Characteristic for data that changes to service
144
+ // We also want the connected client to be notified when value changes so we add the notify property
145
+ characteristicResult = service . CreateCharacteristic ( auth_CharUuid3 ,
146
+ new GattLocalCharacteristicParameters ( )
147
+ {
148
+ CharacteristicProperties = GattCharacteristicProperties . Read | GattCharacteristicProperties . Write ,
149
+ UserDescription = "My Read/Write Characteristic 3" ,
150
+ ReadProtectionLevel = GattProtectionLevel . EncryptionAndAuthenticationRequired ,
151
+ WriteProtectionLevel = GattProtectionLevel . EncryptionAndAuthenticationRequired
152
+ } ) ;
153
+
154
+ if ( characteristicResult . Error != BluetoothError . Success )
155
+ {
156
+ // An error occurred.
157
+ return ;
158
+ }
159
+
160
+ // Get reference to our read Characteristic
161
+ _readWriteCharacteristic3 = characteristicResult . Characteristic ;
162
+
163
+ // Set up event handlers for read/write #3
164
+ _readWriteCharacteristic3 . WriteRequested += _writeCharacteristic_WriteRequested ;
165
+ _readWriteCharacteristic3 . ReadRequested += _readWriteCharacteristic_ReadRequested ;
166
+ #endregion
167
+
109
168
// Once all the Characteristics have been created you need to advertise the Service so
110
169
// other devices can see it. Here we also say the device can be connected too and other
111
170
// devices can see it.
112
171
serviceProvider . StartAdvertising ( new GattServiceProviderAdvertisingParameters ( )
113
172
{
114
- DeviceName = "Sample2" ,
115
173
IsConnectable = true ,
116
174
IsDiscoverable = true
117
175
} ) ;
118
176
119
- Debug . WriteLine ( $ "Sample 2 now Advertising") ;
177
+ Console . WriteLine ( $ "Sample 2 Advertising") ;
120
178
121
179
Thread . Sleep ( Timeout . Infinite ) ;
122
180
}
123
181
182
+ private static void Session_SessionStatusChanged ( object sender , GattSessionStatusChangedEventArgs args )
183
+ {
184
+ Console . WriteLine ( $ "Session_SessionStatusChanged status->{ args . Status } Error->{ args . Error } ") ;
185
+ if ( args . Status == GattSessionStatus . Active )
186
+ {
187
+ Console . WriteLine ( $ "Client connected, address { BluetoothLEServer . Instance . Session . DeviceId : X} ") ;
188
+ }
189
+ else
190
+ {
191
+ Console . WriteLine ( "Client disconnected" ) ;
192
+ }
193
+ }
194
+
195
+ private static void Pairing_PairingComplete ( object sender , DevicePairingEventArgs args )
196
+ {
197
+ DevicePairing dp = sender as DevicePairing ;
198
+
199
+ Console . WriteLine ( $ "PairingComplete:{ args . Status } IOCaps:{ dp . IOCapabilities } IsPaired:{ dp . IsPaired } IsAuthenticated:{ dp . IsAuthenticated } ") ;
200
+ }
201
+
202
+ private static void Pairing_PairingRequested ( object sender , DevicePairingRequestedEventArgs args )
203
+ {
204
+ Console . WriteLine ( $ "CustomPairing_PairingRequested { args . PairingKind } ") ;
205
+
206
+ switch ( args . PairingKind )
207
+ {
208
+ // Passkey displayed on current device or just a know secret passkey
209
+ // Tell BLE what passkey is, so it can be checked against what has been entered on other device
210
+ case DevicePairingKinds . DisplayPin :
211
+ Console . WriteLine ( "DisplayPin" ) ;
212
+
213
+ // We don't actually display pin here but just tell Bluetooth what the pin is so it can
214
+ // compare with pin supplied by client
215
+ args . Accept ( PASSKEY ) ;
216
+ break ;
217
+ }
218
+ }
219
+
124
220
private static void _readWriteCharacteristic_ReadRequested ( GattLocalCharacteristic sender , GattReadRequestedEventArgs ReadRequestEventArgs )
125
221
{
126
222
GattReadRequest request = ReadRequestEventArgs . GetRequest ( ) ;
@@ -152,8 +248,7 @@ private static void _writeCharacteristic_WriteRequested(GattLocalCharacteristic
152
248
request . Respond ( ) ;
153
249
}
154
250
155
- Debug . WriteLine ( $ "Received value={ _value } ") ;
251
+ Console . WriteLine ( $ "Received value={ _value } ") ;
156
252
}
157
-
158
253
}
159
254
}
0 commit comments