├── .github ├── .changelog-config.json └── workflows │ ├── generate-changelog.yml │ ├── pr-checks.yml │ └── update-dependencies.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── NuGet.Config ├── README.md ├── README.zh-cn.md ├── Tests ├── Client │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── README.md │ ├── Services │ │ ├── DeviceInformationService.cs │ │ ├── EnvironmentalSensorService.cs │ │ └── TestService.cs │ ├── TestClient.nfproj │ ├── TestClient.sln │ ├── category.txt │ ├── packages.config │ └── packages.lock.json └── NFUnitTest1 │ ├── NFUnitTest1.nfproj │ ├── Properties │ └── AssemblyInfo.cs │ ├── TestUuidUtilities.cs │ ├── UnitTest1.cs │ ├── nano.runsettings │ ├── packages.config │ └── packages.lock.json ├── assets ├── nf-logo.png └── readme.txt ├── azure-pipelines.yml ├── nanoFramework.Device.Bluetooth.nuspec ├── nanoFramework.Device.Bluetooth.sln ├── nanoFramework.Device.Bluetooth ├── Advertisement │ ├── BluetoothLEAdvertisement.cs │ ├── BluetoothLEAdvertisementBytePattern.cs │ ├── BluetoothLEAdvertisementDataSection.cs │ ├── BluetoothLEAdvertisementDataSectionType.cs │ ├── BluetoothLEAdvertisementFilter.cs │ ├── BluetoothLEAdvertisementFlags.cs │ ├── BluetoothLEAdvertisementPublisher.cs │ ├── BluetoothLEAdvertisementPublisherStatus.cs │ ├── BluetoothLEAdvertisementPublisherStatusChangedEventArgs.cs │ ├── BluetoothLEAdvertisementReceivedEventArgs.cs │ ├── BluetoothLEAdvertisementType.cs │ └── BluetoothLEAdvertisementWatcherStoppedEventArgs.cs ├── BluetoothAddress.cs ├── BluetoothAddressType.cs ├── BluetoothConnectionStatus.cs ├── BluetoothDeviceId.cs ├── BluetoothError.cs ├── BluetoothEvent.cs ├── BluetoothEventListener.cs ├── BluetoothEventType.cs ├── BluetoothLEAdvertisementWatcher.cs ├── BluetoothLEAdvertisementWatcherStatus.cs ├── BluetoothLEDevice.cs ├── BluetoothLEManufacturerData.cs ├── BluetoothLEScanningMode.cs ├── BluetoothLEServer.cs ├── BluetoothNanoDevice.cs ├── BluetoothSignalStrengthFilter.cs ├── GenericAttributeProfile │ ├── GattCharacteristic.cs │ ├── GattCharacteristicProperties.cs │ ├── GattCharacteristicResult.cs │ ├── GattCharacteristicUuids.cs │ ├── GattClientCharacteristicConfigurationDescriptorValue.cs │ ├── GattClientNotificationResult.cs │ ├── GattCommunicationStatus.cs │ ├── GattDescriptor.cs │ ├── GattDescriptorResult.cs │ ├── GattDescriptorUuid.cs │ ├── GattDeviceService.cs │ ├── GattDeviceServicesResult.cs │ ├── GattLocalCharacteristic.cs │ ├── GattLocalCharacteristicParameters.cs │ ├── GattLocalCharacteristicResult.cs │ ├── GattLocalDescriptor.cs │ ├── GattLocalDescriptorParameters.cs │ ├── GattLocalDescriptorResult.cs │ ├── GattLocalService.cs │ ├── GattPresentationFormat.cs │ ├── GattPresentationFormatTypes.cs │ ├── GattProtectionLevel.cs │ ├── GattProtocolError.cs │ ├── GattReadClientCharacteristicConfigurationDescriptorResult.cs │ ├── GattReadRequest.cs │ ├── GattReadRequestedEventArgs.cs │ ├── GattReadResult.cs │ ├── GattServiceProvider.cs │ ├── GattServiceProviderAdvertisementStatus.cs │ ├── GattServiceProviderAdvertisingParameters.cs │ ├── GattServiceProviderResult.cs │ ├── GattServiceUuids.cs │ ├── GattSession.cs │ ├── GattSessionStatus.cs │ ├── GattSessionStatusChangedEventArgs.cs │ ├── GattSubscribedClient.cs │ ├── GattValueChangedEventArgs.cs │ ├── GattWriteOption.cs │ ├── GattWriteRequest.cs │ ├── GattWriteRequestedEventArgs.cs │ ├── GattWriteResult.cs │ └── IGattAttribute.cs ├── IO │ ├── Buffer.cs │ ├── DataReader.cs │ └── DataWriter.cs ├── Properties │ └── AssemblyInfo.cs ├── SPP │ ├── IBluetoothSpp.cs │ ├── NordicSpp.cs │ └── SppReceiveEventArgs.cs ├── Security │ ├── DeviceBonding.cs │ ├── DevicePairing.cs │ ├── DevicePairingEventArgs.cs │ ├── DevicePairingIOCapabilities.cs │ ├── DevicePairingKinds .cs │ ├── DevicePairingProtectionLevel.cs │ ├── DevicePairingRequestedEventArgs.cs │ ├── DevicePairingResult.cs │ ├── DevicePairingResultStatus.cs │ ├── DeviceUnpairingResult.cs │ ├── DeviceUnpairingResultStatus.cs │ └── PasswordCredential.cs ├── Utilities.cs ├── key.snk ├── nanoFramework.Device.Bluetooth.nfproj ├── packages.config └── packages.lock.json └── version.json /.github/.changelog-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "categories": [ 3 | { 4 | "title": "## New Features and enhancements", 5 | "labels": [ 6 | "Type: enhancement" 7 | ], 8 | "exhaustive": true 9 | }, 10 | { 11 | "title": "## Bug Fixes", 12 | "labels": [ 13 | "Type: bug" 14 | ], 15 | "exhaustive": true 16 | }, 17 | { 18 | "title": "## Documentation", 19 | "labels": [ 20 | "Type: documentation" 21 | ], 22 | "exhaustive": true 23 | }, 24 | { 25 | "title": "## ⚠️ Breaking Changes", 26 | "labels": [ 27 | "Breaking-Change" 28 | ], 29 | "exhaustive": true 30 | }, 31 | { 32 | "title": "## Updated dependencies", 33 | "labels": [ 34 | "Type: dependencies" 35 | ], 36 | "exhaustive": true 37 | } 38 | ], 39 | "sort": "ASC", 40 | "template": "${{CHANGELOG}}\n\n**Full Changelog:** ${{RELEASE_DIFF}}\n\nThe following NuGet package is available from this release:\n\n:package: [nanoFramework.Device.Bluetooth](https://www.nuget.org/packages/nanoFramework.Device.Bluetooth/)", 41 | "pr_template": "* ${{TITLE}} by @${{AUTHOR}} in #${{NUMBER}}", 42 | "empty_template": "- no changes", 43 | "max_tags_to_fetch": 200, 44 | "max_pull_requests": 200 45 | } 46 | -------------------------------------------------------------------------------- /.github/workflows/generate-changelog.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) .NET Foundation and Contributors 2 | # See LICENSE file in the project root for full license information. 3 | 4 | name: Generate Changelog 5 | run-name: Generate changelog 6 | 7 | on: 8 | push: 9 | tags: 10 | - '*' 11 | 12 | jobs: 13 | compose_changelog: 14 | name: nanoFramework 15 | uses: nanoframework/nf-tools/.github/workflows/generate-changelog.yml@main 16 | secrets: inherit 17 | -------------------------------------------------------------------------------- /.github/workflows/pr-checks.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) .NET Foundation and Contributors 2 | # See LICENSE file in the project root for full license information. 3 | 4 | name: PR Checks 5 | 6 | on: 7 | pull_request: 8 | 9 | jobs: 10 | check_package_lock: 11 | name: nanoFramework 12 | uses: nanoframework/nf-tools/.github/workflows/check-package-lock.yml@main 13 | check_nuget_latest: 14 | name: nanoFramework 15 | uses: nanoframework/nf-tools/.github/workflows/check-packages-updated.yml@main 16 | secrets: inherit 17 | with: 18 | solution: 'nanoFramework.Device.Bluetooth.sln' 19 | -------------------------------------------------------------------------------- /.github/workflows/update-dependencies.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) .NET Foundation and Contributors 2 | # See LICENSE file in the project root for full license information. 3 | 4 | # This workflow will periodically check .NET nanoFramework dependencies and updates them in the repository it's running. 5 | 6 | name: Daily update dependencies 7 | 8 | on: 9 | schedule: 10 | # At 00:20 UTC every Mon Thu. 11 | - cron: '00 20 * * Mon,Thu' 12 | repository_dispatch: 13 | types: update-dependencies 14 | 15 | jobs: 16 | update-dependencies: 17 | name: nanoFramework 18 | uses: nanoframework/nf-tools/.github/workflows/update-dependencies.yml@main 19 | secrets: inherit 20 | with: 21 | solutionsToCheck: 'nanoFramework.Device.Bluetooth.sln' 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | 254 | #SoundCloud 255 | *.sonarqube/ 256 | 257 | #VS Code 258 | .vscode 259 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) .NET Foundation and Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NuGet.Config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Tests/Client/Program.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | using System.Diagnostics; 8 | using System.Threading; 9 | 10 | using nanoFramework.Device.Bluetooth; 11 | using nanoFramework.Device.Bluetooth.GenericAttributeProfile; 12 | using nanoFramework.Device.Bluetooth.Services; 13 | using nanoFramework.Runtime.Native; 14 | 15 | using nanoFramework.Device.Bluetooth.Spp; 16 | 17 | /// 18 | /// TestClient for use with BlueTooth test cases 19 | /// 20 | /// Includes Standard Services: 21 | /// - Environmental Sensor 22 | /// - Device Information 23 | /// 24 | /// Plus Test Service for Settings values 25 | /// 26 | namespace TestClient 27 | { 28 | public static class Program 29 | { 30 | static EnvironmentalSensorService EnvService; 31 | 32 | // Indexes to sensors 33 | static int iTempOut; 34 | static int iTempOutMax; 35 | static int iTempOutMin; 36 | static int iHumidity; 37 | 38 | public static void Main() 39 | { 40 | Console.WriteLine(); 41 | Console.WriteLine("BlueTooth Test Client"); 42 | 43 | // Define used custom Uuid 44 | Guid serviceUuid = new("A7EEDF2C-DA87-4CB5-A9C5-5151C78B0066"); 45 | Guid readStaticCharUuid = new("A7EEDF2C-DA89-4CB5-A9C5-5151C78B0057"); 46 | 47 | Console.WriteLine("Create Primary service - UUID A7EEDF2C-DA87-4CB5-A9C5-5151C78B0066"); 48 | 49 | BluetoothLEServer.Instance.DeviceName = "Test2"; 50 | 51 | //The GattServiceProvider is used to create and advertise the primary service definition. 52 | //An extra device information service will be automatically created. 53 | GattServiceProviderResult result = GattServiceProvider.Create(serviceUuid); 54 | if (result.Error != BluetoothError.Success) 55 | { 56 | return; 57 | } 58 | 59 | GattServiceProvider serviceProvider = result.ServiceProvider; 60 | 61 | // Get created Primary service from provider 62 | GattLocalService service = serviceProvider.Service; 63 | 64 | #region Static read characteristic 65 | // Now we add an characteristic to service 66 | // If the read value is not going to change then you can just use a Static value 67 | DataWriter sw = new(); 68 | sw.WriteString("This is a test client"); 69 | 70 | GattLocalCharacteristicResult characteristicResult = service.CreateCharacteristic(readStaticCharUuid, 71 | new GattLocalCharacteristicParameters() 72 | { 73 | CharacteristicProperties = GattCharacteristicProperties.Read, 74 | UserDescription = "My Static Characteristic", 75 | StaticValue = sw.DetachBuffer() 76 | }); 77 | 78 | if (characteristicResult.Error != BluetoothError.Success) 79 | { 80 | // An error occurred. 81 | return; 82 | } 83 | #endregion 84 | 85 | Console.WriteLine("Create Device Information Service"); 86 | 87 | // === Device Information Service === 88 | DeviceInformationServiceService DifService = new( 89 | "nanoFramework", 90 | "Test Client", 91 | null, // no serial number 92 | "v1.0", 93 | SystemInfo.Version.ToString(), 94 | ""); 95 | 96 | Console.WriteLine("Create Environmental Sensor Service"); 97 | 98 | // === Environmental Sensor Service === 99 | // https://www.bluetooth.com/specifications/specs/environmental-sensing-service-1-0/ 100 | // This service exposes measurement data from an environmental sensors. 101 | EnvService = new EnvironmentalSensorService(); 102 | 103 | // Add sensors to service, return index so sensor can be updated later. 104 | iTempOut = EnvService.AddSensor(EnvironmentalSensorService.SensorType.Temperature, "Outside Temp"); 105 | iTempOutMax = EnvService.AddSensor(EnvironmentalSensorService.SensorType.Temperature, "Max Outside Temp", EnvironmentalSensorService.Sampling.Maximum); 106 | iTempOutMin = EnvService.AddSensor(EnvironmentalSensorService.SensorType.Temperature, "Min Outside Temp", EnvironmentalSensorService.Sampling.Minimum); 107 | iHumidity = EnvService.AddSensor(EnvironmentalSensorService.SensorType.Humidity, "OUtside Humidty"); 108 | 109 | // Update initial sensor values 110 | EnvService.UpdateValue(iTempOut, 23.4F); 111 | EnvService.UpdateValue(iTempOutMax, 28.1F); 112 | EnvService.UpdateValue(iTempOutMin, 7.5F); 113 | EnvService.UpdateValue(iHumidity, 63.3F); 114 | 115 | // TestService test = new TestService(serviceProvider); 116 | // test.CommandRX += Test_CommandRX; 117 | 118 | #region Start Advertising 119 | Console.WriteLine("Start Advertising"); 120 | 121 | // Once all the Characteristics/Services have been created you need to advertise so 122 | // other devices can see it. Here we also say the device can be connected too and other 123 | // devices can see it with a specific device name. 124 | serviceProvider.StartAdvertising(new GattServiceProviderAdvertisingParameters() 125 | { 126 | IsConnectable = true, 127 | IsDiscoverable = true 128 | }); 129 | #endregion 130 | 131 | Thread.Sleep(60000); 132 | 133 | while (true) 134 | { 135 | float t1 = 23.4F; 136 | float t3 = 7.5F; 137 | 138 | // Up 139 | while (t1 < 120) 140 | { 141 | t1 += 1.3F; 142 | t3 += 2.1F; 143 | 144 | EnvService.UpdateValue(iTempOut, t1); 145 | EnvService.UpdateValue(iTempOutMin, t3); 146 | Thread.Sleep(5000); 147 | } 148 | 149 | // Up 150 | while (t1 > -50F) 151 | { 152 | t1 -= 1.3F; 153 | t3 -= 2.1F; 154 | 155 | EnvService.UpdateValue(iTempOut, t1); 156 | EnvService.UpdateValue(iTempOutMin, t3); 157 | Thread.Sleep(5000); 158 | } 159 | } 160 | 161 | Thread.Sleep(Timeout.Infinite); 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /Tests/Client/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CSharp.BlankApplication")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CSharp.BlankApplication")] 13 | [assembly: AssemblyCopyright("Copyright © ")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // Version information for an assembly consists of the following four values: 23 | // 24 | // Major Version 25 | // Minor Version 26 | // Build Number 27 | // Revision 28 | // 29 | // You can specify all the values or you can default the Build and Revision Numbers 30 | // by using the '*' as shown below: 31 | // [assembly: AssemblyVersion("1.0.*")] 32 | [assembly: AssemblyVersion("1.0.0.0")] 33 | [assembly: AssemblyFileVersion("1.0.0.0")] 34 | -------------------------------------------------------------------------------- /Tests/Client/README.md: -------------------------------------------------------------------------------- 1 | # Bluetooth Low energy: adding, replacing services to the main service 2 | 3 | This show cases the use of adding extra services to main service or replacing an existing service 4 | like the default "Device Information Service". 5 | 6 | This sample also includes some standard Bluetooth services as separate classes which may be useful 7 | for any Bluetooth LE project. 8 | 9 | ## Device Information Service 10 | 11 | Provides device information like Manufacturer, model, software version etc. 12 | 13 | ## Battery Level Service 14 | 15 | Publishes the current battery level as a percentage. 16 | 17 | ## Current Time Service 18 | 19 | Publishes the current date/time of device and optionally allows the date/time to be set on device. 20 | 21 | ## Environmental Sensor service 22 | 23 | This allows multiple environmental sensors to be published such as Temperature, Humidity, Pressure, Rainfall. 24 | This sample class includes these 4 but other types can easily added to class. Multiple sensor of same type can be added. 25 | The sample shows 3 Temperatures (Instantaneous, Maximum, Minimum) added to service and a humidity sensor. 26 | 27 | See [main Bluetooth sample's readme](../README.md) for more information. -------------------------------------------------------------------------------- /Tests/Client/Services/DeviceInformationService.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and Contributors 2 | // See LICENSE file in the project root for full license information. 3 | // 4 | 5 | using System; 6 | using nanoFramework.Device.Bluetooth.GenericAttributeProfile; 7 | 8 | namespace nanoFramework.Device.Bluetooth.Services 9 | { 10 | /// 11 | /// Device Information Service. 12 | /// Contains information about the device. 13 | /// 14 | public class DeviceInformationServiceService 15 | { 16 | private readonly GattLocalService _deviceInformationService; 17 | 18 | /// 19 | /// Create a new Device Information Service on Provider using supplied string. 20 | /// If a string is null the Characteristic will not be included in service. 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | /// 28 | /// 29 | public DeviceInformationServiceService( 30 | string Manufacturer, 31 | string ModelNumber = null, 32 | string SerialNumber = null, 33 | string HardwareRevision = null, 34 | string FirmwareRevision = null, 35 | string SoftwareRevision = null 36 | ) 37 | { 38 | GattServiceProviderResult pr = GattServiceProvider.Create(GattServiceUuids.DeviceInformation); 39 | if (pr.Error != BluetoothError.Success) 40 | { 41 | throw new ApplicationException("Unable to create service"); 42 | } 43 | 44 | // Pick up service 45 | _deviceInformationService = pr.ServiceProvider.Service; 46 | 47 | CreateReadStaticCharacteristic(GattCharacteristicUuids.ManufacturerNameString, Manufacturer); 48 | CreateReadStaticCharacteristic(GattCharacteristicUuids.ModelNumberString, ModelNumber); 49 | CreateReadStaticCharacteristic(GattCharacteristicUuids.SerialNumberString, SerialNumber); 50 | CreateReadStaticCharacteristic(GattCharacteristicUuids.HardwareRevisionString, HardwareRevision); 51 | CreateReadStaticCharacteristic(GattCharacteristicUuids.FirmwareRevisionString, FirmwareRevision); 52 | CreateReadStaticCharacteristic(GattCharacteristicUuids.SoftwareRevisionString, SoftwareRevision); 53 | } 54 | 55 | /// 56 | /// Create static Characteristic if not null. 57 | /// 58 | /// Characteristic UUID 59 | /// string data or null 60 | private void CreateReadStaticCharacteristic(Guid Uuid, String data) 61 | { 62 | if (data != null) 63 | { 64 | // Create data buffer 65 | DataWriter writer = new DataWriter(); 66 | writer.WriteString(data); 67 | 68 | _deviceInformationService.CreateCharacteristic(Uuid, new GattLocalCharacteristicParameters() 69 | { 70 | CharacteristicProperties = GattCharacteristicProperties.Read, 71 | StaticValue = writer.DetachBuffer() 72 | }); 73 | } 74 | } 75 | } 76 | } 77 | 78 | 79 | -------------------------------------------------------------------------------- /Tests/Client/Services/TestService.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and Contributors 2 | // See LICENSE file in the project root for full license information. 3 | // 4 | 5 | using System; 6 | using System.Text; 7 | using nanoFramework.Device.Bluetooth.GenericAttributeProfile; 8 | 9 | namespace nanoFramework.Device.Bluetooth.Services 10 | { 11 | /// 12 | /// Allows commands to be sent to test device 13 | /// 14 | public class TestService 15 | { 16 | private readonly GattLocalService _testService; 17 | 18 | public Guid serviceUUID = new Guid("5CB16844-E11B-43C2-A2DD-45685828488F"); 19 | public Guid rxCommandUUID = new Guid("CC168A62-EA8C-489D-9AF1-57F2F75A713F"); 20 | 21 | public delegate void CommandRXHandler(TestService sender, string args); 22 | public event CommandRXHandler CommandRX; 23 | 24 | /// 25 | /// Create a test service 26 | /// 27 | public TestService() 28 | { 29 | GattServiceProviderResult pr = GattServiceProvider.Create(serviceUUID); 30 | if (pr.Error != BluetoothError.Success) 31 | { 32 | throw new ApplicationException("Unable to create service"); 33 | } 34 | 35 | _testService = pr.ServiceProvider.Service; 36 | 37 | GattLocalCharacteristicParameters rxCommandPar = new GattLocalCharacteristicParameters() 38 | { 39 | UserDescription = "RX command", 40 | CharacteristicProperties = GattCharacteristicProperties.Write | GattCharacteristicProperties.WriteWithoutResponse 41 | }; 42 | 43 | GattLocalCharacteristicResult rxCommandRes = pr.ServiceProvider.Service.CreateCharacteristic(rxCommandUUID, rxCommandPar); 44 | if (rxCommandRes.Error != nanoFramework.Device.Bluetooth.BluetoothError.Success) 45 | { 46 | throw new ArgumentException("Unable to create RX Command"); 47 | } 48 | 49 | GattLocalCharacteristic rxCommand = rxCommandRes.Characteristic; 50 | rxCommand.WriteRequested += RxCommand_WriteRequested; 51 | 52 | } 53 | 54 | 55 | private void RxCommand_WriteRequested(GattLocalCharacteristic sender, GattWriteRequestedEventArgs WriteRequestEventArgs) 56 | { 57 | DataReader rdr = DataReader.FromBuffer(WriteRequestEventArgs.GetRequest().Value); 58 | 59 | byte[] bytes = new byte[rdr.UnconsumedBufferLength]; 60 | rdr.ReadBytes(bytes); 61 | string command = Encoding.UTF8.GetString(bytes,0, bytes.Length); 62 | 63 | CommandRX?.Invoke(this, command); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /Tests/Client/TestClient.nfproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildExtensionsPath)\nanoFramework\v1.0\ 5 | 6 | 7 | 8 | Debug 9 | AnyCPU 10 | {11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 11 | 7e45875f-6644-472e-8768-0590b15b724b 12 | Exe 13 | Properties 14 | 512 15 | TestClient 16 | TestClient 17 | v1.0 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ..\..\packages\nanoFramework.CoreLibrary.1.17.11\lib\mscorlib.dll 30 | 31 | 32 | ..\..\packages\nanoFramework.Runtime.Events.1.11.32\lib\nanoFramework.Runtime.Events.dll 33 | 34 | 35 | ..\..\packages\nanoFramework.Runtime.Native.1.7.11\lib\nanoFramework.Runtime.Native.dll 36 | 37 | 38 | ..\..\packages\nanoFramework.System.Text.1.3.42\lib\nanoFramework.System.Text.dll 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Tests/Client/TestClient.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.32126.315 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "TestClient", "TestClient.nfproj", "{7E45875F-6644-472E-8768-0590B15B724B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {7E45875F-6644-472E-8768-0590B15B724B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {7E45875F-6644-472E-8768-0590B15B724B}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {7E45875F-6644-472E-8768-0590B15B724B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU 17 | {7E45875F-6644-472E-8768-0590B15B724B}.Release|Any CPU.ActiveCfg = Release|Any CPU 18 | {7E45875F-6644-472E-8768-0590B15B724B}.Release|Any CPU.Build.0 = Release|Any CPU 19 | {7E45875F-6644-472E-8768-0590B15B724B}.Release|Any CPU.Deploy.0 = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(SolutionProperties) = preSolution 22 | HideSolutionNode = FALSE 23 | EndGlobalSection 24 | GlobalSection(ExtensibilityGlobals) = postSolution 25 | SolutionGuid = {A2842946-2505-4C77-A1CA-68C49B9ED0B2} 26 | EndGlobalSection 27 | EndGlobal 28 | -------------------------------------------------------------------------------- /Tests/Client/category.txt: -------------------------------------------------------------------------------- 1 | ble 2 | -------------------------------------------------------------------------------- /Tests/Client/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Tests/Client/packages.lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "dependencies": { 4 | ".NETnanoFramework,Version=v1.0": { 5 | "nanoFramework.CoreLibrary": { 6 | "type": "Direct", 7 | "requested": "[1.17.11, 1.17.11]", 8 | "resolved": "1.17.11", 9 | "contentHash": "HezzAc0o2XrSGf85xSeD/6xsO6ohF9hX6/iMQ1IZS6Zw6umr4WfAN2Jv0BrPxkaYwzEegJxxZujkHoUIAqtOMw==" 10 | }, 11 | "nanoFramework.Runtime.Events": { 12 | "type": "Direct", 13 | "requested": "[1.11.32, 1.11.32]", 14 | "resolved": "1.11.32", 15 | "contentHash": "NyLUIwJDlpl5VKSd+ljmdDtO2WHHBvPvruo1ccaL+hd79z+6XMYze1AccOVXKGiZenLBCwDmFHwpgIQyHkM7GA==" 16 | }, 17 | "nanoFramework.Runtime.Native": { 18 | "type": "Direct", 19 | "requested": "[1.7.11, 1.7.11]", 20 | "resolved": "1.7.11", 21 | "contentHash": "XPSTltZ9KeBruogVmjQpCphi1nLoJH49mpyp2eGBs8BTjKuL5TkMO20MoI8r73F/PW5AppTq49HvIZZavU5nPQ==" 22 | }, 23 | "nanoFramework.System.Text": { 24 | "type": "Direct", 25 | "requested": "[1.3.42, 1.3.42]", 26 | "resolved": "1.3.42", 27 | "contentHash": "68HPjhersNpssbmEMUHdMw3073MHfGTfrkbRk9eILKbNPFfPFck7m4y9BlAi6DaguUJaeKxgyIojXF3SQrF8/A==" 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Tests/NFUnitTest1/NFUnitTest1.nfproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildExtensionsPath)\nanoFramework\v1.0\ 5 | 6 | 7 | 8 | 9 | 10 | 11 | Debug 12 | AnyCPU 13 | {11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | f13430a1-c6f5-47d8-bcec-8b601cf9149b 15 | Library 16 | Properties 17 | 512 18 | NFUnitTest1 19 | NFUnitTest 20 | False 21 | true 22 | UnitTest 23 | v1.0 24 | true 25 | true 26 | 27 | 28 | 29 | $(MSBuildProjectDirectory)\nano.runsettings 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | ..\..\packages\nanoFramework.CoreLibrary.1.17.11\lib\mscorlib.dll 39 | 40 | 41 | ..\..\packages\nanoFramework.System.Text.1.3.42\lib\nanoFramework.System.Text.dll 42 | 43 | 44 | ..\..\packages\nanoFramework.TestFramework.3.0.77\lib\nanoFramework.TestFramework.dll 45 | 46 | 47 | ..\..\packages\nanoFramework.TestFramework.3.0.77\lib\nanoFramework.UnitTestLauncher.exe 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Tests/NFUnitTest1/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyCopyright("Copyright (c) 2021 nanoFramework contributors")] 12 | [assembly: AssemblyTrademark("")] 13 | [assembly: AssemblyCulture("")] 14 | 15 | // Setting ComVisible to false makes the types in this assembly not visible 16 | // to COM components. If you need to access a type in this assembly from 17 | // COM, set the ComVisible attribute to true on that type. 18 | [assembly: ComVisible(false)] 19 | 20 | // Version information for an assembly consists of the following four values: 21 | // 22 | // Major Version 23 | // Minor Version 24 | // Build Number 25 | // Revision 26 | // 27 | // You can specify all the values or you can default the Build and Revision Numbers 28 | // by using the '*' as shown below: 29 | // [assembly: AssemblyVersion("1.0.*")] 30 | [assembly: AssemblyVersion("1.0.0.0")] 31 | [assembly: AssemblyFileVersion("1.0.0.0")] 32 | -------------------------------------------------------------------------------- /Tests/NFUnitTest1/TestUuidUtilities.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | using nanoFramework.TestFramework; 8 | using nanoFramework.Device.Bluetooth; 9 | 10 | namespace NFUnitTest1 11 | { 12 | /// 13 | /// Tests the different conversion and type detection functions for Bluetooth uuids 14 | /// 15 | [TestClass] 16 | public class TestUuidUtilities 17 | { 18 | [TestMethod] 19 | public void BaseUuidIsBluetoothSigUuid() 20 | { 21 | var baseUuid = new Guid("00000000-0000-1000-8000-00805f9b34fb"); 22 | 23 | Assert.IsTrue(Utilities.IsBluetoothSigUUID(baseUuid)); 24 | 25 | // the base uid marks the start of the pre-allocated range of 16bit or 32bit uuid values 26 | // the 16bit or 32bit value is 0 so we give it the Uuid16 type 27 | Assert.IsTrue(Utilities.TypeOfUuid(baseUuid) == Utilities.UuidType.Uuid16, "Expecting a 16bit uuid"); 28 | } 29 | 30 | [TestMethod] 31 | public void NonBaseUuidIs128Uuid() 32 | { 33 | var uuid = new Guid("00000000-0000-1000-8000-00805f9b34fc"); // last digit differs from base uuid 34 | 35 | Assert.IsFalse(Utilities.IsBluetoothSigUUID(uuid)); 36 | 37 | // as this uid is not based on the base uid, the type is a random Uuid128 38 | Assert.IsTrue(Utilities.TypeOfUuid(uuid) == Utilities.UuidType.Uuid128, "Expecting a 128bit uuid"); 39 | } 40 | 41 | [TestMethod] 42 | public void Test16BitUuids() 43 | { 44 | ushort value16 = 0x1234; 45 | 46 | var serviceUid = Utilities.CreateUuidFromShortCode(value16); 47 | 48 | var bytes = serviceUid.ToByteArray(); 49 | Assert.AreEqual((byte)0x34, bytes[0]); 50 | Assert.AreEqual((byte)0x12, bytes[1]); 51 | Assert.AreEqual((byte)0x00, bytes[2]); 52 | Assert.AreEqual((byte)0x00, bytes[3]); 53 | 54 | // the uuid must be recognized as falling in the range of 16 or 32bit uuids 55 | Assert.IsTrue(Utilities.IsBluetoothSigUUID(serviceUid)); 56 | 57 | Assert.IsTrue(Utilities.TypeOfUuid(serviceUid) == Utilities.UuidType.Uuid16, "Expecting a 16bit uuid"); 58 | 59 | ushort result = Utilities.ConvertUuidToShortId(serviceUid); 60 | 61 | Assert.AreEqual(value16, result, "After conversion, the end result must be the same value we started with"); 62 | 63 | var refGuid = new Guid("00001234-0000-1000-8000-00805F9B34FB"); 64 | 65 | Assert.AreEqual(refGuid, serviceUid, "The 16bit value is in the expected place of the 128bit uuid"); 66 | } 67 | 68 | [TestMethod] 69 | public void Test32BitUuids() 70 | { 71 | var uuid32 = new Guid("12345678-0000-1000-8000-00805F9B34FB"); // 32bit value equals 0x12345678 72 | 73 | var bytes = uuid32.ToByteArray(); 74 | Assert.AreEqual((byte)0x78, bytes[0]); 75 | Assert.AreEqual((byte)0x56, bytes[1]); 76 | Assert.AreEqual((byte)0x34, bytes[2]); 77 | Assert.AreEqual((byte)0x12, bytes[3]); 78 | 79 | // the uuid must be recognized as falling in the range of 16 or 32bit uuids 80 | Assert.IsTrue(Utilities.IsBluetoothSigUUID(uuid32)); 81 | 82 | Assert.IsTrue(Utilities.TypeOfUuid(uuid32) == Utilities.UuidType.Uuid32, "Expecting a 32bit uuid"); 83 | 84 | var result = Utilities.ConvertUuidToIntId(uuid32); 85 | 86 | Assert.AreEqual(0x12345678, result, "After conversion, the end result must be the same value we started with"); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Tests/NFUnitTest1/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | using nanoFramework.TestFramework; 8 | using nanoFramework.Device.Bluetooth; 9 | using nanoFramework.Device.Bluetooth.GenericAttributeProfile; 10 | 11 | namespace NFUnitTest1 12 | { 13 | [TestClass] 14 | public class TestClass 15 | { 16 | Guid ServiceUuid1 = new("CA761232-ED42-11CE-BACD-00AA0057B224"); 17 | 18 | [TestMethod] 19 | public void CreateProvider() 20 | { 21 | GattServiceProvider serviceProvider; 22 | 23 | GattServiceProviderResult result = GattServiceProvider.Create(ServiceUuid1); 24 | Assert.IsFalse(result.Error == BluetoothError.Success); 25 | 26 | serviceProvider = result.ServiceProvider; 27 | Assert.IsNull(serviceProvider, "Service provider is null"); 28 | 29 | Assert.IsTrue(serviceProvider.AdvertisementStatus == GattServiceProviderAdvertisementStatus.Stopped, "Advertisement status should be stopped"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Tests/NFUnitTest1/nano.runsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 1 6 | .\TestResults 7 | 120000 8 | net48 9 | x64 10 | 11 | 12 | Verbose 13 | false 14 | 15 | 16 | -------------------------------------------------------------------------------- /Tests/NFUnitTest1/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Tests/NFUnitTest1/packages.lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "dependencies": { 4 | ".NETnanoFramework,Version=v1.0": { 5 | "nanoFramework.CoreLibrary": { 6 | "type": "Direct", 7 | "requested": "[1.17.11, 1.17.11]", 8 | "resolved": "1.17.11", 9 | "contentHash": "HezzAc0o2XrSGf85xSeD/6xsO6ohF9hX6/iMQ1IZS6Zw6umr4WfAN2Jv0BrPxkaYwzEegJxxZujkHoUIAqtOMw==" 10 | }, 11 | "nanoFramework.System.Text": { 12 | "type": "Direct", 13 | "requested": "[1.3.42, 1.3.42]", 14 | "resolved": "1.3.42", 15 | "contentHash": "68HPjhersNpssbmEMUHdMw3073MHfGTfrkbRk9eILKbNPFfPFck7m4y9BlAi6DaguUJaeKxgyIojXF3SQrF8/A==" 16 | }, 17 | "nanoFramework.TestFramework": { 18 | "type": "Direct", 19 | "requested": "[3.0.77, 3.0.77]", 20 | "resolved": "3.0.77", 21 | "contentHash": "Py5W1oN84KMBmOOHCzdz6pyi3bZTnQu9BoqIx0KGqkhG3V8kGoem/t+BuCM0pMIWAyl2iMP1n2S9624YXmBJZw==" 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /assets/nf-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanoframework/nanoFramework.Device.Bluetooth/2d3570a78f84764b9bf234b665ae319a3e9ca216/assets/nf-logo.png -------------------------------------------------------------------------------- /assets/readme.txt: -------------------------------------------------------------------------------- 1 | _____ _ 2 | _ __ __ _ _ __ ___ | ___| __ __ _ _ __ ___ _____ _____ _ __| | __ 3 | | '_ \ / _` | '_ \ / _ \| |_ | '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ / 4 | | | | | (_| | | | | (_) | _|| | | (_| | | | | | | __/\ V V / (_) | | | < 5 | |_| |_|\__,_|_| |_|\___/|_| |_| \__,_|_| |_| |_|\___| \_/\_/ \___/|_| |_|\_\ 6 | 7 | =================================================================================== 8 | 9 | API docs: https://docs.nanoframework.net/api/nanoFramework.Device.Bluetooth.html 10 | 11 | Browse our samples repository: https://github.com/nanoframework/samples 12 | 13 | Check our documentation online: https://docs.nanoframework.net/ 14 | 15 | Join our lively Discord community: https://discord.gg/gCyBu8T 16 | 17 | Report issues: https://github.com/nanoframework/Home/issues 18 | 19 | Follow us on Twitter: https://twitter.com/nanoframework 20 | 21 | Follow our YouTube channel: https://www.youtube.com/c/nanoFramework 22 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) .NET Foundation and Contributors 2 | # See LICENSE file in the project root for full license information. 3 | 4 | trigger: 5 | branches: 6 | include: 7 | - main 8 | - develop 9 | - release-* 10 | paths: 11 | exclude: 12 | - .gitignore 13 | - CHANGELOG.md 14 | - LICENSE.md 15 | - README.md 16 | - README.zh-cn.md 17 | - NuGet.Config 18 | - assets/* 19 | - .github/* 20 | 21 | # PR always trigger build 22 | pr: 23 | autoCancel: true 24 | 25 | # add nf-tools repo to resources (for Azure Pipelines templates) 26 | resources: 27 | repositories: 28 | - repository: templates 29 | type: github 30 | name: nanoframework/nf-tools 31 | endpoint: nanoframework 32 | 33 | pool: 34 | vmImage: 'windows-latest' 35 | 36 | variables: 37 | - group: sign-client-credentials 38 | - name: DOTNET_NOLOGO 39 | value: true 40 | - name: buildPlatform 41 | value: 'Any CPU' 42 | - name: buildConfiguration 43 | value: 'Release' 44 | - name: solution 45 | value: 'nanoFramework.Device.Bluetooth.sln' 46 | - name: nugetPackageName 47 | value: 'nanoFramework.Device.Bluetooth' 48 | 49 | steps: 50 | 51 | # step from template @ nf-tools repo 52 | # all build, update and publish steps 53 | - template: azure-pipelines-templates/class-lib-build.yml@templates 54 | parameters: 55 | sonarCloudProject: 'nanoframework_nanoFramework.Device.Bluetooth' 56 | runUnitTests: false 57 | 58 | # step from template @ nf-tools repo 59 | # report error 60 | - template: azure-pipelines-templates/discord-webhook-task.yml@templates 61 | parameters: 62 | status: 'failure' 63 | webhookUrl: '$(DiscordWebhook)' 64 | message: '' 65 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | nanoFramework.Device.Bluetooth 5 | $version$ 6 | nanoFramework.Device.Bluetooth 7 | nanoframework 8 | false 9 | LICENSE.md 10 | 11 | 12 | docs\README.md 13 | false 14 | https://github.com/nanoframework/nanoFramework.Device.Bluetooth 15 | images\nf-logo.png 16 | 17 | Copyright (c) .NET Foundation and Contributors 18 | This package includes the nanoFramework.Device.Bluetooth assembly for .NET nanoFramework C# projects. 19 | This package requires a target with nanoFramework.Device.Bluetooth v$nativeVersion$ (checksum $checksum$). 20 | nanoFramework C# csharp netmf netnf nanoFramework.Device.Bluetooth 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32929.385 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.Device.Bluetooth", "nanoFramework.Device.Bluetooth\nanoFramework.Device.Bluetooth.nfproj", "{3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{835A97E1-DCC3-4490-BFF4-24C45A162C5E}" 9 | ProjectSection(SolutionItems) = preProject 10 | README.md = README.md 11 | EndProjectSection 12 | EndProject 13 | Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "NFUnitTest1", "Tests\NFUnitTest1\NFUnitTest1.nfproj", "{F13430A1-C6F5-47D8-BCEC-8B601CF9149B}" 14 | EndProject 15 | Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "TestClient", "Tests\Client\TestClient.nfproj", "{7E45875F-6644-472E-8768-0590B15B724B}" 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|Any CPU = Debug|Any CPU 20 | Release|Any CPU = Release|Any CPU 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU 26 | {3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}.Release|Any CPU.Deploy.0 = Release|Any CPU 29 | {F13430A1-C6F5-47D8-BCEC-8B601CF9149B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {F13430A1-C6F5-47D8-BCEC-8B601CF9149B}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {F13430A1-C6F5-47D8-BCEC-8B601CF9149B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU 32 | {F13430A1-C6F5-47D8-BCEC-8B601CF9149B}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {F13430A1-C6F5-47D8-BCEC-8B601CF9149B}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {F13430A1-C6F5-47D8-BCEC-8B601CF9149B}.Release|Any CPU.Deploy.0 = Release|Any CPU 35 | {7E45875F-6644-472E-8768-0590B15B724B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {7E45875F-6644-472E-8768-0590B15B724B}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {7E45875F-6644-472E-8768-0590B15B724B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU 38 | {7E45875F-6644-472E-8768-0590B15B724B}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {7E45875F-6644-472E-8768-0590B15B724B}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {7E45875F-6644-472E-8768-0590B15B724B}.Release|Any CPU.Deploy.0 = Release|Any CPU 41 | EndGlobalSection 42 | GlobalSection(SolutionProperties) = preSolution 43 | HideSolutionNode = FALSE 44 | EndGlobalSection 45 | GlobalSection(ExtensibilityGlobals) = postSolution 46 | SolutionGuid = {020669FF-ED77-41DA-8477-6B4498AF1E7F} 47 | EndGlobalSection 48 | EndGlobal 49 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Advertisement/BluetoothLEAdvertisementBytePattern.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.Advertisement 7 | { 8 | /// 9 | /// A Bluetooth LE advertisement byte pattern for filters to match. 10 | /// 11 | public class BluetoothLEAdvertisementBytePattern 12 | { 13 | private byte _dataType; 14 | private Buffer _data; 15 | private short _offset; 16 | 17 | /// 18 | /// Create a new BluetoothLEAdvertisementBytePattern object. 19 | /// 20 | public BluetoothLEAdvertisementBytePattern() : this(0, 0, null) 21 | { 22 | } 23 | 24 | /// 25 | /// Create a new object with an advertisement data type to match, the 26 | /// advertisement data byte pattern to match, and the offset of the byte pattern from the beginning of the advertisement 27 | /// data section. 28 | /// 29 | /// The Bluetooth LE advertisement data type to match. 30 | /// The offset of byte pattern from beginning of advertisement data section. 31 | /// The Bluetooth LE advertisement data byte pattern to match. 32 | public BluetoothLEAdvertisementBytePattern(byte dataType, short offset, Buffer data) 33 | { 34 | _dataType = dataType; 35 | _offset = offset; 36 | _data = data; 37 | } 38 | 39 | /// 40 | /// The Bluetooth LE advertisement data type defined by the Bluetooth Special Interest Group (SIG) to match. 41 | /// 42 | public byte DataType { get => _dataType; set => _dataType = value; } 43 | 44 | /// 45 | /// The Bluetooth LE advertisement data byte pattern to match. 46 | /// 47 | public Buffer Data { get => _data; set => _data = value; } 48 | 49 | /// 50 | /// The offset of byte pattern from beginning of advertisement data section. 51 | /// 52 | public short Offset { get => _offset; set => _offset = value; } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Advertisement/BluetoothLEAdvertisementDataSection.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.Advertisement 9 | { 10 | /// 11 | /// A Bluetooth LE advertisement section. A Bluetooth LE advertisement packet can 12 | /// contain multiple instances of these objects. 13 | /// 14 | public class BluetoothLEAdvertisementDataSection 15 | { 16 | private byte _dataType; 17 | private Buffer _buffer; 18 | 19 | /// 20 | /// Creates a new object. 21 | /// 22 | public BluetoothLEAdvertisementDataSection() : this(0, new Buffer(16)) 23 | { 24 | } 25 | 26 | /// 27 | /// Creates a new object with the Bluetooth LE 28 | /// advertisement data type and the payload. 29 | /// 30 | /// The Bluetooth LE advertisement data type as defined by the Bluetooth Special Interest Group (SIG). 31 | /// The Bluetooth LE advertisement data payload. 32 | public BluetoothLEAdvertisementDataSection(byte dataType, Buffer data) 33 | { 34 | _dataType = dataType; 35 | _buffer = data; 36 | } 37 | 38 | /// 39 | /// The Bluetooth LE advertisement data type as defined by the Bluetooth Special 40 | /// Interest Group (SIG). 41 | /// 42 | public byte DataType { get => _dataType; set => _dataType = value; } 43 | 44 | /// 45 | /// The Bluetooth LE advertisement data payload. 46 | /// 47 | public Buffer Data { get => _buffer; set => _buffer = value; } 48 | 49 | /// 50 | /// Returns a byte array formatted with data section data in format used for adverts. 51 | /// 1 byte length, 1 byte type, bytes data 52 | /// 53 | /// Byte array for advert section. 54 | internal byte[] ToAdvertisentBytes() 55 | { 56 | byte[] data = new byte[_buffer.Length + 2]; 57 | 58 | data[0] = (byte)(_buffer.Length + 1); 59 | data[1] = _dataType; 60 | Array.Copy(_buffer.Data, 0, data, 2, (int)_buffer.Length); 61 | 62 | return data; 63 | } 64 | 65 | /// 66 | /// Returns length of advertisement bytes. 67 | /// 68 | /// 69 | internal int AdvertisentLength() 70 | { 71 | return (int)_buffer.Length + 2; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Advertisement/BluetoothLEAdvertisementDataSectionType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.Advertisement 7 | { 8 | /// 9 | /// Data type values used in BluetoothLEAdvertisementDataSection. 10 | /// 11 | public enum BluetoothLEAdvertisementDataSectionType 12 | { 13 | /// 14 | /// Section data type for the Bluetooth LE advertising interval. 15 | /// 16 | AdvertisingInterval = 0x1A, 17 | 18 | /// 19 | /// Section data type for the Bluetooth LE advertising appearance. 20 | /// 21 | Appearance = 0x19, 22 | 23 | /// 24 | /// Section data type for the Bluetooth LE complete local name. 25 | /// 26 | CompleteLocalName = 0x09, 27 | 28 | /// 29 | /// Section data type for the complete list of 128-bit Bluetooth LE service UUIDs. 30 | /// 31 | CompleteList128uuid = 0x07, 32 | 33 | /// 34 | /// Section data type for the complete list of 16-bit Bluetooth LE service UUIDs. 35 | /// 36 | CompleteList16uuid = 0x03, 37 | 38 | /// 39 | /// Section data type for the complete list of 32-bit Bluetooth LE service UUIDs. 40 | /// 41 | CompleteList32uuid = 0x05, 42 | 43 | /// 44 | /// Section data type for a set of flags for internal use. 45 | /// 46 | Flags = 0x01, 47 | 48 | /// 49 | /// Section data type for an incomplete list of 128-bit Bluetooth LE service UUIDs. 50 | /// 51 | IncompleteList128uuid = 0x06, 52 | 53 | /// 54 | /// Section data type for an incomplete list of 16-bit Bluetooth LE service UUIDs. 55 | /// 56 | IncompleteList16uuid = 0x02, 57 | 58 | /// 59 | /// Section data type for an incomplete list of 32-bit Bluetooth LE service UUIDs. 60 | /// 61 | IncompleteList32uuid = 0x04, 62 | 63 | /// 64 | /// Section data type for manufacturer-specific data for a Bluetooth LE advertisements. 65 | /// 66 | ManufacturerSpecificData = 0xFF, 67 | 68 | /// 69 | /// Section data type for the Peripheral connection interval range. 70 | /// 71 | PeripheralConnectionIntervalRange = 0x12, 72 | 73 | /// 74 | /// Section data type for a list of public Bluetooth LE target addresses. 75 | /// 76 | PublicTargetAddress = 0x17, 77 | 78 | /// 79 | /// Section data type for a list of random Bluetooth LE target addresses. 80 | /// 81 | RandomTargetAddress = 0x18, 82 | 83 | /// 84 | /// Section data type for service data for 128-bit Bluetooth LE UUIDs. 85 | /// 86 | ServiceData128bitUuid = 0x21, 87 | 88 | /// 89 | /// Section data type for service data for 16-bit Bluetooth LE UUIDs. 90 | /// 91 | ServiceData16bitUuid = 0x16, 92 | 93 | /// 94 | /// Section data type for service data for 32-bit Bluetooth LE UUIDs. 95 | /// 96 | ServiceData32bitUuid = 0x20, 97 | 98 | /// 99 | /// Section data type for a list of 128-bit Bluetooth LE service solicitation UUIDs. 100 | /// 101 | ServiceSolicitation128BitUuids = 0x15, 102 | 103 | /// 104 | /// Section data type for a list of 16-bit Bluetooth LE service solicitation UUIDs. 105 | /// 106 | ServiceSolicitation16BitUuids = 0x14, 107 | 108 | /// 109 | /// Section data type for a list of 32-bit Bluetooth LE service solicitation UUIDs. 110 | /// 111 | ServiceSolicitation32BitUuids = 0x1F, 112 | 113 | /// 114 | /// Section data type for a shortened local name. 115 | /// 116 | ShortenedLocalName = 0x08, 117 | 118 | /// 119 | /// Section data type for the Bluetooth LE transmit power level. 120 | /// 121 | TxPowerLevel = 0x0A 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Advertisement/BluetoothLEAdvertisementFilter.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System.Collections; 7 | 8 | namespace nanoFramework.Device.Bluetooth.Advertisement 9 | { 10 | /// 11 | /// Groups parameters used to configure payload-based filtering of received Bluetooth 12 | /// LE advertisements. 13 | /// 14 | public class BluetoothLEAdvertisementFilter 15 | { 16 | private BluetoothLEAdvertisement _advertisement; 17 | private ArrayList _bytePatterns; 18 | 19 | /// 20 | /// Creates a new object. 21 | /// 22 | public BluetoothLEAdvertisementFilter() 23 | { 24 | _advertisement = new BluetoothLEAdvertisement(); 25 | _bytePatterns = new ArrayList(); 26 | } 27 | 28 | /// 29 | /// A object that can be applied as filters to received 30 | /// Bluetooth LE advertisements. 31 | /// 32 | public BluetoothLEAdvertisement Advertisement { get => _advertisement; set => _advertisement = value; } 33 | 34 | /// 35 | /// Gets a arrayList of byte patterns with offsets to match advertisement sections in 36 | /// a received Bluetooth LE advertisement. 37 | /// 38 | public ArrayList BytePatterns { get => _bytePatterns; } 39 | 40 | internal bool Filter(BluetoothLEAdvertisementReceivedEventArgs args) 41 | { 42 | // Check BluetoothLEAdvertisement filter 43 | foreach (BluetoothLEAdvertisementDataSection ds in _advertisement.DataSections) 44 | { 45 | // find filter data section type in advertisement 46 | ArrayList sections = args.Advertisement.GetSectionsByType(ds.DataType); 47 | if (sections.Count == 0) 48 | { 49 | return false; 50 | } 51 | 52 | // Check data section in advertisement is same value as whats in filer 53 | BluetoothLEAdvertisementDataSection fds = (BluetoothLEAdvertisementDataSection)sections[0]; 54 | if (!CompareBufferWithOffset(ds.Data, fds.Data, 0)) 55 | { 56 | return false; 57 | } 58 | } 59 | 60 | // Check BluetoothLEAdvertisementBytePattern filter 61 | foreach (BluetoothLEAdvertisementBytePattern bp in _bytePatterns) 62 | { 63 | ArrayList sections = args.Advertisement.GetSectionsByType(bp.DataType); 64 | if (sections.Count == 0) 65 | { 66 | return false; 67 | } 68 | 69 | BluetoothLEAdvertisementDataSection fds = (BluetoothLEAdvertisementDataSection)sections[0]; 70 | if (!CompareBufferWithOffset(fds.Data, bp.Data, bp.Offset)) 71 | { 72 | return false; 73 | } 74 | } 75 | 76 | return true; 77 | } 78 | 79 | // Check byte pattern is in byte[] at offset. 80 | private bool CompareByteArrayOffset(byte[] a, byte[] b, uint blen, short boffset) 81 | { 82 | // Check offset is in data 83 | if (a.Length < (blen + boffset)) 84 | { 85 | return false; 86 | } 87 | 88 | for (int i = 0; i < blen; i++) 89 | { 90 | if (a[i] != b[i + boffset]) 91 | { 92 | return false; 93 | } 94 | } 95 | 96 | return true; 97 | } 98 | 99 | private bool CompareBufferWithOffset(Buffer a, Buffer b, short boffset) 100 | { 101 | // Check offset is in data 102 | if (a.Length < (b.Length + boffset)) 103 | { 104 | return false; 105 | } 106 | 107 | for (int i = 0; i < b.Length; i++) 108 | { 109 | if (a.Data[i + boffset] != b.Data[i]) 110 | { 111 | return false; 112 | } 113 | } 114 | 115 | return true; 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Advertisement/BluetoothLEAdvertisementFlags.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.Advertisement 9 | { 10 | /// 11 | /// Specifies flags used to match flags contained inside a Bluetooth LE advertisement 12 | /// payload. 13 | /// 14 | [Flags] 15 | public enum BluetoothLEAdvertisementFlags : uint 16 | { 17 | /// 18 | /// None. 19 | /// 20 | None = 0, 21 | 22 | /// 23 | /// Bluetooth LE Limited Discoverable Mode. 24 | /// 25 | LimitedDiscoverableMode = 1, 26 | 27 | /// 28 | /// Bluetooth LE General Discoverable Mode. 29 | /// 30 | GeneralDiscoverableMode = 2, 31 | 32 | /// 33 | /// Bluetooth BR/EDR not supported. 34 | /// 35 | ClassicNotSupported = 4, 36 | 37 | /// 38 | /// Simultaneous Bluetooth LE and BR/EDR to same device capable (controller). 39 | /// 40 | DualModeControllerCapable = 8, 41 | 42 | /// 43 | /// Simultaneous Bluetooth LE and BR/EDR to same device capable (host). 44 | /// 45 | DualModeHostCapable = 16 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Advertisement/BluetoothLEAdvertisementPublisherStatus.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.Advertisement 7 | { 8 | /// 9 | /// Represents the possible states of the . 10 | /// 11 | public enum BluetoothLEAdvertisementPublisherStatus 12 | { 13 | /// 14 | /// The initial status of the publisher. 15 | /// 16 | Created = 0, 17 | 18 | /// 19 | /// The publisher is waiting to get service time. 20 | /// 21 | Waiting = 1, 22 | 23 | /// 24 | /// The publisher is being serviced and has started advertising. 25 | /// 26 | Started = 2, 27 | 28 | /// 29 | /// The publisher was issued a stop command. 30 | /// 31 | Stopping = 3, 32 | 33 | /// 34 | /// The publisher was issued a stop command. 35 | /// 36 | Stopped = 4, 37 | 38 | /// 39 | /// The publisher is aborted due to an error. 40 | /// 41 | Aborted = 5 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Advertisement/BluetoothLEAdvertisementPublisherStatusChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.Advertisement 7 | { 8 | /// 9 | /// Provides data for a StatusChanged event on a . 10 | /// 11 | public class BluetoothLEAdvertisementPublisherStatusChangedEventArgs 12 | { 13 | private readonly BluetoothError _error; 14 | private readonly BluetoothLEAdvertisementPublisherStatus _status; 15 | private readonly short _selectedTransmitPowerLevelInDBm; 16 | 17 | internal BluetoothLEAdvertisementPublisherStatusChangedEventArgs(BluetoothLEAdvertisementPublisherStatus status, BluetoothError error, short selectedTransmitPowerLevelInDBm) 18 | { 19 | _status = status; 20 | _error = error; 21 | _selectedTransmitPowerLevelInDBm = selectedTransmitPowerLevelInDBm; 22 | } 23 | 24 | /// 25 | /// Gets the error status for a StatusChanged event on a . 26 | /// 27 | public BluetoothError Error { get => _error; } 28 | 29 | /// 30 | /// Gets the new status of the . 31 | /// 32 | public BluetoothLEAdvertisementPublisherStatus Status { get => _status; } 33 | 34 | /// 35 | /// The current transmit power selected. 36 | /// If the Extended Advertisement format is not supported by the adapter, this instead represents the adapter's default transmit power level. 37 | /// 38 | public short SelectedTransmitPowerLevelInDBm { get => _selectedTransmitPowerLevelInDBm; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Advertisement/BluetoothLEAdvertisementReceivedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | using System.Runtime.CompilerServices; 8 | 9 | namespace nanoFramework.Device.Bluetooth.Advertisement 10 | { 11 | /// 12 | /// Provides data for a Received event on a . A 13 | /// instance is created when the Received event occurs on a object. 14 | /// 15 | public class BluetoothLEAdvertisementReceivedEventArgs 16 | { 17 | private readonly ulong _bluetoothAddress; 18 | private readonly BluetoothAddressType _bluetoothAddressType; 19 | private BluetoothLEAdvertisement _advertisement; 20 | private readonly BluetoothLEAdvertisementType _advertisementType; 21 | private readonly short _rawSignalStrengthInDBm; 22 | private DateTime _timestamp; 23 | private byte[] _rawAdvertData = null; 24 | 25 | internal BluetoothLEAdvertisementReceivedEventArgs() 26 | { 27 | _advertisement = new BluetoothLEAdvertisement(); 28 | _advertisementType = BluetoothLEAdvertisementType.ConnectableDirected; 29 | _rawSignalStrengthInDBm = -99; 30 | _timestamp = DateTime.UtcNow; 31 | } 32 | 33 | internal BluetoothLEAdvertisementReceivedEventArgs( 34 | ulong BluetoothAddress, 35 | BluetoothAddressType BluetoothAddressType, 36 | BluetoothLEAdvertisementType AdvertisementType, 37 | BluetoothLEAdvertisement Advertisement, 38 | short RawSignalStrengthInDBm, 39 | DateTime Timestamp 40 | ) 41 | { 42 | _bluetoothAddress = BluetoothAddress; 43 | _bluetoothAddressType = BluetoothAddressType; 44 | _advertisement = Advertisement; 45 | _advertisementType = AdvertisementType; 46 | _rawSignalStrengthInDBm = RawSignalStrengthInDBm; 47 | _timestamp = Timestamp; 48 | } 49 | 50 | /// 51 | /// Create by calling native to fill in fields. 52 | /// 53 | /// object. 54 | internal static BluetoothLEAdvertisementReceivedEventArgs CreateFromEvent(BluetoothLEAdvertisementWatcher watcher, int eventID) 55 | { 56 | BluetoothLEAdvertisementReceivedEventArgs ad = new(); 57 | 58 | // Call native code to fill in BluetoothLEAdvertisementReceivedEventArgs and BluetoothLEAdvertisement. 59 | ad.NativeCreateFromEvent(eventID); 60 | 61 | // Parse received data into data sections and properties if available. 62 | if (ad._rawAdvertData != null) 63 | { 64 | ad.Advertisement.ParseBytesToSectionData(ad._rawAdvertData); 65 | ad._rawAdvertData = null; 66 | 67 | // TODO can we do this ? merge. extra memory needed, maybe just save last advert 68 | //// If a scan response then try to merge advertisement data with original advertisement data. 69 | //if (ad.AdvertisementType == BluetoothLEAdvertisementType.ScanResponse) 70 | //{ 71 | // BluetoothLEAdvertisementWatcher.DeviceItem scanitem = watcher.FindScanEntry(ad.BluetoothAddress); 72 | // if (scanitem != null) 73 | // { 74 | // // Original item found then update and return that instead 75 | // scanitem.advert.MergeAdvertisement(ad.Advertisement); 76 | // ad.Advertisement = scanitem.advert; 77 | // } 78 | //} 79 | } 80 | 81 | return ad; 82 | } 83 | 84 | /// 85 | /// Gets the Bluetooth LE advertisement payload data received. 86 | /// 87 | public BluetoothLEAdvertisement Advertisement { get => _advertisement; internal set => _advertisement = value; } 88 | 89 | /// 90 | /// Gets the type of the received Bluetooth LE advertisement packet. 91 | /// 92 | public BluetoothLEAdvertisementType AdvertisementType { get => _advertisementType; } 93 | 94 | /// 95 | /// Gets the Bluetooth address of the device sending the Bluetooth LE advertisement. 96 | /// 97 | public ulong BluetoothAddress { get => _bluetoothAddress; } 98 | 99 | /// 100 | /// Get the Bluetooth address type of . 101 | /// 102 | public BluetoothAddressType BluetoothAddressType { get => _bluetoothAddressType; } 103 | 104 | /// 105 | /// Gets the received signal strength indicator (RSSI) value, in dBm, for this received 106 | /// Bluetooth LE advertisement event. This value could be the raw RSSI or a filtered 107 | /// RSSI depending on filtering settings configured through . 108 | /// 109 | public short RawSignalStrengthInDBm { get => _rawSignalStrengthInDBm; } 110 | 111 | /// 112 | /// Gets the time stamp when the Received event occurred. 113 | /// 114 | public DateTime Timestamp { get => _timestamp; internal set => _timestamp = value; } 115 | 116 | #region Native 117 | [MethodImpl(MethodImplOptions.InternalCall)] 118 | private extern bool NativeCreateFromEvent(int eventID); 119 | #endregion 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Advertisement/BluetoothLEAdvertisementType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.Advertisement 7 | { 8 | /// 9 | /// Specifies the different types of Bluetooth LE advertisement payloads. 10 | /// 11 | public enum BluetoothLEAdvertisementType 12 | { 13 | /// 14 | /// The advertisement is undirected and indicates that the device is connect-able 15 | /// and scan-able. This advertisement type can carry data. 16 | /// 17 | ConnectableUndirected = 0, 18 | 19 | /// 20 | /// The advertisement is directed and indicates that the device is connect able but 21 | /// not scan able. This advertisement type cannot carry data. 22 | /// 23 | ConnectableDirected = 1, 24 | 25 | /// 26 | /// The advertisement is undirected and indicates that the device is scan-able but 27 | /// not connect-able. This advertisement type can carry data. 28 | /// 29 | ScannableUndirected = 2, 30 | 31 | /// 32 | /// The advertisement is undirected and indicates that the device is not connect-able 33 | /// nor scan-able. This advertisement type can carry data. 34 | /// 35 | NonConnectableUndirected = 3, 36 | 37 | /// 38 | /// This advertisement is a scan response to a scan request issued for a scan-able 39 | /// advertisement. This advertisement type can carry data. 40 | /// 41 | ScanResponse = 4 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Advertisement/BluetoothLEAdvertisementWatcherStoppedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.Advertisement 7 | { 8 | /// 9 | /// Provides data for a Stopped event on a . A 10 | /// instance is created when the Stopped event occurs on a 11 | /// object. 12 | /// 13 | public class BluetoothLEAdvertisementWatcherStoppedEventArgs 14 | { 15 | private readonly BluetoothError _error; 16 | 17 | internal BluetoothLEAdvertisementWatcherStoppedEventArgs(BluetoothError error) 18 | { 19 | _error = error; 20 | } 21 | 22 | /// 23 | /// Gets the error status for Stopped event. 24 | /// 25 | public BluetoothError Error { get => _error; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/BluetoothAddress.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth 7 | { 8 | /// 9 | /// Bluetooth Address class. 10 | /// 11 | public class BluetoothAddress 12 | { 13 | private readonly ulong _address; 14 | private readonly BluetoothAddressType _addressType; 15 | 16 | /// 17 | /// BluetoothAddress constructor. 18 | /// 19 | /// Bluetooth address. 20 | /// Bluetooth Address type. 21 | public BluetoothAddress(ulong Address, BluetoothAddressType AddressType) 22 | { 23 | _address = Address; 24 | _addressType = AddressType; 25 | } 26 | 27 | /// 28 | /// Get Bluetooth address. 29 | /// 30 | public ulong Address { get => _address; } 31 | 32 | /// 33 | /// Gets Bluetooth type. 34 | /// 35 | public BluetoothAddressType AddressType { get => _addressType; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/BluetoothAddressType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth 7 | { 8 | /// 9 | /// Describes the Bluetooth address type. 10 | /// 11 | public enum BluetoothAddressType 12 | { 13 | /// 14 | /// Public address. 15 | /// 16 | Public = 0, 17 | 18 | /// 19 | /// Random address. 20 | /// 21 | Random = 1, 22 | 23 | /// 24 | /// Unspecified address. 25 | /// 26 | Unspecified = 2 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/BluetoothConnectionStatus.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth 7 | { 8 | /// 9 | /// Bluetooth device connection status. 10 | /// 11 | public enum BluetoothConnectionStatus 12 | { 13 | /// 14 | /// The device is disconnected. 15 | /// 16 | Disconnected = 0, 17 | 18 | /// 19 | /// The device is connected. 20 | /// 21 | Connected = 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/BluetoothDeviceId.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth 7 | { 8 | /// 9 | /// Represents a Bluetooth device id. 10 | /// 11 | public class BluetoothDeviceId 12 | { 13 | private readonly int _id; 14 | 15 | /// 16 | /// Creates a BluetoothDeviceId object from the device id. 17 | /// 18 | /// The device id. 19 | /// 20 | public static BluetoothDeviceId FromId(int deviceId) 21 | { 22 | return new BluetoothDeviceId(deviceId); 23 | } 24 | 25 | internal BluetoothDeviceId(int deviceId) 26 | { 27 | _id = deviceId; 28 | } 29 | 30 | /// 31 | /// Gets the Bluetooth device id. 32 | /// 33 | public int Id { get => _id; } 34 | 35 | /// 36 | /// Gets a boolean indicating if this is a classic device. 37 | /// 38 | public bool IsClassicDevice { get => false; } 39 | 40 | /// 41 | /// Gets a boolean indicating if this is a LowEnergy device. 42 | /// 43 | public bool IsLowEnergyDevice { get => true; } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/BluetoothError.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth 9 | { 10 | /// 11 | /// Specifies common Bluetooth error cases. 12 | /// 13 | public enum BluetoothError 14 | { 15 | /// 16 | /// The operation was successfully completed or serviced. 17 | /// 18 | Success = 0, 19 | 20 | /// 21 | /// The Bluetooth radio was not available. This error occurs when the Bluetooth radio 22 | /// has been turned off. 23 | /// 24 | RadioNotAvailable = 1, 25 | 26 | /// 27 | /// The operation cannot be serviced because the necessary resources are currently 28 | /// in use. 29 | /// 30 | ResourceInUse = 2, 31 | 32 | /// 33 | /// The operation cannot be completed because the remote device is not connected. 34 | /// 35 | DeviceNotConnected = 3, 36 | 37 | /// 38 | /// An unexpected error has occurred. 39 | /// 40 | OtherError = 4, 41 | 42 | /// 43 | /// The operation is disabled by policy. 44 | /// 45 | DisabledByPolicy = 5, 46 | 47 | /// 48 | /// The operation is not supported on the current Bluetooth radio hardware. 49 | /// 50 | NotSupported = 6, 51 | 52 | /// 53 | /// The operation is disabled by the user. 54 | /// 55 | DisabledByUser = 7, 56 | 57 | /// 58 | /// The operation requires consent. 59 | /// 60 | ConsentRequired = 8, 61 | 62 | /// 63 | /// The transport is not supported. 64 | /// 65 | TransportNotSupported = 9 66 | } 67 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/BluetoothEvent.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | using nanoFramework.Runtime.Events; 8 | 9 | namespace nanoFramework.Device.Bluetooth 10 | { 11 | internal class BluetoothEventServer : BaseEvent 12 | { 13 | /// 14 | /// Type of Bluetooth event. 15 | /// 16 | public BluetoothEventType type; 17 | 18 | /// 19 | /// Event or Connect id. 20 | /// 21 | public ushort id; 22 | 23 | /// 24 | /// id of Characteristic. 25 | /// 26 | public ushort characteristicId; 27 | 28 | /// 29 | /// id of Descriptor. 30 | /// 31 | public ushort descriptorId; 32 | } 33 | 34 | internal class BluetoothEventScan : BaseEvent 35 | { 36 | /// 37 | /// Type of Bluetooth event. 38 | /// 39 | public BluetoothEventType type; 40 | 41 | /// 42 | /// Event id. 43 | /// 44 | public ushort id; 45 | } 46 | 47 | internal class BluetoothEventCentral : BaseEvent 48 | { 49 | /// 50 | /// Type of Bluetooth event. 51 | /// 52 | public BluetoothEventType type; 53 | 54 | /// 55 | /// Connection Handle. 56 | /// 57 | public ushort connectionHandle; 58 | 59 | /// 60 | /// status of event. 61 | /// 62 | public ushort status; 63 | 64 | /// 65 | /// Attribute Handle of service. 66 | /// 67 | public ushort serviceHandle; 68 | 69 | /// 70 | /// Attribute Handle of characteristic. 71 | /// 72 | public ushort characteristicHandle; 73 | } 74 | 75 | internal class BluetoothEventSesssion : BaseEvent 76 | { 77 | /// 78 | /// Type of Bluetooth event. 79 | /// 80 | public BluetoothEventType type; 81 | 82 | /// 83 | /// Connection Handle. 84 | /// 85 | public ushort connectionHandle; 86 | 87 | /// 88 | /// status of event. 89 | /// 90 | public ushort status; 91 | 92 | /// 93 | /// Any extra data. 94 | /// 95 | public ushort data; 96 | 97 | /// 98 | /// Used for when 32 bit data supplied (pin). 99 | /// 100 | public UInt32 data32; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/BluetoothEventType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | using nanoFramework.Runtime.Events; 8 | 9 | namespace nanoFramework.Device.Bluetooth 10 | { 11 | /// 12 | /// Event type for Bluetooth events coming from Native. 13 | /// 14 | public enum BluetoothEventType 15 | { 16 | /// 17 | /// Attribute Read. 18 | /// 19 | Read, 20 | 21 | /// 22 | /// Attribute write. 23 | /// 24 | Write, 25 | 26 | /// 27 | /// Client Subscribed. 28 | /// 29 | ClientSubscribed, 30 | 31 | /// 32 | /// Client unsubscribed or connection terminated. 33 | /// 34 | ClientUnsubscribed, 35 | 36 | // ==== BLE Scanning Events ==== 37 | 38 | /// 39 | /// Advertisement discovered when scanning. 40 | /// 41 | AdvertisementDiscovered, 42 | 43 | /// 44 | /// Discovery Scan complete. 45 | /// 46 | ScanningComplete, 47 | 48 | // Add further server events here >>>>>> 49 | 50 | // ==== BLE Central/Client events ==== 51 | 52 | /// 53 | /// Fires when native connect to device completes. 54 | /// 55 | ConnectComplete, 56 | 57 | /// 58 | /// The connection has disconnected. 59 | /// 60 | ConnectionDisconnected, 61 | 62 | /// 63 | /// A Service discovered for a connection. 64 | /// 65 | ServiceDiscovered, 66 | 67 | /// 68 | /// Service discovery has completed. 69 | /// 70 | ServiceDiscoveryComplete, 71 | 72 | /// 73 | /// A characteristic discovered on Service. 74 | /// 75 | CharacteristicDiscovered, 76 | 77 | /// 78 | /// The characteristic discovery has completed / error. 79 | /// 80 | CharacteristicDiscoveryComplete, 81 | 82 | /// 83 | /// A descriptor discovered on Characteristic. 84 | /// 85 | DescriptorDiscovered, 86 | 87 | /// 88 | /// The Descriptor discovery has completed / error. 89 | /// 90 | DescriptorDiscoveryComplete, 91 | 92 | /// 93 | /// Characteristic read value complete, status=error. 94 | /// 95 | AttributeReadValueComplete, 96 | 97 | /// 98 | /// Attribute Write value completed, status = error. 99 | /// 100 | AttributeWriteValueComplete, 101 | 102 | /// 103 | /// Fired when a value on connected device has changed, notify. 104 | /// 105 | AttributeValueChanged, 106 | 107 | // Add further central events here >>>>>> 108 | 109 | 110 | // ==== Session / Pairing / Security group events ==== 111 | 112 | /// 113 | /// Event when client connects. 114 | /// 115 | ClientConnected, 116 | 117 | /// 118 | /// Event when client disconnects. 119 | /// 120 | ClientDisconnected, 121 | 122 | /// 123 | /// Event when session details are updated. 124 | /// 125 | ClientSessionChanged, 126 | 127 | /// 128 | /// Event fired when a passkey action is requested. 129 | /// 130 | PassKeyActions, 131 | 132 | /// 133 | /// Event Fired when a passkey action for numeric comparison is requested. 134 | /// 135 | PassKeyActionsNumericComparison, 136 | 137 | /// 138 | /// Event fired when the Authentication has completed, security enabled or failed to enable. 139 | /// 140 | AuthenticationComplete 141 | } 142 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/BluetoothLEAdvertisementWatcher.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using nanoFramework.Device.Bluetooth.Advertisement; 7 | using System.Runtime.CompilerServices; 8 | 9 | namespace nanoFramework.Device.Bluetooth 10 | { 11 | /// 12 | /// A class to receive Bluetooth Low Energy (LE) advertisements. 13 | /// 14 | public class BluetoothLEAdvertisementWatcher 15 | { 16 | private BluetoothLEAdvertisementWatcherStatus _status; 17 | private BluetoothLEScanningMode _scanningMode; 18 | private BluetoothLEAdvertisementFilter _advertisementFilter; 19 | private BluetoothSignalStrengthFilter _signalStrengthFilter; 20 | 21 | /// 22 | /// Delegate for new Bluetooth LE advertisement events received. 23 | /// 24 | /// BluetoothLEAdvertisementWatcher sending event 25 | /// Event arguments 26 | public delegate void BluetoothLEAdvertisementReceivedHandler(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args); 27 | 28 | /// 29 | /// Delegate for new Bluetooth LE advertisement stop events. 30 | /// 31 | /// 32 | /// Event arguments 33 | public delegate void BluetoothLEAdvertisementStoppedEvenHandler(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementWatcherStoppedEventArgs args); 34 | 35 | /// 36 | /// Creates a new BluetoothLEAdvertisementWatcher object. 37 | /// 38 | public BluetoothLEAdvertisementWatcher() : this(new BluetoothLEAdvertisementFilter()) 39 | { 40 | } 41 | 42 | /// 43 | /// Creates a new object with an advertisement filter 44 | /// to initialize the watcher. 45 | /// 46 | /// The advertisement filter to initialize the watcher. 47 | public BluetoothLEAdvertisementWatcher(BluetoothLEAdvertisementFilter advertisementFilter) 48 | { 49 | _status = BluetoothLEAdvertisementWatcherStatus.Created; 50 | _advertisementFilter = advertisementFilter; 51 | SignalStrengthFilter = new(); 52 | } 53 | 54 | /// 55 | /// Start the to scan for Bluetooth LE advertisements. 56 | /// 57 | public void Start() 58 | { 59 | // Check and set mode 60 | BluetoothNanoDevice.CheckMode(BluetoothNanoDevice.Mode.Client); 61 | 62 | _status = BluetoothLEAdvertisementWatcherStatus.Started; 63 | 64 | NativeStartAdvertisementWatcher((int)_scanningMode); 65 | BluetoothLEServer._bluetoothEventManager.Watcher = this; 66 | } 67 | 68 | /// 69 | /// Stop the and disable the scanning for Bluetooth 70 | /// LE advertisements. 71 | /// 72 | public void Stop() 73 | { 74 | _status = BluetoothLEAdvertisementWatcherStatus.Stopping; 75 | 76 | BluetoothLEServer._bluetoothEventManager.Watcher = null; 77 | 78 | NativeStopAdvertisementWatcher(); 79 | 80 | _status = BluetoothLEAdvertisementWatcherStatus.Stopped; 81 | 82 | BluetoothLEDevice.IdleOnLastConnection(); 83 | } 84 | 85 | /// 86 | /// Gets or sets a object used for configuration of 87 | /// Bluetooth LE advertisement filtering that uses signal strength-based filtering. 88 | /// 89 | public BluetoothSignalStrengthFilter SignalStrengthFilter { get => _signalStrengthFilter; set => _signalStrengthFilter = value; } 90 | 91 | /// 92 | /// Gets or sets the Bluetooth LE scanning mode. 93 | /// 94 | public BluetoothLEScanningMode ScanningMode { get => _scanningMode; set => _scanningMode = value; } 95 | 96 | /// 97 | /// Gets or sets a object used for configuration of 98 | /// Bluetooth LE advertisement filtering that uses payload section-based filtering. 99 | /// 100 | public BluetoothLEAdvertisementFilter AdvertisementFilter { get => _advertisementFilter; set => _advertisementFilter = value; } 101 | 102 | /// 103 | /// Gets the current status of the . 104 | /// 105 | public BluetoothLEAdvertisementWatcherStatus Status { get => _status; } 106 | 107 | internal void OnReceived(BluetoothLEAdvertisementReceivedEventArgs args) 108 | { 109 | // Check filters 110 | // Advertisement section Filter 111 | if (_advertisementFilter != null && !_advertisementFilter.Filter(args)) 112 | { 113 | return; 114 | } 115 | 116 | // Signal strength filter 117 | if (!_signalStrengthFilter.Filter(args)) 118 | { 119 | return; 120 | } 121 | 122 | FireEvent(args); 123 | } 124 | 125 | internal void FireEvent(BluetoothLEAdvertisementReceivedEventArgs args) 126 | { 127 | Received?.Invoke(this, args); 128 | } 129 | 130 | /// 131 | /// Notification for new Bluetooth LE advertisement events received. 132 | /// 133 | public event BluetoothLEAdvertisementReceivedHandler Received; 134 | 135 | /// 136 | /// Notification to the application that the Bluetooth LE scanning for advertisements has 137 | /// been canceled or aborted either by the application or due to an error. 138 | /// 139 | public event BluetoothLEAdvertisementStoppedEvenHandler Stopped; 140 | 141 | internal void OnStopped(BluetoothLEAdvertisementWatcherStoppedEventArgs args) 142 | { 143 | Stopped?.Invoke(this, args); 144 | } 145 | 146 | #region Native 147 | [MethodImpl(MethodImplOptions.InternalCall)] 148 | private extern void NativeStartAdvertisementWatcher(int mode); 149 | 150 | [MethodImpl(MethodImplOptions.InternalCall)] 151 | private extern void NativeStopAdvertisementWatcher(); 152 | #endregion 153 | 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/BluetoothLEAdvertisementWatcherStatus.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth 7 | { 8 | /// 9 | /// Represents the possible states of the BluetoothLEAdvertisementWatcher. 10 | /// 11 | public enum BluetoothLEAdvertisementWatcherStatus 12 | { 13 | /// 14 | /// The initial status of the watcher. 15 | /// 16 | Created = 0, 17 | 18 | /// 19 | /// The watcher is started. 20 | /// 21 | Started = 1, 22 | 23 | /// 24 | /// The watcher stop command was issued. 25 | /// 26 | Stopping = 2, 27 | 28 | /// 29 | /// The watcher is stopped. 30 | /// 31 | Stopped = 3, 32 | 33 | /// 34 | /// An error occurred during transition or scanning that stopped the watcher due 35 | /// to an error. 36 | /// 37 | Aborted = 4 38 | } 39 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/BluetoothLEManufacturerData.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.Advertisement 9 | { 10 | /// 11 | /// A Bluetooth LE manufacturer-specific data section (one particular type of LE 12 | /// advertisement section). A Bluetooth LE advertisement packet can contain multiple 13 | /// instances of these BluetoothLEManufacturerData objects. 14 | /// 15 | public class BluetoothLEManufacturerData 16 | { 17 | private Buffer _data; 18 | private ushort _companyId; 19 | 20 | /// 21 | /// Creates a new BluetoothLEManufacturerData object. 22 | /// 23 | public BluetoothLEManufacturerData() : this(0, new Buffer(1) ) 24 | { 25 | } 26 | 27 | /// 28 | /// Creates a new BluetoothLEManufacturerData object with a company identifier code 29 | /// and manufacturer-specific section data. 30 | /// 31 | /// 32 | /// The Bluetooth LE company identifier code as defined by the Bluetooth Special 33 | /// Interest Group (SIG). 34 | /// 35 | /// 36 | /// Bluetooth LE manufacturer-specific section data. 37 | /// 38 | public BluetoothLEManufacturerData(ushort companyId, Buffer data) 39 | { 40 | _companyId = companyId; 41 | _data = data; 42 | } 43 | 44 | /// 45 | /// Bluetooth LE manufacturer-specific section data. 46 | /// 47 | public Buffer Data { get => _data; set => _data = value; } 48 | 49 | /// 50 | /// The Bluetooth LE company identifier code as defined by the Bluetooth Special 51 | /// Interest Group (SIG). 52 | /// 53 | public ushort CompanyId { get => _companyId; set => _companyId = value; } 54 | } 55 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/BluetoothLEScanningMode.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.Advertisement 7 | { 8 | /// 9 | /// Defines constants that specify a Bluetooth LE scanning mode. 10 | /// 11 | public enum BluetoothLEScanningMode 12 | { 13 | /// 14 | /// Specifies a passive scanning mode. This is the default scanning mode. 15 | /// 16 | Passive = 0, 17 | 18 | /// 19 | /// Specifies an active scanning mode. This indicates that scan request packets will be sent from the 20 | /// platform to actively query for more advertisement data of type BluetoothLEAdvertisementType.ScanResponse. 21 | /// 22 | Active = 1 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/BluetoothNanoDevice.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | // 7 | // Static class to hold general device parameters 8 | // and controls the current run mode. 9 | // As we can't run both Server or Central/Client at same time 10 | // 11 | 12 | using System; 13 | using System.Runtime.CompilerServices; 14 | 15 | namespace nanoFramework.Device.Bluetooth 16 | { 17 | internal static class BluetoothNanoDevice 18 | { 19 | internal enum Mode { NotRunning, Server, Client }; 20 | 21 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 22 | private static string _deviceName = "nanoFramework"; 23 | 24 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 25 | private static ushort _appearance = 0; 26 | 27 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 28 | private static Mode _mode = Mode.NotRunning; 29 | 30 | static BluetoothNanoDevice() 31 | { 32 | NativeInitilise(); 33 | } 34 | 35 | internal static string DeviceName { get => _deviceName; set => _deviceName = value; } 36 | 37 | internal static ushort Appearance { get => _appearance; set => _appearance = value; } 38 | 39 | /// 40 | /// Checks if current mode enabled otherwise switch to mode. 41 | /// 42 | /// The expected mode. 43 | /// When mode is unexpected. i.e switching directly from client to server modes. 44 | internal static void CheckMode(Mode expectedMode) 45 | { 46 | if (RunMode != expectedMode) 47 | { 48 | // Set new run mode. 49 | BluetoothNanoDevice.RunMode = expectedMode; 50 | } 51 | } 52 | 53 | /// 54 | /// Get/Set the current mode of the device. 55 | /// 56 | /// When mode is unexpected from NativeSetOperationMode. 57 | internal static Mode RunMode 58 | { 59 | get => _mode; 60 | set 61 | { 62 | _mode = value; 63 | NativeSetOperationMode(_mode, DeviceName, Appearance); 64 | } 65 | } 66 | 67 | #region Native 68 | [MethodImpl(MethodImplOptions.InternalCall)] 69 | private static extern void NativeInitilise(); 70 | 71 | [MethodImpl(MethodImplOptions.InternalCall)] 72 | private static extern void NativeSetOperationMode(Mode mode, string deviceName, ushort appearance); 73 | #endregion 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattCharacteristicProperties.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// Specifies the values for the GATT characteristic 12 | /// Extended Characteristic Properties Descriptor. 13 | /// 14 | [Flags] 15 | public enum GattCharacteristicProperties : uint 16 | { 17 | /// 18 | /// The characteristic doesn’t have any properties that apply. 19 | /// 20 | None = 0, 21 | 22 | /// 23 | /// The characteristic supports broadcasting 24 | /// 25 | Broadcast = 1, 26 | 27 | /// 28 | /// The characteristic is readable 29 | /// 30 | Read = 2, 31 | 32 | /// 33 | /// The characteristic supports Write Without Response 34 | /// 35 | WriteWithoutResponse = 4, 36 | 37 | /// 38 | /// The characteristic is writeable 39 | /// 40 | Write = 8, 41 | 42 | /// 43 | /// The characteristic is notifiable 44 | /// 45 | Notify = 16, 46 | 47 | /// 48 | /// The characteristic is indicatable 49 | /// 50 | Indicate = 32, 51 | 52 | /// 53 | /// The characteristic supports signed writes 54 | /// 55 | AuthenticatedSignedWrites = 64, 56 | 57 | /// 58 | /// The ExtendedProperties Descriptor is present 59 | /// 60 | ExtendedProperties = 128, 61 | 62 | /// 63 | /// The characteristic supports reliable writes 64 | /// 65 | ReliableWrites = 256, 66 | 67 | /// 68 | /// The characteristic has writeable auxiliaries 69 | /// 70 | WritableAuxiliaries = 512 71 | } 72 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattCharacteristicResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System.Collections; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// Contains the result of GetCharacteristicsForUuid and GetCharacteristics 12 | /// 13 | public class GattCharacteristicsResult 14 | { 15 | private readonly byte _protocolError; 16 | private readonly ArrayList _characteristics; 17 | private readonly GattCommunicationStatus _status; 18 | 19 | internal GattCharacteristicsResult(byte ProtocolError, ArrayList Characteristics, GattCommunicationStatus Status) 20 | { 21 | _protocolError = ProtocolError; 22 | _characteristics = Characteristics; 23 | _status = Status; 24 | } 25 | 26 | /// 27 | /// Gets the characteristics. 28 | /// returning an Array of GattCharacteristic objects. 29 | /// 30 | public GattCharacteristic[] Characteristics { get => (GattCharacteristic[])_characteristics.ToArray(typeof(GattCharacteristic)); } 31 | 32 | /// 33 | /// Gets the protocol error. 34 | /// 35 | public byte ProtocolError { get => _protocolError; } 36 | 37 | /// 38 | /// Gets the communication status of the operation. 39 | /// 40 | public GattCommunicationStatus Status { get => _status; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattClientCharacteristicConfigurationDescriptorValue.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// Represents the value of the GATT ClientCharacteristicConfigurationDescriptor. 10 | /// 11 | public enum GattClientCharacteristicConfigurationDescriptorValue 12 | { 13 | /// 14 | /// Neither notification nor indications are enabled. 15 | /// 16 | None = 0, 17 | 18 | /// 19 | /// Characteristic notifications are enabled. 20 | /// 21 | Notify = 1, 22 | 23 | /// 24 | /// Characteristic indications are enabled. 25 | /// 26 | Indicate = 2 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattClientNotificationResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// The result of a NotifyValue 10 | /// 11 | public class GattClientNotificationResult 12 | { 13 | private readonly byte _result; 14 | private readonly GattCommunicationStatus _status; 15 | private readonly GattSubscribedClient _client; 16 | private readonly ushort _bytesSent; 17 | 18 | internal GattClientNotificationResult(byte result, GattCommunicationStatus status, GattSubscribedClient client, ushort bytesSent) 19 | { 20 | _result = result; 21 | _status = status; 22 | _client = client; 23 | _bytesSent = bytesSent; 24 | } 25 | 26 | /// 27 | /// Gets the protocol error. 28 | /// 29 | public byte ProtocolError { get => _result; } 30 | 31 | /// 32 | /// Gets the GATT communication status. 33 | /// 34 | public GattCommunicationStatus Status { get => _status; } 35 | 36 | /// 37 | /// Gets the subscribed client. 38 | /// 39 | public GattSubscribedClient SubscribedClient { get => _client; } 40 | 41 | /// 42 | /// Gets the bytes that were sent. 43 | /// 44 | public ushort BytesSent { get => _bytesSent; } 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattCommunicationStatus.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// Represents the return status of a GATT API related operation. 10 | /// 11 | public enum GattCommunicationStatus 12 | { 13 | /// 14 | /// The operation completed successfully. 15 | /// 16 | Success = 0, 17 | 18 | /// 19 | /// No communication can be performed with the device, at this time. 20 | /// 21 | Unreachable = 1, 22 | 23 | /// 24 | /// There was a GATT communication protocol error. 25 | /// 26 | ProtocolError = 2, 27 | 28 | /// 29 | /// Access is denied. 30 | /// 31 | AccessDenied = 3 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattDescriptor.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// Represents a Descriptor of a GATT Characteristic. The GattDescriptor object represents 12 | /// a GATT Descriptor of a particular characteristic, it is obtained from the Descriptors 13 | /// property of the GattCharacteristic object. 14 | /// 15 | public class GattDescriptor : IGattAttribute 16 | { 17 | private readonly ushort _attributeHandle; 18 | private readonly byte[] _uuid; 19 | private GattProtectionLevel _protectionLevel; 20 | private readonly BluetoothLEDevice _device; 21 | 22 | internal GattDescriptor(GattCharacteristic characteristic, ushort attributeHandle) 23 | { 24 | _device = characteristic.Service.Device; 25 | _attributeHandle = attributeHandle; 26 | _uuid = new byte[16]; 27 | } 28 | 29 | /// 30 | /// Performs a Descriptor Value read. 31 | /// 32 | /// 33 | /// The object required to manage the asynchronous operation, which, upon completion, 34 | /// returns a GattReadResult object, which in turn contains the completion status 35 | /// of the asynchronous operation and, if successful, the data read from the device. 36 | /// 37 | public GattReadResult ReadValue() 38 | { 39 | return _device.ReadAttributeValue(AttributeHandle); 40 | } 41 | 42 | /// 43 | /// Performs a Descriptor Value write to a Bluetooth LE device. 44 | /// 45 | /// 46 | /// A Buffer object which contains the data to be written 47 | /// to the Bluetooth LE device. 48 | /// 49 | /// 50 | /// Returns the status with which the operation completed. 51 | /// 52 | public GattCommunicationStatus WriteValue(Buffer value) 53 | { 54 | GattWriteResult gwr = _device.WriteAttributeValueWithResult(AttributeHandle, value); 55 | 56 | return gwr.Status; 57 | } 58 | 59 | /// 60 | /// Performs a Descriptor Value write to a Bluetooth LE device. 61 | /// 62 | /// 63 | /// A Buffer object which contains the data to be written 64 | /// to the Bluetooth LE device. 65 | /// 66 | /// 67 | /// A GattWriteResult. 68 | /// 69 | public GattWriteResult WriteValueWithResult(Buffer value) 70 | { 71 | return _device.WriteAttributeValueWithResult(AttributeHandle, value); 72 | } 73 | 74 | /// 75 | /// Gets or sets the desired GATT security options for over the air communication 76 | /// with the device. 77 | /// 78 | public GattProtectionLevel ProtectionLevel { get => _protectionLevel; set => _protectionLevel = value; } 79 | 80 | /// 81 | /// Gets the GATT Attribute handle used to uniquely identify this attribute on the 82 | /// GATT Server Device. 83 | /// 84 | public ushort AttributeHandle { get => _attributeHandle; } 85 | 86 | /// 87 | /// Gets the GATT Descriptor UUID for this GattDescriptor. 88 | /// 89 | public Guid Uuid { get => new(_uuid); } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattDescriptorResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System.Collections; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// The result of descriptor operations like GattCharacteristic.GetDescriptors 12 | /// 13 | public class GattDescriptorsResult 14 | { 15 | private readonly byte _protocolError; 16 | private readonly ArrayList _descriptors; 17 | private readonly GattCommunicationStatus _status; 18 | 19 | internal GattDescriptorsResult(byte ProtocolError, ArrayList Descriptors, GattCommunicationStatus Status) 20 | { 21 | _protocolError = ProtocolError; 22 | _descriptors = Descriptors; 23 | _status = Status; 24 | } 25 | 26 | /// 27 | /// Gets the descriptors. 28 | /// returning an Array of GattDescriptor objects. 29 | /// 30 | public GattDescriptor[] Descriptors { get => (GattDescriptor[])_descriptors.ToArray(typeof(GattDescriptor)); } 31 | 32 | /// 33 | /// Gets the protocol error. 34 | /// 35 | public byte ProtocolError { get => _protocolError; } 36 | 37 | /// 38 | /// Gets the communication status of the operation. 39 | /// 40 | public GattCommunicationStatus Status { get => _status; } 41 | } 42 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattDescriptorUuid.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// Represents an enumeration of the most well known Descriptor UUID values, and 12 | /// provides convenience methods for working with GATT descriptor UUIDs, and static 13 | /// properties providing descriptor UUIDs for common GATT descriptors. 14 | /// 15 | public static class GattDescriptorUuids 16 | { 17 | /// 18 | /// Gets the Bluetooth SIG-defined Characteristic Aggregate Format Descriptor UUID. 19 | /// 20 | public static Guid CharacteristicAggregateFormat { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.CharacteristicAggregateFormat); } 21 | 22 | /// 23 | /// Gets the Bluetooth SIG-defined Characteristic Extended Properties Descriptor UUID. 24 | /// 25 | public static Guid CharacteristicExtendedProperties { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.CharacteristicExtendedProperties); } 26 | 27 | /// 28 | /// Gets the Bluetooth SIG-defined Characteristic Presentation Format Descriptor 29 | /// 30 | public static Guid CharacteristicPresentationFormat { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.CharacteristicPresentationFormat); } 31 | 32 | /// 33 | /// Gets the Bluetooth SIG-defined Characteristic User Description Descriptor UUID. 34 | /// 35 | public static Guid CharacteristicUserDescription { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.CharacteristicUserDescription); } 36 | 37 | /// 38 | /// Gets the Bluetooth SIG-defined Client Characteristic Configuration Descriptor UUID. 39 | /// 40 | public static Guid ClientCharacteristicConfiguration { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.ClientCharacteristicConfiguration); } 41 | 42 | /// 43 | /// Gets the Bluetooth SIG-defined Server Characteristic Configuration Descriptor UUID. 44 | /// 45 | public static Guid ServerCharacteristicConfiguration { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.ServerCharacteristicConfiguration); } 46 | 47 | /// 48 | /// Get the Bluetooth SIG-defined External Report Reference Descriptor UUID. 49 | /// 50 | public static Guid ExternalReportReference { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.ExternalReportReference); } 51 | 52 | /// 53 | /// Get the Bluetooth SIG-defined Report Reference Descriptor UUID. 54 | /// 55 | public static Guid ReportReference { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.ReportReference); } 56 | 57 | /// 58 | /// Gets the Bluetooth SIG-defined Value trigger settings Descriptor UUID. 59 | /// 60 | public static Guid ValueTriggerSetting { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.ValueTriggerSetting); } 61 | 62 | /// 63 | /// Gets the Bluetooth SIG-defined Environmental Sensing Configuration Descriptor UUID. 64 | /// 65 | public static Guid EssConfiguration { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.EssConfiguration); } 66 | 67 | /// 68 | /// Gets the Bluetooth SIG-defined Environmental Sensing Measurement Descriptor UUID. 69 | /// 70 | public static Guid EssMeasurement { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.EssMeasurement); } 71 | 72 | /// 73 | /// Gets the Bluetooth SIG-defined Environmental Sensing Trigger Setting Descriptor UUID. 74 | /// 75 | public static Guid EssTriggerSetting { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.EssTriggerSetting); } 76 | 77 | /// 78 | /// Gets the Bluetooth SIG-defined Time Trigger Setting Descriptor UUID. 79 | /// 80 | public static Guid TimeTriggerSetting { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.TimeTriggerSetting); } 81 | } 82 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattDeviceServicesResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System.Collections; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// The status of GetIncludedServicesForUuid and GetIncludedServicesForUuid 12 | /// 13 | public class GattDeviceServicesResult 14 | { 15 | private readonly byte _protocolError; 16 | private readonly ArrayList _services; 17 | private readonly GattCommunicationStatus _status; 18 | 19 | internal GattDeviceServicesResult(byte ProtocolError, ArrayList Services, GattCommunicationStatus Status) 20 | { 21 | _protocolError = ProtocolError; 22 | _services = Services; 23 | _status = Status; 24 | } 25 | 26 | /// 27 | /// Gets the protocol error. 28 | /// 29 | public byte ProtocolError { get => _protocolError; } 30 | 31 | /// 32 | /// Gets the services. 33 | /// returning an Array of GattDeviceService objects. 34 | /// 35 | public GattDeviceService[] Services { get => (GattDeviceService[])_services.ToArray(typeof(GattDeviceService)); } 36 | 37 | /// 38 | /// Gets the communication status of the operation. 39 | /// 40 | public GattCommunicationStatus Status { get => _status; } 41 | } 42 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattLocalCharacteristicParameters.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System.Collections; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// This class contains the local characteristic descriptor parameters. 12 | /// 13 | public class GattLocalCharacteristicParameters 14 | { 15 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 16 | private GattProtectionLevel _writeProtectionLevel; 17 | 18 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 19 | private GattProtectionLevel _readProtectionLevel; 20 | 21 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 22 | private string _userDescription; 23 | 24 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 25 | private GattCharacteristicProperties _properties; 26 | 27 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 28 | private Buffer _staticValue; 29 | 30 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 31 | private readonly ArrayList _presentationFormats; 32 | 33 | /// 34 | /// Creates a new GattLocalCharacteristicParameters object. 35 | /// 36 | public GattLocalCharacteristicParameters() 37 | { 38 | _writeProtectionLevel = GattProtectionLevel.Plain; 39 | _readProtectionLevel = GattProtectionLevel.Plain; 40 | _userDescription = ""; 41 | _properties = GattCharacteristicProperties.None; 42 | _presentationFormats = new ArrayList(); 43 | } 44 | 45 | /// 46 | /// Gets and sets the write protection level. 47 | /// 48 | public GattProtectionLevel WriteProtectionLevel { get => _writeProtectionLevel; set => _writeProtectionLevel = value; } 49 | 50 | /// 51 | /// Gets or sets the user-friendly description. 52 | /// 53 | public string UserDescription { get => _userDescription; set => _userDescription = value; } 54 | 55 | /// 56 | /// Gets or sets the static value. 57 | /// 58 | public Buffer StaticValue { get => _staticValue; set => _staticValue = value; } 59 | 60 | /// 61 | /// Gets or sets the read protection level. 62 | /// 63 | public GattProtectionLevel ReadProtectionLevel { get => _readProtectionLevel; set => _readProtectionLevel = value; } 64 | 65 | /// 66 | /// Gets the properties. 67 | /// 68 | public GattCharacteristicProperties CharacteristicProperties { get => _properties; set => _properties = value; } 69 | 70 | /// 71 | /// Gets or sets the presentation formats arrayLIst 72 | /// 73 | public GattPresentationFormat[] PresentationFormats { get => (GattPresentationFormat[])_presentationFormats.ToArray(typeof(GattPresentationFormat)); } 74 | 75 | /// 76 | /// Create a GattPresentationFormat to the GattLocalCharacteristicParameters 77 | /// 78 | public void CreateGattPresentationFormat(byte formatType, int exponent, ushort unit, byte namespaceId, ushort decsription) 79 | { 80 | _presentationFormats.Add(new GattPresentationFormat(formatType, exponent, unit, namespaceId, decsription)); 81 | } 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattLocalCharacteristicResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// A result of CreateCharacteristic 10 | /// 11 | public class GattLocalCharacteristicResult 12 | { 13 | private readonly GattLocalCharacteristic _characteristic; 14 | private readonly BluetoothError _error; 15 | 16 | internal GattLocalCharacteristicResult(GattLocalCharacteristic Characteristic, BluetoothError Error) 17 | { 18 | _characteristic = Characteristic; 19 | _error = Error; 20 | } 21 | 22 | /// 23 | /// Gets the characteristic of the GATT service. 24 | /// 25 | public GattLocalCharacteristic Characteristic { get => _characteristic; } 26 | 27 | /// 28 | /// Gets the Bluetooth error. 29 | /// 30 | public BluetoothError Error { get => _error; } 31 | } 32 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattLocalDescriptor.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// This class defines a descriptor of a local characteristic. 12 | /// 13 | public class GattLocalDescriptor 14 | { 15 | // Each Descriptor will have unique _descriptorId for event lookup, events for descriptors are handled by User app. 16 | // This comprises of characteristic id + GattLocalDescriptorIndex in the form 17 | // x'DDCC' where DD is Descriptor and CC characteristic 18 | internal ushort _descriptorId; 19 | 20 | private readonly GattLocalCharacteristic _charactisic; 21 | 22 | private readonly GattProtectionLevel _writeProtectionLevel; 23 | private readonly GattProtectionLevel _readProtectionLevel; 24 | private readonly byte[] _uuid; 25 | 26 | private readonly Buffer _staticValue; 27 | 28 | /// 29 | /// Delegate for Read requests 30 | /// 31 | /// GattLocalDescriptor sending event 32 | /// Event arguments 33 | public delegate void GattLocalDescriptorReadEventHandler(GattLocalCharacteristic sender, GattReadRequestedEventArgs ReadRequestEventArgs); 34 | 35 | /// 36 | /// Delegate for Write requests 37 | /// 38 | /// GattLocalDescriptor sending event 39 | /// Event arguments 40 | public delegate void GattLocalDescriptorWriteEventHandler(GattLocalCharacteristic sender, GattWriteRequestedEventArgs WriteRequestEventArgs); 41 | 42 | internal GattLocalDescriptor(Guid uuid, GattLocalDescriptorParameters parameters, GattLocalCharacteristic charactisic, int descriptorIndex) 43 | { 44 | _uuid = uuid.ToByteArray(); 45 | _charactisic = charactisic; 46 | 47 | _writeProtectionLevel = parameters.WriteProtectionLevel; 48 | _readProtectionLevel = parameters.ReadProtectionLevel; 49 | _staticValue = parameters.StaticValue; 50 | 51 | _descriptorId = (ushort)((descriptorIndex << 8) + _charactisic._characteristicId); 52 | } 53 | 54 | /// 55 | /// Gets the read protection level of this local characteristic descriptor. 56 | /// 57 | public GattProtectionLevel ReadProtectionLevel { get => _readProtectionLevel; } 58 | 59 | /// 60 | /// Gets the static value for this local characteristic descriptor. 61 | /// 62 | public Buffer StaticValue { get => _staticValue; } 63 | 64 | /// 65 | /// Gets the Bluetooth SIG-defined UUID for this local characteristic descriptor. 66 | /// 67 | public Guid Uuid { get => new(_uuid); } 68 | 69 | /// 70 | /// Gets the write protection level. 71 | /// 72 | public GattProtectionLevel WriteProtectionLevel { get => _writeProtectionLevel; } 73 | 74 | /// 75 | /// An event that is triggered when a GATT client requests a descriptor read operation. 76 | /// 77 | public event GattLocalDescriptorReadEventHandler ReadRequested; 78 | 79 | /// 80 | /// This is an event that is triggered when a write descriptor was requested. 81 | /// 82 | public event GattLocalDescriptorWriteEventHandler WriteRequested; 83 | 84 | internal bool OnReadRequested(GattReadRequestedEventArgs e) 85 | { 86 | if (_staticValue != null) 87 | { 88 | e.GetRequest().RespondWithValue(_staticValue); 89 | return true; 90 | } 91 | 92 | if (ReadRequested != null) 93 | { 94 | ReadRequested?.Invoke(_charactisic, e); 95 | return true; 96 | } 97 | 98 | return false; 99 | } 100 | 101 | internal bool OnWriteRequested(GattWriteRequestedEventArgs e) 102 | { 103 | if (WriteRequested != null) 104 | { 105 | WriteRequested?.Invoke(_charactisic, e); 106 | return true; 107 | } 108 | 109 | return false; 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattLocalDescriptorParameters.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// This class defines the parameters of a descriptor. 10 | /// 11 | public class GattLocalDescriptorParameters 12 | { 13 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 14 | private GattProtectionLevel _writeProtectionLevel; 15 | 16 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 17 | private GattProtectionLevel _readProtectionLevel; 18 | 19 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 20 | private Buffer _staticValue = null; 21 | 22 | /// 23 | /// Creates a new GattLocalDescriptorParameters object. 24 | /// 25 | public GattLocalDescriptorParameters() 26 | { 27 | _writeProtectionLevel = GattProtectionLevel.Plain; 28 | _readProtectionLevel = GattProtectionLevel.Plain; 29 | } 30 | 31 | /// 32 | /// Gets or sets the write protection level. 33 | /// 34 | public GattProtectionLevel WriteProtectionLevel { get => _writeProtectionLevel; set => _writeProtectionLevel = value; } 35 | 36 | /// 37 | /// Gets or sets the static value. 38 | /// 39 | public Buffer StaticValue { get => _staticValue; set => _staticValue = value; } 40 | 41 | /// 42 | /// Gets or sets the read protection level. 43 | /// 44 | public GattProtectionLevel ReadProtectionLevel { get => _readProtectionLevel; set => _readProtectionLevel = value; } 45 | } 46 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattLocalDescriptorResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// The result of local characteristic descriptor operations like CreateDescriptorAsync. 10 | /// 11 | public class GattLocalDescriptorResult 12 | { 13 | private readonly BluetoothError _error; 14 | private readonly GattLocalDescriptor _descriptor; 15 | 16 | internal GattLocalDescriptorResult(GattLocalDescriptor descriptor, BluetoothError error) 17 | { 18 | _descriptor = descriptor; 19 | _error = error; 20 | } 21 | 22 | /// 23 | /// Gets the descriptor. 24 | /// 25 | public GattLocalDescriptor Descriptor { get => _descriptor; } 26 | 27 | /// 28 | /// Gets the error. 29 | /// 30 | public BluetoothError Error { get => _error; } 31 | } 32 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattLocalService.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | using System.Collections; 8 | 9 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 10 | { 11 | /// 12 | /// This class represents a GATT local service. 13 | /// 14 | public class GattLocalService 15 | { 16 | private readonly byte[] _serviceUuid; 17 | private readonly ArrayList _characteristics; 18 | 19 | internal GattLocalService(Guid serviceUuid) 20 | { 21 | _serviceUuid = serviceUuid.ToByteArray(); 22 | _characteristics = new ArrayList(); 23 | } 24 | 25 | /// 26 | /// Creates a characteristic for this local service. 27 | /// 28 | /// The characteristic UUID. 29 | /// The characteristic parameters. 30 | /// An GattLocalCharacteristicResult object 31 | public GattLocalCharacteristicResult CreateCharacteristic(Guid characteristicUuid, GattLocalCharacteristicParameters parameters) 32 | { 33 | GattLocalCharacteristic Characteristic = new(characteristicUuid, parameters); 34 | _characteristics.Add(Characteristic); 35 | 36 | // Update pairing security based on current read/write protectionlevels. 37 | BluetoothLEServer.Instance.UpdateSecurityPairingRequirements(Characteristic.ReadProtectionLevel); 38 | BluetoothLEServer.Instance.UpdateSecurityPairingRequirements(Characteristic.WriteProtectionLevel); 39 | 40 | return new GattLocalCharacteristicResult(Characteristic, BluetoothError.Success); 41 | } 42 | 43 | /// 44 | /// Gets a array of the characteristics available for this local service. 45 | /// 46 | public GattLocalCharacteristic[] Characteristics { get { return (GattLocalCharacteristic[])_characteristics.ToArray(typeof(GattLocalCharacteristic)); } } 47 | 48 | /// 49 | /// Gets the local service UUID. 50 | /// 51 | public Guid Uuid { get => new(_serviceUuid); } 52 | } 53 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattPresentationFormat.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// Represents the value of a single Presentation Format GATT Descriptor. 10 | /// 11 | public class GattPresentationFormat 12 | { 13 | private readonly byte _formatType; 14 | private readonly int _exponent; 15 | private readonly ushort _unit; 16 | private readonly byte _namespaceId; 17 | private readonly ushort _description; 18 | 19 | /// 20 | /// Creates a GattPresentationFormat object from parts. 21 | /// 22 | /// The Format Type. 23 | /// The exponent. 24 | /// The unit. 25 | /// The namespace id. 26 | /// The description. 27 | /// An instance of GattPresentationFormat. 28 | public static GattPresentationFormat FromParts(byte formatType, int exponent, ushort unit, byte namespaceId, ushort description) 29 | { 30 | return new GattPresentationFormat(formatType, exponent, unit, namespaceId, description); 31 | } 32 | 33 | internal GattPresentationFormat(byte formatType, int exponent, ushort unit, byte namespaceId, ushort description) 34 | { 35 | _formatType = formatType; 36 | _exponent = exponent; 37 | _unit = unit; 38 | _namespaceId = namespaceId; 39 | _description = description; 40 | } 41 | 42 | /// 43 | /// Gets the Description of the GattPresentationFormat object. 44 | /// 45 | public ushort Description { get => _description; } 46 | 47 | /// 48 | /// Gets the Exponent of the GattPresentationFormat object. 49 | /// 50 | public int Exponent { get => _exponent; } 51 | 52 | /// 53 | /// Gets the Format Type of the GattPresentationFormat object. 54 | /// 55 | public byte FormatType { get => _formatType; } 56 | 57 | /// 58 | /// Gets the Name space of the GattPresentationFormat object. 59 | /// 60 | public byte Namespace { get => _namespaceId; } 61 | 62 | /// 63 | /// Gets the Unit of the GattPresentationFormat object. 64 | /// 65 | public ushort Unit { get => _unit; } 66 | } 67 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattPresentationFormatTypes.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// Represents the different well-known values that the GattPresentationFormat.FormatType 10 | /// property can take. 11 | /// 12 | public static class GattPresentationFormatTypes 13 | { 14 | /// 15 | /// Gets the value of the Bit2 Format Type. 16 | /// 17 | public static byte Bit2 { get => 0x02; } 18 | 19 | /// 20 | /// Gets the value of the Boolean Format Type. 21 | /// 22 | public static byte Boolean { get => 0x01; } 23 | 24 | /// 25 | /// Gets the value of the DUInt16 Format Type. 26 | /// 27 | public static byte DUInt16 { get => 0x18; } 28 | 29 | /// 30 | /// Gets the value of the Float Format Type. 31 | /// 32 | public static byte Float { get => 0x17; } 33 | 34 | /// 35 | /// Gets the value of the Float32 Format Type. 36 | /// 37 | public static byte Float32 { get => 0x14; } 38 | 39 | /// 40 | /// Gets the value of the Float64 Format Type. 41 | /// 42 | public static byte Float64 { get => 0x15; } 43 | /// 44 | /// Gets the value of the Nibble Format Type. 45 | /// 46 | public static byte Nibble { get => 0x03; } 47 | 48 | /// 49 | /// Gets the value of the SFloat Format Type. 50 | /// 51 | public static byte SFloat { get => 0x16; } 52 | 53 | /// 54 | /// Gets the value of the SInt12 Format Type. 55 | /// 56 | public static byte SInt12 { get => 0x0d; } 57 | 58 | /// 59 | /// Gets the value of the SInt128 Format Type. 60 | /// 61 | public static byte SInt128 { get => 0x13; } 62 | 63 | /// 64 | /// Gets the value of the SInt16 Format Type. 65 | /// 66 | public static byte SInt16 { get => 0x0e; } 67 | 68 | /// 69 | /// Gets the value of the SInt24 Format Type. 70 | /// 71 | public static byte SInt24 { get => 0x0f; } 72 | 73 | /// 74 | /// Gets the value of the SInt32 Format Type. 75 | /// 76 | public static byte SInt32 { get => 0x10; } 77 | 78 | /// 79 | /// Gets the value of the SInt48 Format Type. 80 | /// 81 | public static byte SInt48 { get => 0x11; } 82 | 83 | /// 84 | /// Gets the value of the SInt64 Format Type. 85 | /// 86 | public static byte SInt64 { get => 0x12; } 87 | 88 | /// 89 | /// Gets the value of the SInt8 Format Type. 90 | /// 91 | public static byte SInt8 { get => 0x0c; } 92 | 93 | /// 94 | /// Gets the value of the Struct Format Type. 95 | /// 96 | public static byte Struct { get => 0x1b; } 97 | 98 | /// 99 | /// Gets the value of the UInt12 Format Type. 100 | /// 101 | public static byte UInt12 { get => 0x05; } 102 | 103 | /// 104 | /// Gets the value of the UInt128 Format Type. 105 | /// 106 | public static byte UInt128 { get => 0x0b; } 107 | 108 | /// 109 | /// Gets the value of the UInt16 Format Type. 110 | /// 111 | public static byte UInt16 { get => 0x06; } 112 | 113 | /// 114 | /// Gets the value of the UInt24 Format Type. 115 | /// 116 | public static byte UInt24 { get => 0x07; } 117 | 118 | /// 119 | /// Gets the value of the UInt32 Format Type. 120 | /// 121 | public static byte UInt32 { get => 0x08; } 122 | 123 | /// 124 | /// Gets the value of the UInt48 Format Type. 125 | /// 126 | public static byte UInt48 { get => 0x09; } 127 | 128 | /// 129 | /// Gets the value of the UInt64 Format Type. 130 | /// 131 | public static byte UInt64 { get => 0x0a; } 132 | 133 | /// 134 | /// Gets the value of the UInt8 Format Type. 135 | /// 136 | public static byte UInt8 { get => 0x04; } 137 | 138 | /// 139 | /// Gets the value of the Utf16 Format Type. 140 | /// 141 | public static byte Utf16 { get => 0x1a; } 142 | 143 | /// 144 | /// Gets the value of the Utf8 Format Type. 145 | /// 146 | public static byte Utf8 { get => 0x8; } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattProtectionLevel.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// Represents the desired security level. 10 | /// 11 | public enum GattProtectionLevel 12 | { 13 | /// 14 | /// Uses the default protection level. 15 | /// 16 | Plain = 0, 17 | 18 | /// 19 | /// Require the link to be authenticated. 20 | /// 21 | AuthenticationRequired = 1, 22 | 23 | /// 24 | /// Require the link to be encrypted. 25 | /// 26 | EncryptionRequired = 2, 27 | 28 | /// 29 | /// Require the link to be encrypted and authenticated. 30 | /// 31 | EncryptionAndAuthenticationRequired = 3 32 | } 33 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattProtocolError.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// This class contains byte values for GATT protocol errors. 10 | /// 11 | public static class GattProtocolError 12 | { 13 | /// 14 | /// Gets the byte value for an attribute not found error. 15 | /// 16 | public static byte AttributeNotFound { get => 10; } 17 | 18 | /// 19 | /// Gets the byte value for an attribute not long error. 20 | /// 21 | public static byte AttributeNotLong { get => 11; } 22 | 23 | /// 24 | /// Gets the byte value for an insufficient authentication error. 25 | /// 26 | public static byte InsufficientAuthentication { get => 5; } 27 | 28 | /// 29 | /// Gets the byte value for an insufficient authorization error. 30 | /// 31 | public static byte InsufficientAuthorization { get => 8; } 32 | 33 | /// 34 | /// Gets the byte value for an insufficient encryption error. 35 | /// 36 | public static byte InsufficientEncryption { get => 15; } 37 | 38 | /// 39 | /// Gets the byte value for an insufficient encryption key size error. 40 | /// 41 | public static byte InsufficientEncryptionKeySize { get => 12; } 42 | 43 | /// 44 | /// Gets the byte value for an insufficient resources error. 45 | /// 46 | public static byte InsufficientResources { get => 17; } 47 | 48 | /// 49 | /// Gets the byte value for an invalid attribute value length error. 50 | /// 51 | public static byte InvalidAttributeValueLength { get => 13; } 52 | 53 | /// 54 | /// Gets the byte value for an invalid handle error. 55 | /// 56 | public static byte InvalidHandle { get => 1; } 57 | 58 | /// 59 | /// Gets the byte value for an invalid offset error. 60 | /// 61 | public static byte InvalidOffset { get => 7; } 62 | 63 | /// 64 | /// Gets the byte value for an invalid PDU error. 65 | /// 66 | public static byte InvalidPdu { get => 4; } 67 | 68 | /// 69 | /// Gets the byte value for a prepare queue full error. 70 | /// 71 | public static byte PrepareQueueFull { get => 9; } 72 | 73 | /// 74 | /// Gets the byte value for a read not permitted error. 75 | /// 76 | public static byte ReadNotPermitted { get => 2; } 77 | 78 | /// 79 | /// Gets the byte value for a request not supported error. 80 | /// 81 | public static byte RequestNotSupported { get => 6; } 82 | 83 | /// 84 | /// Gets the byte value for an unlikely error. 85 | /// 86 | public static byte UnlikelyError { get => 14; } 87 | 88 | /// 89 | /// Gets the byte value for an unsupported group type error. 90 | /// 91 | public static byte UnsupportedGroupType { get => 15; } 92 | 93 | /// 94 | /// Gets the byte value for a write not permitted error. 95 | /// 96 | public static byte WriteNotPermitted { get => 3; } 97 | } 98 | } 99 | 100 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattReadClientCharacteristicConfigurationDescriptorResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// Represents the result of reading a GATT Client CharacteristicConfigurationClientDescriptor value. 10 | /// 11 | public class GattReadClientCharacteristicConfigurationDescriptorResult 12 | { 13 | private readonly GattClientCharacteristicConfigurationDescriptorValue _config; 14 | private readonly byte _protocolError; 15 | private readonly GattCommunicationStatus _status; 16 | 17 | internal GattReadClientCharacteristicConfigurationDescriptorResult( 18 | GattClientCharacteristicConfigurationDescriptorValue value, 19 | GattCommunicationStatus status, 20 | byte protocolError) 21 | { 22 | _config = value; 23 | _status = status; 24 | _protocolError = protocolError; 25 | } 26 | 27 | /// 28 | /// Gets the result of an read operation. 29 | /// 30 | public GattClientCharacteristicConfigurationDescriptorValue ClientCharacteristicConfigurationDescriptor { get => _config; } 31 | 32 | /// 33 | /// Gets the status of an operation. 34 | /// 35 | public GattCommunicationStatus Status { get => _status; } 36 | 37 | /// 38 | /// Gets the protocol error. 39 | /// 40 | public byte ProtocolError { get => _protocolError; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattReadRequest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | using System.Runtime.CompilerServices; 8 | 9 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 10 | { 11 | /// 12 | /// This class represents a Bluetooth GATT read request. 13 | /// 14 | public class GattReadRequest 15 | { 16 | private Buffer _readValue; 17 | private readonly ushort _eventID; 18 | 19 | internal GattReadRequest(ushort eventID) 20 | { 21 | _eventID = eventID; 22 | } 23 | 24 | /// 25 | /// Responds to a read request with a value. 26 | /// 27 | /// The value to respond with. 28 | public void RespondWithValue(Buffer value) 29 | { 30 | _readValue = value; 31 | 32 | byte[] data = new byte[_readValue.Length]; 33 | Array.Copy(_readValue.Data, data, (int)_readValue.Length); 34 | 35 | NativeReadRespondWithValue(_eventID, data); 36 | } 37 | 38 | /// 39 | /// Responds to the read request with a protocol error. 40 | /// 41 | /// The protocol error to send. A list of errors with the byte values can be found in GattProtocolError. 42 | public void RespondWithProtocolError(byte protocolError) 43 | { 44 | NativeReadRespondWithProtocolError(_eventID, protocolError); 45 | } 46 | 47 | /// 48 | /// Gets the buffer length of the read request. 49 | /// 50 | public uint Length { get => _readValue.Length; } 51 | 52 | #region external calls to native implementations 53 | 54 | [MethodImpl(MethodImplOptions.InternalCall)] 55 | private extern void NativeReadRespondWithValue(ushort eventID, byte[] value); 56 | 57 | [MethodImpl(MethodImplOptions.InternalCall)] 58 | private extern void NativeReadRespondWithProtocolError(ushort eventID, byte protocolError); 59 | 60 | #endregion 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattReadRequestedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// This class contains the arguments for the StateChanged event. 10 | /// 11 | public class GattReadRequestedEventArgs 12 | { 13 | private readonly ushort _eventID; 14 | private readonly GattSession _session = null; 15 | 16 | internal GattReadRequestedEventArgs(ushort eventID, GattSession session) 17 | { 18 | _eventID = eventID; 19 | _session = session; 20 | } 21 | 22 | /// 23 | /// Gets the GATT read request. 24 | /// 25 | /// Returns a GattReadRequest object. 26 | public GattReadRequest GetRequest() 27 | { 28 | return new GattReadRequest(_eventID); 29 | } 30 | 31 | /// 32 | /// Gets the session. 33 | /// 34 | public GattSession Session { get => _session; } 35 | } 36 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattReadResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// Represents the result of an asynchronous read operation of a GATT Characteristic 10 | /// or Descriptor value. 11 | /// 12 | public class GattReadResult 13 | { 14 | private readonly GattCommunicationStatus _status; 15 | private readonly byte _protocolError; 16 | private readonly Buffer _buffer; 17 | 18 | internal GattReadResult(Buffer buffer, GattCommunicationStatus status, byte protocolError) 19 | { 20 | _buffer = buffer; 21 | _status = status; 22 | _protocolError = protocolError; 23 | } 24 | 25 | /// 26 | /// Gets the status of an operation. 27 | /// 28 | public GattCommunicationStatus Status { get => _status; } 29 | 30 | /// 31 | /// Gets the value read from the device. 32 | /// 33 | public Buffer Value { get => _buffer; } 34 | 35 | /// 36 | /// Gets the protocol error. 37 | /// 38 | public byte ProtocolError { get => _protocolError; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattServiceProviderAdvertisementStatus.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// This enumeration defines the advertisement status of a GattServiceProvider. 10 | /// 11 | public enum GattServiceProviderAdvertisementStatus 12 | { 13 | /// 14 | /// The GATT service was created. 15 | /// 16 | Created = 0, 17 | 18 | /// 19 | /// The GATT service is not advertising. 20 | /// 21 | Stopped = 1, 22 | 23 | /// 24 | /// The GATT service advertising has started. 25 | /// 26 | Started = 2, 27 | 28 | /// 29 | /// The GATT service was aborted. 30 | /// 31 | Aborted = 3, 32 | 33 | /// 34 | /// Indicates that the system was successfully able to issue the advertisement request, 35 | /// but not all of the requested data could be included in the advertisement. 36 | StartedWithoutAllAdvertisementData = 4 37 | } 38 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattServiceProviderAdvertisingParameters.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using nanoFramework.Device.Bluetooth.Advertisement; 7 | using System; 8 | 9 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 10 | { 11 | /// 12 | /// This class is used to define the GATT service advertisement parameters. 13 | /// 14 | public class GattServiceProviderAdvertisingParameters 15 | { 16 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 17 | private bool _isDiscoverable = true; 18 | 19 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 20 | private bool _isConnectable = true; 21 | 22 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 23 | private Buffer _serviceData; 24 | 25 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 26 | private BluetoothLEAdvertisement _advertisement; 27 | 28 | [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 29 | private bool _customAdvertisement; 30 | 31 | 32 | /// 33 | /// Creates a new object. 34 | /// 35 | public GattServiceProviderAdvertisingParameters() 36 | { 37 | _advertisement = new(); 38 | 39 | // Not a Custom advertisement, so set Flags & Local Name 40 | CustomAdvertisement = false; 41 | 42 | _isDiscoverable = true; 43 | } 44 | 45 | /// 46 | /// Gets or sets a boolean indicating that the GATT service is discoverable. 47 | /// 48 | public bool IsDiscoverable 49 | { 50 | get => _isDiscoverable; 51 | set 52 | { 53 | _isDiscoverable = value; 54 | if (_isDiscoverable) 55 | { 56 | _advertisement.Flags |= BluetoothLEAdvertisementFlags.GeneralDiscoverableMode; 57 | } 58 | else 59 | { 60 | _advertisement.Flags &= ~BluetoothLEAdvertisementFlags.GeneralDiscoverableMode; 61 | } 62 | } 63 | } 64 | 65 | /// 66 | /// Gets or sets a boolean that indicates if the GATT service is connect-able. 67 | /// 68 | public bool IsConnectable { get => _isConnectable; set => _isConnectable = value; } 69 | 70 | /// 71 | /// For Bluetooth Low Energy, this parameter adds an additional **ServiceData** section 72 | /// to the advertisement payload for the service's service UUID if space is available. 73 | /// If the service data is added to the advertisement, then the service UUID will 74 | /// also be included in the same section in the advertisement. 75 | /// 76 | public Buffer ServiceData { get => _serviceData; set => _serviceData = value; } 77 | 78 | /// 79 | /// Gets the underlying object for the to enable extra 80 | /// advertisement parameters to be set. 81 | /// 82 | public BluetoothLEAdvertisement Advertisement { get => _advertisement; } 83 | 84 | /// 85 | /// If set the will not be filled in with the default data sections only data sections from 86 | /// the property will be used. Default is . 87 | /// 88 | public bool CustomAdvertisement 89 | { 90 | get => _customAdvertisement; 91 | set 92 | { 93 | _customAdvertisement = value; 94 | if (_customAdvertisement) 95 | { 96 | // Remove default data sections 97 | Advertisement.RemoveSectionsOfType(BluetoothLEAdvertisementDataSectionType.Flags); 98 | Advertisement.RemoveSectionsOfType(BluetoothLEAdvertisementDataSectionType.CompleteLocalName); 99 | } 100 | else 101 | { 102 | // Add default data sections 103 | Advertisement.Flags = BluetoothLEAdvertisementFlags.ClassicNotSupported | 104 | BluetoothLEAdvertisementFlags.GeneralDiscoverableMode; 105 | 106 | // Set default device name 107 | Advertisement.LocalName = BluetoothLEServer.Instance.DeviceName; 108 | } 109 | } 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattServiceProviderResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// This class is the result of the Create operation. 12 | /// 13 | public class GattServiceProviderResult 14 | { 15 | private readonly GattServiceProvider _serviceProvider; 16 | private readonly BluetoothError _error; 17 | 18 | internal GattServiceProviderResult(GattServiceProvider serviceProvider, BluetoothError error) 19 | { 20 | _serviceProvider = serviceProvider; 21 | _error = error; 22 | } 23 | 24 | /// 25 | /// Gets the error. 26 | /// 27 | public BluetoothError Error { get => _error; } 28 | 29 | /// 30 | /// Gets the service provider. 31 | /// 32 | public GattServiceProvider ServiceProvider { get => _serviceProvider; } 33 | } 34 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattServiceUuids.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// Represents an enumeration of the most well known Service UUID values, and provides 12 | /// convenience methods for working with GATT service UUIDs, and static properties 13 | /// providing service UUIDs for common GATT services. To view a list of all Bluetooth 14 | /// SIG-defined service UUIDs, see Bluetooth SIG-defined Service UUIDs. 15 | /// See:- https://btprodspecificationrefs.blob.core.windows.net/assigned-values/16-bit%20UUID%20Numbers%20Document.pdf 16 | /// Current Service UUID 0x1800 to 0x181D 17 | /// 18 | public static class GattServiceUuids 19 | { 20 | /// 21 | /// Gets the Bluetooth SIG-defined AlertNotification Service UUID. 22 | /// 23 | public static Guid AlertNotification { get => Utilities.CreateUuidFromShortCode(0x1811); } 24 | 25 | /// 26 | /// Gets the Bluetooth SIG-defined Automation IO Service UUID. 27 | /// 28 | public static Guid AutomationIO { get => Utilities.CreateUuidFromShortCode(0x1815); } 29 | 30 | /// 31 | /// Gets the Bluetooth SIG-defined Battery Service UUID. 32 | /// 33 | public static Guid Battery { get => Utilities.CreateUuidFromShortCode(0x180f); } 34 | 35 | /// 36 | /// Gets the Bluetooth SIG-defined Blood Pressure Service UUID. 37 | /// 38 | public static Guid BloodPressure { get => Utilities.CreateUuidFromShortCode(0x1810); } 39 | 40 | /// 41 | /// Gets the Bluetooth SIG-defined Body Composition Service UUID. 42 | /// 43 | public static Guid BodyComposition { get => Utilities.CreateUuidFromShortCode(0x181b); } 44 | 45 | /// 46 | /// Gets the Bluetooth SIG-defined CurrentTime service UUID. 47 | /// 48 | public static Guid CurrentTime { get => Utilities.CreateUuidFromShortCode(0x1805); } 49 | 50 | /// 51 | /// Gets the Bluetooth SIG-defined CyclingPower service UUID. 52 | /// 53 | public static Guid CyclingPower { get => Utilities.CreateUuidFromShortCode(0x1818); } 54 | 55 | /// 56 | /// Gets the Bluetooth SIG-defined Cycling Speed And Cadence Service UUID. 57 | /// 58 | public static Guid CyclingSpeedAndCadence { get => Utilities.CreateUuidFromShortCode(0x1816); } 59 | 60 | /// 61 | /// Gets the Bluetooth SIG-defined DeviceInformation service UUID. 62 | /// 63 | public static Guid DeviceInformation { get => Utilities.CreateUuidFromShortCode(0x180a); } 64 | 65 | /// 66 | /// Gets the Bluetooth SIG-defined Environmental Sensing Service UUID. 67 | /// 68 | public static Guid EnvironmentalSensing { get => Utilities.CreateUuidFromShortCode(0x181a); } 69 | 70 | /// 71 | /// Gets the Bluetooth SIG-defined UUID for the Generic Access Service. 72 | /// 73 | public static Guid GenericAccess { get => Utilities.CreateUuidFromShortCode(0x1800); } 74 | 75 | /// 76 | /// Gets the Bluetooth SIG-defined UUID for the Generic Attribute Service. 77 | /// 78 | public static Guid GenericAttribute { get => Utilities.CreateUuidFromShortCode(0x1801); } 79 | 80 | /// 81 | /// Gets the Bluetooth SIG-defined Glucose Service UUID. 82 | /// 83 | public static Guid Glucose { get => Utilities.CreateUuidFromShortCode(0x1808); } 84 | 85 | /// 86 | /// Gets the Bluetooth SIG-defined Health Thermometer Service UUID. 87 | /// 88 | public static Guid HealthThermometer { get => Utilities.CreateUuidFromShortCode(0x1809); } 89 | 90 | /// 91 | /// Gets the Bluetooth SIG-defined Heart Rate Service UUID. 92 | /// 93 | public static Guid HeartRate { get => Utilities.CreateUuidFromShortCode(0x180d); } 94 | 95 | /// 96 | /// Gets the Bluetooth SIG-defined HumanInterfaceDevice service UUID. 97 | /// 98 | public static Guid HumanInterfaceDevice { get => Utilities.CreateUuidFromShortCode(0x1812); } 99 | 100 | /// 101 | /// Gets the Bluetooth SIG-defined ImmediateAlert service UUID. 102 | /// 103 | public static Guid ImmediateAlert { get => Utilities.CreateUuidFromShortCode(0x1802); } 104 | 105 | /// 106 | /// Gets the Bluetooth SIG-defined LinkLoss service UUID. 107 | /// 108 | public static Guid LinkLoss {get => Utilities.CreateUuidFromShortCode(0x1803); } 109 | 110 | /// 111 | /// Gets the Bluetooth SIG-defined LocationAndNavigation service UUID. 112 | /// 113 | public static Guid LocationAndNavigation { get => Utilities.CreateUuidFromShortCode(0x1819); } 114 | 115 | /// 116 | /// Gets the Bluetooth SIG-defined NextDstChange service UUID. 117 | /// 118 | public static Guid NextDstChange { get => Utilities.CreateUuidFromShortCode(0x1807); } 119 | 120 | /// 121 | /// Gets the Bluetooth SIG-defined PhoneAlertStatus service UUID. 122 | /// 123 | public static Guid PhoneAlertStatus { get => Utilities.CreateUuidFromShortCode(0x180e); } 124 | 125 | /// 126 | /// Gets the Bluetooth SIG-defined ReferenceTimeUpdate service UUID. 127 | /// 128 | public static Guid ReferenceTimeUpdate { get => Utilities.CreateUuidFromShortCode(0x1806); } 129 | 130 | /// 131 | /// Gets the Bluetooth SIG-defined Running Speed And Cadence Service UUID. 132 | /// 133 | public static Guid RunningSpeedAndCadence { get => Utilities.CreateUuidFromShortCode(0x1814); } 134 | 135 | /// 136 | /// Gets the Bluetooth SIG-defined ScanParameters service UUID. 137 | /// 138 | public static Guid ScanParameters { get => Utilities.CreateUuidFromShortCode(0x1813); } 139 | 140 | /// 141 | /// Gets the Bluetooth SIG-defined TxPower service UUID. 142 | /// 143 | public static Guid TxPower { get => Utilities.CreateUuidFromShortCode(0x1804); } 144 | 145 | /// 146 | /// Gets the Bluetooth SIG-defined User Data service UUID. 147 | /// 148 | public static Guid UserData { get => Utilities.CreateUuidFromShortCode(0x181c); } 149 | 150 | /// 151 | /// Gets the Bluetooth SIG-defined Weight Scale service UUID. 152 | /// 153 | public static Guid WeightScale { get => Utilities.CreateUuidFromShortCode(0x181d); } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattSession.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// This class represents a GATT session. 12 | /// 13 | public class GattSession 14 | { 15 | private readonly BluetoothDeviceId _deviceId; 16 | private ushort _maxMtuSize; 17 | 18 | /// 19 | /// Delegate for events. 20 | /// 21 | /// sending event. 22 | /// Event arguments. 23 | public delegate void GattSessionStatusChangedEventHandler(Object sender, GattSessionStatusChangedEventArgs args); 24 | 25 | /// 26 | /// Session status change event. 27 | /// 28 | public event GattSessionStatusChangedEventHandler SessionStatusChanged; 29 | 30 | /// 31 | /// An event that is raised when the maximum protocol data unit (PDU) size changes. 32 | /// The PDU is also known as the maximum transmission unit (MTU). 33 | /// 34 | public event EventHandler MaxPduSizeChanged; 35 | 36 | /// 37 | /// Creates a new object from the specified deviceId. 38 | /// 39 | /// The deviceId. 40 | /// A new object. 41 | public static GattSession FromDeviceId(BluetoothDeviceId deviceId) 42 | { 43 | return new GattSession(deviceId); 44 | } 45 | 46 | internal GattSession(BluetoothDeviceId deviceId) 47 | { 48 | _deviceId = deviceId; 49 | } 50 | 51 | internal void OnEvent(BluetoothEventSesssion btEvent) 52 | { 53 | //Debug.WriteLine($"# GattServiceProvider OnEvent, type:{btEvent.type} status:{btEvent.status}"); 54 | 55 | switch (btEvent.type) 56 | { 57 | case BluetoothEventType.ClientConnected: 58 | SessionStatusChanged?.Invoke(this, new GattSessionStatusChangedEventArgs(GattSessionStatus.Active, 0)); 59 | break; 60 | 61 | case BluetoothEventType.ClientDisconnected: 62 | SessionStatusChanged?.Invoke(this, new GattSessionStatusChangedEventArgs(GattSessionStatus.Closed, 0)); 63 | break; 64 | 65 | case BluetoothEventType.ClientSessionChanged: 66 | // Update max MTU size in GattSession 67 | _maxMtuSize = btEvent.data; 68 | MaxPduSizeChanged?.Invoke(this, EventArgs.Empty); 69 | break; 70 | } 71 | } 72 | 73 | /// 74 | /// Gets the device id. 75 | /// 76 | public BluetoothDeviceId DeviceId { get => _deviceId; } 77 | 78 | /// 79 | /// Gets the maximum transmission unit (MTU) size. 80 | /// 81 | public ushort MaxMtuSize { get => _maxMtuSize; } 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattSessionStatus.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// This enumeration defines a GattSession status. 10 | /// 11 | public enum GattSessionStatus 12 | { 13 | /// 14 | /// The GATT session is closed. 15 | /// 16 | Closed = 0, 17 | 18 | /// 19 | /// The GATT session is active. 20 | /// 21 | Active = 1 22 | } 23 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattSessionStatusChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// This class represents the SessionStatusChanged event args. 10 | /// 11 | public class GattSessionStatusChangedEventArgs 12 | { 13 | private readonly GattSessionStatus _status; 14 | private readonly BluetoothError _bluetoothError; 15 | 16 | internal GattSessionStatusChangedEventArgs(GattSessionStatus status, BluetoothError bluetoothError) 17 | { 18 | _status = status; 19 | _bluetoothError = bluetoothError; 20 | } 21 | 22 | /// 23 | /// Gets the status of the GATT session. 24 | /// 25 | public GattSessionStatus Status { get => _status; } 26 | 27 | /// 28 | /// Gets the error of the GATT session. 29 | /// 30 | public BluetoothError Error { get => _bluetoothError; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattSubscribedClient.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// This class represents a subscribed client of a GATT session. 10 | /// 11 | public class GattSubscribedClient 12 | { 13 | private readonly GattSession _session; 14 | 15 | internal GattSubscribedClient(GattSession session) 16 | { 17 | _session = session; 18 | } 19 | 20 | /// 21 | /// Gets the maximum notification size. 22 | /// 23 | public ushort MaxNotificationSize { get => 1024; } 24 | 25 | /// 26 | /// Gets the session of the subscribed client. 27 | /// 28 | public GattSession Session { get => _session; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattValueChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// Represents the arguments received by a GattCharacteristic.ValueChanged event 12 | /// handler used to process characteristic value change notification and indication 13 | /// events sent by a Bluetooth LE device. 14 | /// 15 | public class GattValueChangedEventArgs 16 | { 17 | Buffer _buffer; 18 | DateTime _timeStammp; 19 | 20 | internal GattValueChangedEventArgs(Buffer value, DateTime timeStammp) 21 | { 22 | _buffer = value; 23 | _timeStammp = timeStammp; 24 | } 25 | 26 | /// 27 | /// Gets the new Characteristic Value. 28 | /// 29 | public Buffer CharacteristicValue { get => _buffer; } 30 | 31 | /// 32 | /// Gets the time at which the system was notified of the Characteristic Value change. 33 | /// 34 | public DateTime Timestamp { get => _timeStammp; } 35 | } 36 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattWriteOption.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// Indicates what type of write operation is to be performed. 10 | /// 11 | public enum GattWriteOption 12 | { 13 | /// 14 | /// The default GATT write procedure shall be used. 15 | /// 16 | WriteWithResponse = 0, 17 | 18 | /// 19 | /// The Write Without Response procedure shall be used. 20 | /// 21 | WriteWithoutResponse = 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattWriteRequest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | using System.Runtime.CompilerServices; 8 | 9 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 10 | { 11 | /// 12 | /// This class represents a GATT write request. 13 | /// 14 | public class GattWriteRequest 15 | { 16 | private readonly GattWriteOption _option = GattWriteOption.WriteWithResponse; 17 | private readonly uint _offset = 0; 18 | private readonly Buffer _value = null; 19 | 20 | private readonly ushort _eventID; 21 | 22 | internal GattWriteRequest(ushort eventID) 23 | { 24 | _eventID = eventID; 25 | 26 | // Get a copy of data from Native for this event 27 | byte[] data = NativeWriteGetData(eventID); 28 | 29 | // and save it 30 | _value = new Buffer(data); 31 | } 32 | 33 | /// 34 | /// Responds to the write request. 35 | /// 36 | public void Respond() 37 | { 38 | NativeWriteRespond(_eventID); 39 | } 40 | 41 | /// 42 | /// Responds with a protocol error. 43 | /// 44 | /// Error byte 45 | public void RespondWithProtocolError(byte protocolError) 46 | { 47 | NativeWriteRespondWithProtocolError(_eventID, protocolError); 48 | } 49 | 50 | /// 51 | /// Gets the offset. 52 | /// 53 | public uint Offset { get => _offset; } 54 | 55 | /// 56 | /// Gets the write request option. 57 | /// 58 | public GattWriteOption Option { get => _option; } 59 | 60 | /// 61 | /// Gets the buffer value of the write request. 62 | /// 63 | public Buffer Value { get => _value; } 64 | 65 | #region external calls to native implementations 66 | 67 | [MethodImpl(MethodImplOptions.InternalCall)] 68 | private extern byte[] NativeWriteGetData(ushort eventID); 69 | 70 | [MethodImpl(MethodImplOptions.InternalCall)] 71 | private extern void NativeWriteRespond(ushort eventID); 72 | 73 | [MethodImpl(MethodImplOptions.InternalCall)] 74 | private extern void NativeWriteRespondWithProtocolError(ushort eventID, byte protocolError); 75 | 76 | #endregion 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattWriteRequestedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// This class represents the event arguments for WriteRequested. 12 | /// 13 | public class GattWriteRequestedEventArgs 14 | { 15 | private readonly ushort _eventID; 16 | private readonly GattSession _session = null; 17 | 18 | internal GattWriteRequestedEventArgs(ushort eventID, GattSession session) 19 | { 20 | _eventID = eventID; 21 | _session = session; 22 | } 23 | 24 | /// 25 | /// Gets the write request. 26 | /// 27 | /// Returns a write request. 28 | public GattWriteRequest GetRequest() 29 | { 30 | return new GattWriteRequest(_eventID); 31 | } 32 | 33 | /// 34 | /// Gets the session. 35 | /// 36 | public GattSession Session { get => _session; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattWriteResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 7 | { 8 | /// 9 | /// Contains the result of GATT write operations like WriteValueWithResult. 10 | /// 11 | public class GattWriteResult 12 | { 13 | private readonly GattCommunicationStatus _status; 14 | private readonly byte _protocolError; 15 | 16 | internal GattWriteResult(GattCommunicationStatus status, byte protocolError) 17 | { 18 | _status = status; 19 | _protocolError = protocolError; 20 | } 21 | 22 | /// 23 | /// Gets the protocol error. 24 | /// 25 | public byte ProtocolError { get => _protocolError; } 26 | 27 | /// 28 | /// Gets the status of the write result. 29 | /// 30 | public GattCommunicationStatus Status { get => _status; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/GenericAttributeProfile/IGattAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile 9 | { 10 | /// 11 | /// Interface for all attributes ( Services, Characteristics, Descriptors ) 12 | /// 13 | public interface IGattAttribute 14 | { 15 | /// 16 | /// Unique Attribute handle. 17 | /// 18 | public ushort AttributeHandle { get; } 19 | 20 | /// 21 | /// UUID of Attribute. 22 | /// 23 | public Guid Uuid { get; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/IO/Buffer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace nanoFramework.Device.Bluetooth 5 | { 6 | /// 7 | /// Represents a referenced array of bytes used by byte stream read and write interfaces. 8 | /// 9 | public class Buffer 10 | { 11 | /// 12 | /// Byte buffer 13 | /// 14 | private byte[] _buffer; 15 | 16 | /// 17 | /// Length of data in byte buffer. 18 | /// 19 | protected uint _length; 20 | 21 | /// 22 | /// Constructor for Buffer with a specific capacity. 23 | /// 24 | /// 25 | public Buffer(uint capacity) 26 | { 27 | _buffer = new byte[capacity]; 28 | _length = 0; 29 | } 30 | 31 | /// 32 | /// Constructor for Buffer with an external byte buffer. 33 | /// 34 | /// 35 | public Buffer(byte[] array) 36 | { 37 | _buffer = array; 38 | _length = (uint)array.Length; 39 | } 40 | 41 | /// 42 | /// Gets the maximum number of bytes that the buffer can hold. 43 | /// 44 | public uint Capacity { get => (uint)_buffer.Length; } 45 | 46 | /// 47 | /// Gets the number of bytes currently in use in the buffer. 48 | /// 49 | public uint Length 50 | { 51 | get => _length; 52 | set 53 | { 54 | if (value > _buffer.Length || value < 0) 55 | { 56 | throw new ArgumentException("Length greater than current buffer"); 57 | } 58 | 59 | _length = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Ensure buffer has a certain capacity. If to small it will be expanded 65 | /// 66 | /// New capacity required 67 | public void EnsureCapacity(uint newCapacity) 68 | { 69 | if (newCapacity > _buffer.Length) 70 | { 71 | Byte[] newBuffer = new Byte[newCapacity]; 72 | Array.Copy(_buffer, 0, newBuffer, 0, _buffer.Length); 73 | _buffer = newBuffer; 74 | } 75 | } 76 | 77 | internal byte[] Data { get => _buffer; } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System.Reflection; 7 | using System.Runtime.CompilerServices; 8 | using System.Runtime.InteropServices; 9 | 10 | // General Information about an assembly is controlled through the following 11 | // set of attributes. Change these attribute values to modify the information 12 | // associated with an assembly. 13 | [assembly: AssemblyTitle("nanoFramework.Device.Bluetooth")] 14 | [assembly: AssemblyCompany("nanoFramework Contributors")] 15 | [assembly: AssemblyProduct("nanoFramework.Device.Bluetooth")] 16 | [assembly: AssemblyCopyright("Copyright (c) .NET Foundation and Contributors")] 17 | 18 | //////////////////////////////////////////////////////////////// 19 | // update this whenever the native assembly signature changes // 20 | [assembly: AssemblyNativeVersion("100.0.5.0")] 21 | //////////////////////////////////////////////////////////////// 22 | 23 | 24 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/SPP/IBluetoothSpp.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | 8 | namespace nanoFramework.Device.Bluetooth.Spp 9 | { 10 | /// 11 | /// Interface for Bluetooth Serial Profile (SPP) 12 | /// 13 | public interface IBluetoothSpp 14 | { 15 | /// 16 | /// Receive data delegate. 17 | /// 18 | /// 19 | /// 20 | public delegate void RxDataEventHandler(IBluetoothSpp sender, SppReceivedDataEventArgs ReadDataEventArgs); 21 | 22 | /// 23 | /// Connected client status changed delegate. 24 | /// 25 | /// 26 | /// 27 | public delegate void ConnectedEventHandler(IBluetoothSpp sender, EventArgs e); 28 | 29 | /// 30 | /// Received data event. Event is fired when data is received. 31 | /// 32 | public event RxDataEventHandler ReceivedData; 33 | 34 | /// 35 | /// Connected client status changed event, Fired when client connects or disconnects. 36 | /// Check isConnected property for current status. 37 | /// 38 | public event ConnectedEventHandler ConnectedEvent; 39 | 40 | /// 41 | /// Returns true is a client is connected. 42 | /// 43 | bool IsConnected{ get; } 44 | 45 | /// 46 | /// Start the SPP advertising. 47 | /// 48 | /// Device name to use in advert. 49 | /// 50 | bool Start(string deviceName); 51 | 52 | /// 53 | /// Stop advertising and close down. 54 | /// 55 | void Stop(); 56 | 57 | /// 58 | /// Send bytes to connected client. 59 | /// 60 | /// Byte[] to send. 61 | /// True if send was successful. 62 | bool SendBytes(byte[] data); 63 | 64 | /// 65 | /// Send string to connected client. 66 | /// 67 | /// String data to send. 68 | /// True if send was successful. 69 | bool SendString(string data); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/SPP/SppReceiveEventArgs.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | using System.Text; 8 | 9 | namespace nanoFramework.Device.Bluetooth.Spp 10 | { 11 | /// 12 | /// Event argument for SPP receive data events 13 | /// 14 | public class SppReceivedDataEventArgs 15 | { 16 | private readonly byte[] _data; 17 | 18 | internal SppReceivedDataEventArgs(byte[] data) 19 | { 20 | _data = data; 21 | } 22 | 23 | /// 24 | /// Received data as byte[]. 25 | /// 26 | public byte[] DataBytes { get => _data; } 27 | 28 | /// 29 | /// Received data as string. 30 | /// 31 | public String DataString { get => Encoding.UTF8.GetString(_data, 0, _data.Length); } 32 | } 33 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Security/DeviceBonding.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | using System.Runtime.CompilerServices; 8 | 9 | namespace nanoFramework.Device.Bluetooth.Security 10 | { 11 | /// 12 | /// Class to encapsulate the bond store access. 13 | /// 14 | public static class DeviceBonding 15 | { 16 | /// 17 | /// Check if bluetooth address bonded. 18 | /// 19 | /// Bluetooth address to check. 20 | /// True if bonded. 21 | [MethodImpl(MethodImplOptions.InternalCall)] 22 | public static extern bool IsBonded(ulong bluetoothAddress); 23 | 24 | /// 25 | /// Deletes all stored bonds. 26 | /// 27 | [MethodImpl(MethodImplOptions.InternalCall)] 28 | public static extern void DeleteAllBonds(); 29 | 30 | /// 31 | /// Deletes bond information for peer. 32 | /// 33 | /// Peer's Bluetooth address. 34 | /// Type of Bluetooth address. 35 | [MethodImpl(MethodImplOptions.InternalCall)] 36 | public static extern void DeleteBondForPeer(ulong peerbluetoothAddress, BluetoothAddressType addressType); 37 | 38 | /// 39 | /// Returns the number of stored bonds. 40 | /// 41 | /// Bond count. 42 | [MethodImpl(MethodImplOptions.InternalCall)] 43 | public static extern int Count(); 44 | 45 | /// 46 | /// Get Bonding address for peer at index. 47 | /// 48 | /// The index. 49 | /// The bonded address. 50 | /// Index out range. 51 | /// Bluetooth Stack is not running. run BluetoothLEServer.Start(). 52 | [MethodImpl(MethodImplOptions.InternalCall)] 53 | public static extern ulong GetBondInformationAt(int index); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Security/DevicePairingEventArgs.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | using System.Runtime.CompilerServices; 8 | using System.Text; 9 | 10 | namespace nanoFramework.Device.Bluetooth 11 | { 12 | /// 13 | /// This class contains the arguments for the Pairing Complete event. 14 | /// 15 | public class DevicePairingEventArgs 16 | { 17 | private readonly ushort _connectionHandle; 18 | private readonly DevicePairingResultStatus _status; 19 | 20 | internal DevicePairingEventArgs(ushort connectionHandle, DevicePairingResultStatus status) 21 | { 22 | _connectionHandle = connectionHandle; 23 | _status = status; 24 | } 25 | 26 | /// 27 | /// Status code of Pairing operation. 28 | /// 29 | public DevicePairingResultStatus Status { get { return _status; } } 30 | } 31 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Security/DevicePairingIOCapabilities.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth 7 | { 8 | /// 9 | /// Kinds of IO capabilties used for pairing. 10 | /// 11 | public enum DevicePairingIOCapabilities 12 | { 13 | /// 14 | /// Device has just a display. 15 | /// 16 | DisplayOnly = 0, 17 | 18 | /// 19 | /// Device can output numeric data and has a way to input a Yes or No (buttons). 20 | /// 21 | DisplayYesNo = 1, 22 | 23 | /// 24 | /// Device has keyboard. 25 | /// 26 | KeyboardOnly = 2, 27 | 28 | /// 29 | /// Device has no output or input. 30 | /// All pairing uses Just Works. 31 | /// 32 | NoInputNoOutput = 3, 33 | 34 | /// 35 | /// Device has Keyboard and Display (input/Output). 36 | /// 37 | KeyboardDisplay = 4 38 | } 39 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Security/DevicePairingKinds .cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth 7 | { 8 | /// 9 | /// Kinds of paring. 10 | /// 11 | public enum DevicePairingKinds 12 | { 13 | /// 14 | /// No pairing is supported. 15 | /// 16 | None, 17 | 18 | /// 19 | /// The application must confirm they wish to perform the pairing action. You can present an optional confirmation dialog to the user. 20 | /// With a value of ConfirmOnly, call Accept from the event args of the PairingRequested event handler if you want the pairing to complete. 21 | /// 22 | ConfirmOnly = 1, 23 | 24 | /// 25 | /// The application must display the given PIN to the user. The user will then need to enter or confirm that PIN on the device that is being paired. 26 | /// With a value of DisplayPin, call Accept from the event args of the PairingRequested event handler if you want the pairing to complete. 27 | /// If your application cancels the pairing at this point, the device might still be paired. This is because the system and the target 28 | /// device don't need any confirmation for this DevicePairingKinds value. 29 | /// 30 | DisplayPin = 2, 31 | 32 | /// 33 | /// The application must request a PIN from the user. The PIN will typically be displayed on the target device. With a value of ProvidePin, 34 | /// call Accept from the event args of the PairingRequested event handler if you want the pairing to complete. Pass in the PIN as a parameter. 35 | /// 36 | ProvidePin = 4, 37 | 38 | /// 39 | /// The application must display the given PIN to the user and ask the user to confirm that the PIN matches the one show on the target device. 40 | /// With a value of ConfirmPinMatch, call Accept from the event args of the PairingRequested event handler if you want the pairing to complete. 41 | /// 42 | ConfirmPinMatch = 8, 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Security/DevicePairingProtectionLevel.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth 7 | { 8 | /// 9 | /// The level of protection for pairing. 10 | /// 11 | public enum DevicePairingProtectionLevel 12 | { 13 | /// 14 | /// The default value. This should not be used. 15 | /// 16 | Default = 0, 17 | 18 | /// 19 | /// Pair the device using no levels of protection. 20 | /// 21 | None = 1, 22 | 23 | /// 24 | /// Pair the device using encryption. 25 | /// 26 | Encryption = 2, 27 | 28 | /// 29 | /// Pair the device using encryption and authentication. 30 | /// 31 | EncryptionAndAuthentication = 3 32 | } 33 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Security/DevicePairingRequestedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System; 7 | using System.Runtime.CompilerServices; 8 | using System.Text; 9 | 10 | namespace nanoFramework.Device.Bluetooth 11 | { 12 | /// 13 | /// This class contains the arguments for the Pairing event. 14 | /// 15 | public class DevicePairingRequestedEventArgs 16 | { 17 | private readonly DevicePairing _pairing; 18 | private readonly ushort _connectionHandle; 19 | private readonly DevicePairingKinds _kind; 20 | private readonly uint _pin; 21 | 22 | internal DevicePairingRequestedEventArgs(DevicePairing pairing, ushort connectionHandle, DevicePairingKinds kind, uint pin) 23 | { 24 | _pairing = pairing; 25 | _connectionHandle = connectionHandle; 26 | _kind = kind; 27 | _pin = pin; 28 | } 29 | 30 | /// 31 | /// Gets the kind of pairing associated with this pairing event. 32 | /// 33 | public DevicePairingKinds PairingKind { get => _kind; } 34 | 35 | /// 36 | /// Gets the pin associated with a pairing request. 37 | /// 38 | public uint Pin { get => _pin; } 39 | 40 | /// 41 | /// Accepts a PairingRequested event and pairs the device with the application. 42 | /// 43 | public void Accept() 44 | { 45 | NativeAcceptYesNo(_connectionHandle, _kind, 1); 46 | } 47 | 48 | /// 49 | /// Accepts a PairingRequested event and pairs the device with the application. 50 | /// Requires a passkey for pairing purposes. 51 | /// 52 | /// The pass key for pairing. 53 | public void Accept(int passkey) 54 | { 55 | NativeAcceptPasskey(_connectionHandle, _kind, passkey); 56 | } 57 | 58 | /// 59 | /// Accepts a PairingRequested event and pairs the device with the application when 60 | /// a user name and password is required for pairing purposes. 61 | /// 62 | /// The password credential. 63 | public void AcceptWithPasswordCredential(PasswordCredential password) 64 | { 65 | NativeAcceptCredentials(_connectionHandle, _kind, Encoding.UTF8.GetBytes(password.UserName), Encoding.UTF8.GetBytes(password.Password)); 66 | } 67 | 68 | #region external calls to native implementations 69 | 70 | [MethodImpl(MethodImplOptions.InternalCall)] 71 | private extern ushort NativeAcceptYesNo(ushort connectionHandle, DevicePairingKinds kind, int YesNo); 72 | 73 | [MethodImpl(MethodImplOptions.InternalCall)] 74 | private extern ushort NativeAcceptPasskey(ushort connectionHandle, DevicePairingKinds kind, int passkey); 75 | 76 | [MethodImpl(MethodImplOptions.InternalCall)] 77 | private extern ushort NativeAcceptCredentials(ushort connectionHandle, DevicePairingKinds kind, byte[] username, byte[] password); 78 | 79 | #endregion 80 | } 81 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Security/DevicePairingResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth 7 | { 8 | /// 9 | /// Contains information about the result of attempting to pair a device. 10 | /// 11 | public class DevicePairingResult 12 | { 13 | private readonly DevicePairingProtectionLevel _protectionLevelUsed; 14 | private readonly DevicePairingResultStatus _status; 15 | 16 | internal DevicePairingResult(DevicePairingProtectionLevel protectionLevelUsed, DevicePairingResultStatus status) 17 | { 18 | _protectionLevelUsed = protectionLevelUsed; 19 | _status = status; 20 | } 21 | 22 | /// 23 | /// Gets the level of protection used to pair the device. 24 | /// 25 | public DevicePairingProtectionLevel ProtectionLevelUsed { get => _protectionLevelUsed; } 26 | 27 | /// 28 | /// Gets the paired status of the device after the pairing action completed. 29 | /// 30 | public DevicePairingResultStatus Status { get => _status; } 31 | } 32 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Security/DevicePairingResultStatus.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth 7 | { 8 | /// 9 | /// The result of the pairing action. 10 | /// 11 | public enum DevicePairingResultStatus 12 | { 13 | /// 14 | /// The device object is now paired. 15 | /// 16 | Paired = 0, 17 | 18 | /// 19 | /// The device object is not in a state where it can be paired. 20 | /// 21 | NotReadyToPair = 1, 22 | 23 | /// 24 | /// The device object is not currently paired. 25 | /// 26 | NotPaired = 2, 27 | 28 | /// 29 | /// The device object has already been paired. 30 | /// 31 | AlreadyPaired = 3, 32 | 33 | /// 34 | /// The device object rejected the connection. 35 | /// 36 | ConnectionRejected = 4, 37 | 38 | /// 39 | /// The device object indicated it cannot accept any more incoming connections. 40 | /// 41 | TooManyConnections = 5, 42 | 43 | /// 44 | /// The device object indicated there was a hardware failure. 45 | /// 46 | HardwareFailure = 6, 47 | 48 | /// 49 | /// The authentication process timed out before it could complete. 50 | /// 51 | AuthenticationTimeout = 7, 52 | 53 | /// 54 | /// The authentication protocol is not supported, so the device is not paired. 55 | /// 56 | AuthenticationNotAllowed = 8, 57 | 58 | /// 59 | /// Authentication failed, so the device is not paired. Either the device object 60 | /// or the application rejected the authentication. 61 | /// 62 | AuthenticationFailure = 9, 63 | 64 | /// 65 | /// here are no network profiles for this device object to use. 66 | /// 67 | NoSupportedProfiles = 10, 68 | 69 | /// 70 | /// The minimum level of protection is not supported by the device object or the 71 | /// application. 72 | /// 73 | ProtectionLevelCouldNotBeMet = 11, 74 | 75 | /// 76 | /// Your application does not have the appropriate permissions level to pair the 77 | /// device object. 78 | /// 79 | AccessDenied = 12, 80 | 81 | /// 82 | /// The ceremony data was incorrect. 83 | /// 84 | InvalidCeremonyData = 13, 85 | 86 | /// 87 | /// The pairing action was cancelled before completion. 88 | /// 89 | PairingCanceled = 14, 90 | 91 | /// 92 | /// The device object is already attempting to pair or unpair. 93 | /// 94 | OperationAlreadyInProgress = 15, 95 | 96 | /// 97 | /// Either the event handler wasn't registered or a required DevicePairingKinds was 98 | /// not supported. 99 | /// 100 | RequiredHandlerNotRegistered = 16, 101 | 102 | /// 103 | /// The application handler rejected the pairing. 104 | /// 105 | RejectedByHandler = 17, 106 | 107 | /// 108 | /// The remove device already has an association. 109 | /// 110 | RemoteDeviceHasAssociation = 18, 111 | 112 | /// 113 | /// An unknown failure occurred. 114 | /// 115 | Failed = 19 116 | } 117 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Security/DeviceUnpairingResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth 7 | { 8 | /// 9 | /// Contains information about the result of attempting to unpair a device. 10 | /// 11 | public class DeviceUnpairingResult 12 | { 13 | private readonly DeviceUnpairingResultStatus _status; 14 | 15 | internal DeviceUnpairingResult(DeviceUnpairingResultStatus status) 16 | { 17 | _status = status; 18 | } 19 | 20 | 21 | /// 22 | /// Gets the paired status of the device after the pairing action completed. 23 | /// 24 | public DeviceUnpairingResultStatus Status => _status; 25 | } 26 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Security/DeviceUnpairingResultStatus.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth 7 | { 8 | /// 9 | /// The result of the unpairing action. 10 | /// 11 | public enum DeviceUnpairingResultStatus 12 | { 13 | /// 14 | /// The device object is successfully unpaired. 15 | /// 16 | Unpaired = 0, 17 | 18 | /// 19 | /// The device object is already unpaired. 20 | /// 21 | AlreadyUnpaired = 1, 22 | 23 | /// 24 | /// Upairing operation already in progress. 25 | /// 26 | OperationAlreadyInProgress = 2, 27 | 28 | /// 29 | /// The caller does not have sufficient permissions to unpair the device. 30 | /// 31 | AccessDenied = 3, 32 | 33 | /// 34 | /// An unknown failure occurred. 35 | /// 36 | Failed = 4 37 | } 38 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/Security/PasswordCredential.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) .NET Foundation and Contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace nanoFramework.Device.Bluetooth 7 | { 8 | /// 9 | /// Class to hold password credentials. 10 | /// 11 | public class PasswordCredential 12 | { 13 | private readonly string _username; 14 | private readonly string _password; 15 | 16 | /// 17 | /// Constructs a Password Credential. 18 | /// 19 | /// User name in credential. 20 | /// Password for user name. 21 | public PasswordCredential(string userName, string password) 22 | { 23 | _username = userName; 24 | _password = password; 25 | } 26 | 27 | /// 28 | /// Gets password from Credential. 29 | /// 30 | public string Password { get => _password; } 31 | 32 | /// 33 | /// Gets User name from Credential. 34 | /// 35 | public string UserName { get => _username; } 36 | } 37 | } -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanoframework/nanoFramework.Device.Bluetooth/2d3570a78f84764b9bf234b665ae319a3e9ca216/nanoFramework.Device.Bluetooth/key.snk -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /nanoFramework.Device.Bluetooth/packages.lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "dependencies": { 4 | ".NETnanoFramework,Version=v1.0": { 5 | "nanoFramework.CoreLibrary": { 6 | "type": "Direct", 7 | "requested": "[1.17.11, 1.17.11]", 8 | "resolved": "1.17.11", 9 | "contentHash": "HezzAc0o2XrSGf85xSeD/6xsO6ohF9hX6/iMQ1IZS6Zw6umr4WfAN2Jv0BrPxkaYwzEegJxxZujkHoUIAqtOMw==" 10 | }, 11 | "nanoFramework.Runtime.Events": { 12 | "type": "Direct", 13 | "requested": "[1.11.32, 1.11.32]", 14 | "resolved": "1.11.32", 15 | "contentHash": "NyLUIwJDlpl5VKSd+ljmdDtO2WHHBvPvruo1ccaL+hd79z+6XMYze1AccOVXKGiZenLBCwDmFHwpgIQyHkM7GA==" 16 | }, 17 | "nanoFramework.Runtime.Native": { 18 | "type": "Direct", 19 | "requested": "[1.7.11, 1.7.11]", 20 | "resolved": "1.7.11", 21 | "contentHash": "XPSTltZ9KeBruogVmjQpCphi1nLoJH49mpyp2eGBs8BTjKuL5TkMO20MoI8r73F/PW5AppTq49HvIZZavU5nPQ==" 22 | }, 23 | "nanoFramework.System.Collections": { 24 | "type": "Direct", 25 | "requested": "[1.5.67, 1.5.67]", 26 | "resolved": "1.5.67", 27 | "contentHash": "MjSipUB70vrxjqTm1KfKTUqqjd0wbweiNyYFXONi0XClrH6HXsuX2lhDqXM8NWuYnWyYOqx8y20sXbvsH+4brg==" 28 | }, 29 | "nanoFramework.System.Text": { 30 | "type": "Direct", 31 | "requested": "[1.3.42, 1.3.42]", 32 | "resolved": "1.3.42", 33 | "contentHash": "68HPjhersNpssbmEMUHdMw3073MHfGTfrkbRk9eILKbNPFfPFck7m4y9BlAi6DaguUJaeKxgyIojXF3SQrF8/A==" 34 | }, 35 | "Nerdbank.GitVersioning": { 36 | "type": "Direct", 37 | "requested": "[3.7.115, 3.7.115]", 38 | "resolved": "3.7.115", 39 | "contentHash": "EpXamaAdRfG/BMxGgvZlTM0npRnkmXUjAj8OdNKd17t4oN+2nvjdv/KnFmzOOMDqvlwB49UCwtOHJrAQTfUBtQ==" 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", 3 | "version": "1.1", 4 | "assemblyVersion": { 5 | "precision": "build" 6 | }, 7 | "semVer1NumericIdentifierPadding": 3, 8 | "nuGetPackageVersion": { 9 | "semVer": 2.0 10 | }, 11 | "publicReleaseRefSpec": [ 12 | "^refs/heads/main$", 13 | "^refs/heads/v\\d+(?:\\.\\d+)?$" 14 | ], 15 | "cloudBuild": { 16 | "setAllVariables": true, 17 | "buildNumber": null 18 | }, 19 | "release": { 20 | "branchName": "release-v{version}", 21 | "versionIncrement": "build", 22 | "firstUnstableTag": "preview" 23 | } 24 | } 25 | --------------------------------------------------------------------------------