Initial Bluetooth project (#1)
* Main project * No change * Required files * Test project * Update from review part 1 * @AdrianSoundy Update from review part 2 Removed sealed from some classes Remove SPP device Update Readme.md * Update for review part 3 Service UUIDs * Update README.md - Fix build badges. ***NO_CI*** * Update UUID classes * Add back SPP classes * Update nanoFramework.Device.Bluetooth.nuspec Co-authored-by: José Simões <jose.simoes@eclo.solutions> * Update nanoFramework.Device.Bluetooth.nuspec Co-authored-by: José Simões <jose.simoes@eclo.solutions> * Update nanoFramework.Device.Bluetooth/nanoFramework.Device.Bluetooth.nfproj Co-authored-by: José Simões <jose.simoes@eclo.solutions> * Fix URL and typo * Replace logo * Migrate project to allow VS2022 * Update Readme.md and SPP in project * Fix welcome in Readme.md * Update nuspec and readme * Latest update Disable tests for now. Fix project file, add XML docs Co-authored-by: José Simões <jose.simoes@eclo.solutions>
This commit is contained in:
Родитель
a1c611d5f4
Коммит
5baa6e1900
|
@ -0,0 +1,13 @@
|
|||
user=nanoframework
|
||||
project=nanoframework.Device.Bluetooth
|
||||
issues=true
|
||||
add_issues_wo_labels=false
|
||||
add_pr_wo_labels=false
|
||||
add_issues_wo_labels=false
|
||||
filter_issues_by_milestone=false
|
||||
exclude_labels=Area: Config-and-Build,Area: Infrastructure-and-Organization,reverted
|
||||
enhancement_labels=Type: enhancement
|
||||
bug_labels=Type: bug
|
||||
merge_prefix=**Documentation and other chores:**
|
||||
unreleased_label=**Changes available only in 'Preview' NuGet packages:**
|
||||
author=false
|
|
@ -0,0 +1,258 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# DNX
|
||||
project.lock.json
|
||||
artifacts/
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignoreable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
orleans.codegen.cs
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
#SoundCloud
|
||||
*.sonarqube/
|
||||
|
||||
#VS Code
|
||||
.vscode
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) .NET Foundation and Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
|
||||
<ItemGroup>
|
||||
<ProjectCapability Include="TestContainer" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<ProjectGuid>f13430a1-c6f5-47d8-bcec-8b601cf9149b</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<RootNamespace>NFUnitTest1</RootNamespace>
|
||||
<AssemblyName>NFUnitTest</AssemblyName>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
|
||||
<PropertyGroup>
|
||||
<RunSettingsFilePath>$(MSBuildProjectDirectory)\nano.runsettings</RunSettingsFilePath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="UnitTest1.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib, Version=1.10.5.4, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.CoreLibrary.1.10.5\lib\mscorlib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<SpecificVersion>True</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.System.Text, Version=1.1.1.3, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.System.Text.1.1.1\lib\nanoFramework.System.Text.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<SpecificVersion>True</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.TestFramework, Version=1.0.150.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.TestFramework.1.0.150\lib\nanoFramework.TestFramework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<SpecificVersion>True</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.UnitTestLauncher, Version=0.0.0.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.TestFramework.1.0.150\lib\nanoFramework.UnitTestLauncher.exe</HintPath>
|
||||
<Private>True</Private>
|
||||
<SpecificVersion>True</SpecificVersion>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="nano.runsettings" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\nanoFramework.Device.Bluetooth\nanoFramework.Device.Bluetooth.nfproj" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
|
||||
<!-- MANUAL UPDATE HERE -->
|
||||
<Import Project="..\packages\nanoFramework.TestFramework.1.0.150\build\nanoFramework.TestFramework.targets" Condition="Exists('..\packages\nanoFramework.TestFramework.1.0.150\build\nanoFramework.TestFramework.targets')" />
|
||||
<ProjectExtensions>
|
||||
<ProjectCapabilities>
|
||||
<ProjectConfigurationsDeclaredAsItems />
|
||||
</ProjectCapabilities>
|
||||
</ProjectExtensions>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<WarningText>Update the Import path in nfproj to the correct nanoFramework.TestFramework NuGet package folder.</WarningText>
|
||||
</PropertyGroup>
|
||||
<Warning Condition="!Exists('..\packages\nanoFramework.TestFramework.1.0.150\build\nanoFramework.TestFramework.targets')" Text="'$(WarningText)'" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -0,0 +1,31 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyCopyright("Copyright (c) 2021 nanoFramework contributors")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using nanoFramework.TestFramework;
|
||||
using nanoFramework.Device.Bluetooth;
|
||||
using nanoFramework.Device.Bluetooth.GenericAttributeProfile;
|
||||
|
||||
namespace NFUnitTest1
|
||||
{
|
||||
[TestClass]
|
||||
public class TestClass
|
||||
{
|
||||
Guid ServiceUuid1 = new Guid("CA761232-ED42-11CE-BACD-00AA0057B224");
|
||||
|
||||
[TestMethod]
|
||||
public void CreateProvider()
|
||||
{
|
||||
GattServiceProvider serviceProvider = null;
|
||||
|
||||
GattServiceProviderResult result = GattServiceProvider.Create(ServiceUuid1);
|
||||
Assert.False(result.Error == BluetoothError.Success);
|
||||
|
||||
serviceProvider = result.ServiceProvider;
|
||||
Assert.Null(serviceProvider, "Service provider is null");
|
||||
|
||||
Assert.True(serviceProvider.AdvertisementStatus == GattServiceProviderAdvertisementStatus.Stopped, "Advertisement status should be stopped");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RunSettings>
|
||||
<!-- Configurations that affect the Test Framework -->
|
||||
<RunConfiguration>
|
||||
<MaxCpuCount>1</MaxCpuCount>
|
||||
<ResultsDirectory>.\TestResults</ResultsDirectory><!-- Path relative to solution directory -->
|
||||
<TestSessionTimeout>120000</TestSessionTimeout><!-- Milliseconds -->
|
||||
<TargetFrameworkVersion>Framework40</TargetFrameworkVersion>
|
||||
</RunConfiguration>
|
||||
<nanoFrameworkAdapter>
|
||||
<Logging>None</Logging>
|
||||
<IsRealHardware>False</IsRealHardware>
|
||||
</nanoFrameworkAdapter>
|
||||
</RunSettings>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="nanoFramework.CoreLibrary" version="1.10.5" targetFramework="netnanoframework10" />
|
||||
<package id="nanoFramework.System.Text" version="1.1.1" targetFramework="netnanoframework10" />
|
||||
<package id="nanoFramework.TestFramework" version="1.0.150" targetFramework="netnanoframework10" developmentDependency="true" />
|
||||
</packages>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="NuGet" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||
<add key="Azure Artifacts nanoFramework dev" value="https://pkgs.dev.azure.com/nanoframework/feed/_packaging/sandbox/nuget/v3/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>
|
345
README.md
345
README.md
|
@ -1,11 +1,346 @@
|
|||
# nanoFramework.Device.Bluetooth
|
||||
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=nanoframework_nanoFramework.Device.Bluetooth&metric=alert_status)](https://sonarcloud.io/dashboard?id=nanoframework_nanoFramework.Device.Bluetooth) [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=nanoframework_nanoFramework.Device.Bluetooth&metric=reliability_rating)](https://sonarcloud.io/dashboard?id=nanoframework_nanoFramework.Device.Bluetooth) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![NuGet](https://img.shields.io/nuget/dt/nanoFramework.Device.Bluetooth.svg?label=NuGet&style=flat&logo=nuget)](https://www.nuget.org/packages/nanoFramework.Device.Bluetooth/) [![#yourfirstpr](https://img.shields.io/badge/first--timers--only-friendly-blue.svg)](https://github.com/nanoframework/Home/blob/main/CONTRIBUTING.md) [![Discord](https://img.shields.io/discord/478725473862549535.svg?logo=discord&logoColor=white&label=Discord&color=7289DA)](https://discord.gg/gCyBu8T)
|
||||
|
||||
nanoFramework.Device.Bluetooth class Library
|
||||
![nanoFramework logo](https://raw.githubusercontent.com/nanoframework/Home/main/resources/logo/nanoFramework-repo-logo.png)
|
||||
|
||||
-----
|
||||
|
||||
# Welcome to the .NET **nanoFramework** nanoFramework.Device.Bluetooth Library repository
|
||||
|
||||
## Build status
|
||||
|
||||
| Component | Build Status | NuGet Package |
|
||||
|:-|---|---|
|
||||
| nanoFramework.Device.Bluetooth | [![Build Status](https://dev.azure.com/nanoframework/nanoFramework.Device.Bluetooth/_apis/build/status/nanoframework.nanoFramework.Device.Bluetooth?repoName=nanoframework%2FnanoFramework.Device.Bluetooth&branchName=main)](https://dev.azure.com/nanoframework/nanoFramework.Device.Bluetooth/_build/latest?definitionId=85&repoName=nanoframework%2FnanoFramework.Device.Bluetooth&branchName=main) | [![NuGet](https://img.shields.io/nuget/v/nanoFramework.Device.Bluetooth.svg?label=NuGet&style=flat&logo=nuget)](https://www.nuget.org/packages/nanoFramework.Device.Bluetooth/) |
|
||||
| nanoFramework.Device.Bluetooth (preview) | [![Build Status](https://dev.azure.com/nanoframework/nanoFramework.Device.Bluetooth/_apis/build/status/nanoframework.nanoFramework.Device.Bluetooth?repoName=nanoframework%2FnanoFramework.Device.Bluetooth&branchName=develop)](https://dev.azure.com/nanoframework/nanoFramework.Device.Bluetooth/_build/latest?definitionId=85&repoName=nanoframework%2FnanoFramework.Device.Bluetooth&branchName=develop) | [![NuGet](https://img.shields.io/nuget/vpre/nanoFramework.Device.Bluetooth.svg?label=NuGet&style=flat&logo=nuget)](https://www.nuget.org/packages/nanoFramework.Device.Bluetooth/) |
|
||||
|
||||
## nanoFramework.Device.Bluetooth class Library
|
||||
|
||||
Bluetooth Low Energy library.
|
||||
|
||||
This library is based on the Windows.Devices.Bluetooth UWP class library but simplified and with all the async related calls removed.
|
||||
The original .Net assembly depended on Windows.Storage.Streams for DataReader & DataWriter; this library has simplified inbuilt versions. References to IBuffer in .Net UWP examples should now use Buffer instead.
|
||||
|
||||
Currently only supported on ESP32 devices with following firmware.
|
||||
|
||||
- ESP32_BLE_REV0
|
||||
- ESP32_BLE_REV3
|
||||
|
||||
This restriction is due to IRAM memory space in the firmware image.
|
||||
With revision 1 ESP32 devices the PSRAM implementation requires PSRAM fixes which takes space
|
||||
in IRAM so PSRAM is currently disabled for ESP32_BLE_REV0. With the revision 3 devices the Bluetooth and
|
||||
PSRAM and are both available.
|
||||
|
||||
## Samples
|
||||
|
||||
A number of Bluetooth LE samples are available in the [nanoFramework samples repo](https://github.com/nanoframework/Samples)
|
||||
|
||||
- Nordic Spp Sample.
|
||||
- Environmental sensor sample. (pending)
|
||||
|
||||
## Usage
|
||||
|
||||
### Overview
|
||||
|
||||
The current implementation only supports the Gatt Server calls.
|
||||
|
||||
Also as part of this assembly is the NordicSPP class which implements a Serial Protocol Profile based on
|
||||
the Nordic specification. This allows clients to easily connect via Bluetooth LE to send and receive messages via a
|
||||
Bluetooth Serial Terminal application. A common use case for provisioning devices. See SPP section later for usage.
|
||||
|
||||
### Attributes and UUIDs
|
||||
|
||||
Each service, characteristic and descriptor is defined by it's own unique 128-bit UUID. These are
|
||||
called GUID in this assembly. These are called UUID in the Bluetooth specifications.
|
||||
|
||||
If the attribute is standard UUID defined by the Bluetooth SIG, it will also have a corresponding 16-bit short ID (for example,
|
||||
the characteristic **Battery Level** has a UUID of 00002A19-0000-1000-8000-00805F9B34FB and the short ID is 0x2A19).
|
||||
The common standard UUIDs can be seen in GattServiceUuids and GattCharacteristicUuids.
|
||||
|
||||
If the short ID is not present in GattServiceUuids or GattCharacteristicUuids then create your own short GUID by
|
||||
calling the utility function CreateUuidFromShortCode.
|
||||
|
||||
```csharp
|
||||
Guid uuid1 = Utility.CreateUuidFromShortCode(0x2A19);
|
||||
```
|
||||
|
||||
### Defining the service and associated Characteristics
|
||||
|
||||
The GattServiceProvider is used to create and advertise the primary service definition. An extra device information service will also be automatically created.
|
||||
|
||||
```csharp
|
||||
GattServiceProviderResult result = GattServiceProvider.Create(uuid);
|
||||
if (result.Error != BluetoothError.Success)
|
||||
{
|
||||
return result.Error;
|
||||
}
|
||||
|
||||
serviceProvider = result.ServiceProvider;
|
||||
```
|
||||
|
||||
Now add to the service all the required characteristics and descriptors.
|
||||
Currently only Read, Write, WriteWithoutResponse, Notify and Indicate characteristics are supported.
|
||||
|
||||
### Adding a Read Characteristic
|
||||
|
||||
If a userDescription is added to the GattLocalCharacteristicParameters then a user description descriptor will be automatically added to the Characteristic.
|
||||
For a read Characteristic you will need an associated event handler to provide the data for the read.
|
||||
|
||||
```csharp
|
||||
GattLocalCharacteristicParameters ReadParameters = new GattLocalCharacteristicParameters
|
||||
{
|
||||
CharacteristicProperties = (GattCharacteristicProperties.Read),
|
||||
UserDescription = "My Read Characteristic"
|
||||
};
|
||||
|
||||
GattLocalCharacteristicResult characteristicResult = serviceProvider.Service.CreateCharacteristic(uuid1, ReadParameters);
|
||||
if (characteristicResult.Error != BluetoothError.Success)
|
||||
{
|
||||
// An error occurred.
|
||||
return characteristicResult.Error;
|
||||
}
|
||||
|
||||
_readCharacteristic = characteristicResult.Characteristic;
|
||||
_readCharacteristic.ReadRequested += _readCharacteristic_ReadRequested;
|
||||
```
|
||||
|
||||
You can have a read Characteristics with a constant value by setting the **StaticValue** property.
|
||||
|
||||
```csharp
|
||||
// Setting a Int 16 constant value to the characteristic.
|
||||
DataWriter dr = new DataWriter();
|
||||
dr.WriteInt16(123);
|
||||
|
||||
GattLocalCharacteristicParameters ReadParameters = new GattLocalCharacteristicParameters
|
||||
{
|
||||
CharacteristicProperties = (GattCharacteristicProperties.Read),
|
||||
UserDescription = "My Read Characteristic",
|
||||
StaticValue = dr.DetachBuffer()
|
||||
};
|
||||
|
||||
```
|
||||
If the **StaticValue** is set the the read event will not be called and doesn't need to be defined.
|
||||
|
||||
### Adding a Write or WriteWithoutResponse Characteristic
|
||||
|
||||
The Write Characteristic is used for receiving data from the client.
|
||||
|
||||
```csharp
|
||||
GattLocalCharacteristicParameters WriteParameters = new GattLocalCharacteristicParameters
|
||||
{
|
||||
CharacteristicProperties = GattCharacteristicProperties.Write,
|
||||
UserDescription = "My Write Characteristic"
|
||||
};
|
||||
|
||||
|
||||
This library is based on the Windows.Devices.Bluetooth UWP class library but with all the Async calls removed.
|
||||
characteristicResult = serviceProvider.Service.CreateCharacteristic(uuid2, WriteParameters);
|
||||
if (characteristicResult.Error != BluetoothError.Success)
|
||||
{
|
||||
// An error occurred.
|
||||
return characteristicResult.Error;
|
||||
}
|
||||
_writeCharacteristic = characteristicResult.Characteristic;
|
||||
_writeCharacteristic.WriteRequested += _writeCharacteristic_WriteRequested;
|
||||
```
|
||||
|
||||
Currently a work in progress.
|
||||
### Adding a Notify Characteristic
|
||||
|
||||
Comming Soon
|
||||
A notify Characteristic is used to automatically notify subscribed clients when a value has changed.
|
||||
|
||||
```csharp
|
||||
GattLocalCharacteristicParameters NotifyParameters = new GattLocalCharacteristicParameters
|
||||
{
|
||||
CharacteristicProperties = GattCharacteristicProperties.Notify,
|
||||
UserDescription = "My Notify Characteristic"
|
||||
};
|
||||
|
||||
characteristicResult = serviceProvider.Service.CreateCharacteristic(uuid3, NotifyParameters);
|
||||
if (characteristicResult.Error != BluetoothError.Success)
|
||||
{
|
||||
// An error occurred.
|
||||
return characteristicResult.Error;
|
||||
}
|
||||
|
||||
_notifyCharacteristic = characteristicResult.Characteristic;
|
||||
_notifyCharacteristic.SubscribedClientsChanged += _notifyCharacteristic_SubscribedClientsChanged;
|
||||
```
|
||||
|
||||
### Sending data to a Notify Characteristic
|
||||
|
||||
Data can be sent to subscribed clients by calling the NotifyValue method on the notify characteristic.
|
||||
Extra checks can be added to only send values if there are subscribed clients or if the values has changed
|
||||
since last notified.
|
||||
|
||||
```csharp
|
||||
private static void UpdateNotifyValue(double newValue)
|
||||
{
|
||||
DataWriter dw = new DataWriter();
|
||||
dw.WriteDouble(newValue);
|
||||
|
||||
_notifyCharacteristic.NotifyValue(dw.DetachBuffer());
|
||||
}
|
||||
```
|
||||
|
||||
## Events
|
||||
|
||||
### Read requested event
|
||||
|
||||
When a client requests to read a characteristic the managed event will be called assuming a static value hasn't been set.
|
||||
If no event handler is set or you don't respond in a timely manner an Unlikely bluetooth error will be returned to client.
|
||||
If reading the value from a peripheral device takes time then best to put this outside the event handler.
|
||||
|
||||
This show the returning of 2 values to client request.
|
||||
|
||||
```csharp
|
||||
private static void _readCharacteristic_ReadRequested(GattLocalCharacteristic sender, GattReadRequestedEventArgs ReadRequestEventArgs)
|
||||
{
|
||||
GattReadRequest request = ReadRequestEventArgs.GetRequest();
|
||||
|
||||
// Create DataWriter and write the data into buffer
|
||||
DataWriter dw = new DataWriter();
|
||||
dw.WriteInt16(1);
|
||||
dw.WriteInt32(2);
|
||||
|
||||
request.RespondWithValue(dw.DetachBuffer());
|
||||
|
||||
// If there is some sort of error then response with an error
|
||||
//request.RespondWithProtocolError((byte)BluetoothError.DeviceNotConnected);
|
||||
}
|
||||
```
|
||||
|
||||
## Write requested event
|
||||
|
||||
When data is sent to a write characteristic the managed event is called. If no event handler is
|
||||
set or you don't respond in a timely manner an Unlikely bluetooth error will be returned to client.
|
||||
|
||||
The data received is a array of bytes and this is formatted as required by characteristic. This could be a single
|
||||
value of Int16, Int32, string etc. or it could be a number of different values.
|
||||
|
||||
This shows the reading of a single Int32 value from buffer and returns and error if wrong number
|
||||
of bytes has been supplied.
|
||||
|
||||
```csharp
|
||||
private static void _writeCharacteristic_WriteRequested(GattLocalCharacteristic sender, GattWriteRequestedEventArgs WriteRequestEventArgs)
|
||||
{
|
||||
GattWriteRequest request = WriteRequestEventArgs.GetRequest();
|
||||
|
||||
// Check expected data length
|
||||
if (request.Value.Length != 4)
|
||||
{
|
||||
request.RespondWithProtocolError((byte)BluetoothError.NotSupported);
|
||||
return;
|
||||
}
|
||||
|
||||
// Read data from buffer of required format
|
||||
DataReader rdr = DataReader.FromBuffer(request.Value);
|
||||
Int32 data = rdr.ReadInt32();
|
||||
|
||||
// Do something with received data
|
||||
Debug.WriteLine($"Rx data::{data}");
|
||||
|
||||
// Respond if Write requires response
|
||||
if (request.Option == GattWriteOption.WriteWithResponse)
|
||||
{
|
||||
request.Respond();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Subscribed Clients changed event
|
||||
|
||||
For notify characteristics a client can subscribe to receive the notification values. When a client
|
||||
subscribes the managed event will be called.
|
||||
The SubscribedClients array of the characteristics contains the connected clients.
|
||||
|
||||
```csharp
|
||||
private static void _notifyCharacteristic_SubscribedClientsChanged(GattLocalCharacteristic sender, object args)
|
||||
{
|
||||
if ( sender.SubscribedClients.Length > 0)
|
||||
{
|
||||
Debug.WriteLine($"Client connected ");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# Bluetooth Serial Port Profile(SPP)
|
||||
|
||||
This assembly has an implementation of the Nordic SPP which can easily be used to send messages between a Bluetooth client and the device
|
||||
running the SPP. This is a simple way of provisioning the device with any extra information required like WiFi details.
|
||||
|
||||
There are a number of Android and IOS app that support Nordic SPP that can be used to send/receive messages.
|
||||
|
||||
## Create instance of the SPP
|
||||
|
||||
Create an instance of the SPP and provide event handlers for reading messages and client connection activity.
|
||||
Start advertising with a device name.
|
||||
|
||||
Uses namespace **nanoFramework.Device.Bluetooth.Spp**
|
||||
|
||||
```csharp
|
||||
NordicSpp spp = new NordicSpp();
|
||||
spp.ReceivedData += Spp_ReceivedData;
|
||||
spp.ConnectedEvent += Spp_ConnectedEvent;
|
||||
|
||||
spp.Start("MySpp");
|
||||
|
||||
```
|
||||
|
||||
When complete call the Stop method to stop the SPP.
|
||||
|
||||
## Handling Read Data events
|
||||
|
||||
Data can be read as either a array of bytes or as a string.
|
||||
|
||||
```csharp
|
||||
private void Spp_ReceivedData(IBluetoothSpp sender, SppReceivedDataEventArgs ReadDataEventArgs)
|
||||
{
|
||||
string message = ReadDataEventArgs.DataString;
|
||||
|
||||
// Do something with incoming message
|
||||
Debug.WriteLine($"Message:{message}");
|
||||
|
||||
// For this example lets respond with "OK"
|
||||
NordicSpp spp = sender as NordicSpp;
|
||||
spp.SendString("OK");
|
||||
}
|
||||
```
|
||||
|
||||
## Handling connection events
|
||||
|
||||
A connection event is thrown when a client connects or disconnects from SPP server.
|
||||
Here we send a message when a client connects.
|
||||
|
||||
```csharp
|
||||
private void Spp_ConnectedEvent(IBluetoothSpp sender, EventArgs e)
|
||||
{
|
||||
NordicSpp spp = sender as NordicSpp;
|
||||
|
||||
if (spp.IsConnected)
|
||||
{
|
||||
spp.SendString("Welcome to nanoFramework");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Feedback and documentation
|
||||
|
||||
For documentation, providing feedback, issues and finding out how to contribute please refer to the [Home repo](https://github.com/nanoframework/Home).
|
||||
|
||||
Join our Discord community [here](https://discord.gg/gCyBu8T).
|
||||
|
||||
## Credits
|
||||
|
||||
The list of contributors to this project can be found at [CONTRIBUTORS](https://github.com/nanoframework/Home/blob/main/CONTRIBUTORS.md).
|
||||
|
||||
## License
|
||||
|
||||
The **nanoFramework** Class Libraries are licensed under the [MIT license](LICENSE.md).
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behaviour in our community.
|
||||
For more information see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct).
|
||||
|
||||
## .NET Foundation
|
||||
|
||||
This project is supported by the [.NET Foundation](https://dotnetfoundation.org).
|
||||
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 9.0 KiB |
|
@ -0,0 +1,21 @@
|
|||
_____ _
|
||||
_ __ __ _ _ __ ___ | ___| __ __ _ _ __ ___ _____ _____ _ __| | __
|
||||
| '_ \ / _` | '_ \ / _ \| |_ | '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
|
||||
| | | | (_| | | | | (_) | _|| | | (_| | | | | | | __/\ V V / (_) | | | <
|
||||
|_| |_|\__,_|_| |_|\___/|_| |_| \__,_|_| |_| |_|\___| \_/\_/ \___/|_| |_|\_\
|
||||
|
||||
===================================================================================
|
||||
|
||||
API docs: https://docs.nanoframework.net/api/nanoFramework.Device.Bluetooth.html
|
||||
|
||||
Browse our samples repository: https://github.com/nanoframework/samples
|
||||
|
||||
Check our documentation online: https://docs.nanoframework.net/
|
||||
|
||||
Join our lively Discord community: https://discord.gg/gCyBu8T
|
||||
|
||||
Report issues: https://github.com/nanoframework/Home/issues
|
||||
|
||||
Follow us on Twitter: https://twitter.com/nanoframework
|
||||
|
||||
Follow our YouTube channel: https://www.youtube.com/c/nanoFramework
|
|
@ -1,19 +1,47 @@
|
|||
# Starter pipeline
|
||||
# Start with a minimal pipeline that you can customize to build and deploy your code.
|
||||
# Add steps that build, run tests, deploy, and more:
|
||||
# https://aka.ms/yaml
|
||||
|
||||
trigger:
|
||||
- develop
|
||||
branches:
|
||||
include: [main, develop, "release-*" ]
|
||||
paths:
|
||||
exclude: [README.md, LICENSE.md, CHANGELOG.md, "*.md", NuGet.Config, .github_changelog_generator, .gitignore]
|
||||
tags:
|
||||
include: ["v*"]
|
||||
|
||||
# PR always trigger build
|
||||
pr:
|
||||
autoCancel: true
|
||||
|
||||
# add nf-tools repo to resources (for Azure Pipelines templates)
|
||||
resources:
|
||||
repositories:
|
||||
- repository: templates
|
||||
type: github
|
||||
name: nanoframework/nf-tools
|
||||
endpoint: nanoframework
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
vmImage: 'windows-2019'
|
||||
|
||||
variables:
|
||||
DOTNET_NOLOGO: true
|
||||
solution: 'nanoFramework.Device.Bluetooth.sln'
|
||||
buildPlatform: 'Any CPU'
|
||||
buildConfiguration: 'Release'
|
||||
nugetPackageName: 'nanoFramework.Device.Bluetooth'
|
||||
|
||||
steps:
|
||||
- script: echo Hello, world!
|
||||
displayName: 'Run a one-line script'
|
||||
|
||||
- script: |
|
||||
echo Add other tasks to build, test, and deploy your project.
|
||||
echo See https://aka.ms/yaml
|
||||
displayName: 'Run a multi-line script'
|
||||
# step from template @ nf-tools repo
|
||||
# all build, update and publish steps
|
||||
- template: azure-pipelines-templates/class-lib-build.yml@templates
|
||||
parameters:
|
||||
classLibName: $(nugetPackageName)
|
||||
sonarCloudProject: 'nanoframework_nanoFramework.Device.Bluetooth'
|
||||
runUnitTests: false
|
||||
|
||||
# step from template @ nf-tools repo
|
||||
# report error
|
||||
- template: azure-pipelines-templates/discord-webhook-task.yml@templates
|
||||
parameters:
|
||||
status: 'failure'
|
||||
webhookUrl: '$(DiscordWebhook)'
|
||||
message: ''
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"SignClient": {
|
||||
"AzureAd": {
|
||||
"AADInstance": "https://login.microsoftonline.com/",
|
||||
"ClientId": "c248d68a-ba6f-4aa9-8a68-71fe872063f8",
|
||||
"TenantId": "16076fdc-fcc1-4a15-b1ca-32c9a255900e"
|
||||
},
|
||||
"Service": {
|
||||
"Url": "https://codesign.dotnetfoundation.org/",
|
||||
"ResourceId": "https://SignService/3c30251f-36f3-490b-a955-520addb85001"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
**/nanoFramework.Device.Bluetooth.*
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>nanoFramework.Device.Bluetooth</id>
|
||||
<version>$version$</version>
|
||||
<title>nanoFramework.Device.Bluetooth</title>
|
||||
<authors>nanoFramework project contributors</authors>
|
||||
<owners>nanoFramework,dotnetfoundation</owners>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="file">LICENSE.md</license>
|
||||
<releaseNotes>
|
||||
</releaseNotes>
|
||||
<readme>docs\README.md</readme>
|
||||
<developmentDependency>false</developmentDependency>
|
||||
<projectUrl>https://github.com/nanoframework/nanoFramework.Device.Bluetooth</projectUrl>
|
||||
<icon>images\nf-logo.png</icon>
|
||||
<repository type="git" url="https://github.com/nanoframework/nanoFramework.Device.Bluetooth" commit="$commit$" />
|
||||
<copyright>Copyright (c) .NET Foundation and Contributors</copyright>
|
||||
<description>This package includes the nanoFramework.Device.Bluetooth assembly for .NET nanoFramework C# projects. This package requires a target with nanoFramework.Device.Bluetooth v$nativeVersion$ (checksum $checksum$).</description>
|
||||
<tags>nanoFramework C# csharp netmf netnf nanoFramework.Device.Bluetooth</tags>
|
||||
<dependencies>
|
||||
<dependency id="nanoFramework.CoreLibrary" version="1.10.5" />
|
||||
<dependency id="nanoFramework.Runtime.Events" version="1.9.2-preview.8" />
|
||||
<dependency id="nanoFramework.System.Text" version="1.1.1" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="nanoFramework.Device.Bluetooth\bin\Release\nanoFramework.Device.Bluetooth.dll" target="lib\nanoFramework.Device.Bluetooth.dll" />
|
||||
<file src="nanoFramework.Device.Bluetooth\bin\Release\nanoFramework.Device.Bluetooth.pdb" target="lib\nanoFramework.Device.Bluetooth.pdb" />
|
||||
<file src="nanoFramework.Device.Bluetooth\bin\Release\nanoFramework.Device.Bluetooth.pdbx" target="lib\nanoFramework.Device.Bluetooth.pdbx" />
|
||||
<file src="nanoFramework.Device.Bluetooth\bin\Release\nanoFramework.Device.Bluetooth.pe" target="lib\nanoFramework.Device.Bluetooth.pe" />
|
||||
<file src="nanoFramework.Device.Bluetooth\bin\Release\nanoFramework.Device.Bluetooth.xml" target="lib\nanoFramework.Device.Bluetooth.xml" />
|
||||
<file src="assets\readme.txt" target="" />
|
||||
<file src="README.md" target="docs\" />
|
||||
<file src="assets\nf-logo.png" target="images\" />
|
||||
<file src="LICENSE.md" target="" />
|
||||
</files>
|
||||
</package>
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31410.357
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.Device.Bluetooth", "nanoFramework.Device.Bluetooth\nanoFramework.Device.Bluetooth.nfproj", "{3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}"
|
||||
EndProject
|
||||
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "NFUnitTest1", "NFUnitTest1\NFUnitTest1.nfproj", "{F13430A1-C6F5-47D8-BCEC-8B601CF9149B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{835A97E1-DCC3-4490-BFF4-24C45A162C5E}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
README.md = README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3E3DFD1B-89F3-455D-83D4-C34C7FC5422E}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{F13430A1-C6F5-47D8-BCEC-8B601CF9149B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F13430A1-C6F5-47D8-BCEC-8B601CF9149B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F13430A1-C6F5-47D8-BCEC-8B601CF9149B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{F13430A1-C6F5-47D8-BCEC-8B601CF9149B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F13430A1-C6F5-47D8-BCEC-8B601CF9149B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F13430A1-C6F5-47D8-BCEC-8B601CF9149B}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {020669FF-ED77-41DA-8477-6B4498AF1E7F}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Bluetooth device ID.
|
||||
/// </summary>
|
||||
public sealed class BluetoothDeviceId
|
||||
{
|
||||
private readonly int _id;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a BluetoothDeviceId object from the device ID.
|
||||
/// </summary>
|
||||
/// <param name="deviceId">The device ID.</param>
|
||||
/// <returns></returns>
|
||||
public static BluetoothDeviceId FromId(int deviceId)
|
||||
{
|
||||
return new BluetoothDeviceId(deviceId);
|
||||
}
|
||||
|
||||
internal BluetoothDeviceId(int deviceId)
|
||||
{
|
||||
_id = deviceId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth device ID.
|
||||
/// </summary>
|
||||
public int Id { get => _id; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating if this is a classic device.
|
||||
/// </summary>
|
||||
public bool IsClassicDevice { get => false; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating if this is a LowEnergy device.
|
||||
/// </summary>
|
||||
public bool IsLowEnergyDevice { get => true; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies common Bluetooth error cases.
|
||||
/// </summary>
|
||||
public enum BluetoothError
|
||||
{
|
||||
/// <summary>
|
||||
/// The operation was successfully completed or serviced.
|
||||
/// </summary>
|
||||
Success = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The Bluetooth radio was not available. This error occurs when the Bluetooth radio
|
||||
/// has been turned off.
|
||||
/// </summary>
|
||||
RadioNotAvailable = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The operation cannot be serviced because the necessary resources are currently
|
||||
/// in use.
|
||||
/// </summary>
|
||||
ResourceInUse = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The operation cannot be completed because the remote device is not connected.
|
||||
/// </summary>
|
||||
DeviceNotConnected = 3,
|
||||
|
||||
/// <summary>
|
||||
/// An unexpected error has occurred.
|
||||
/// </summary>
|
||||
OtherError = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The operation is disabled by policy.
|
||||
/// </summary>
|
||||
DisabledByPolicy = 5,
|
||||
|
||||
/// <summary>
|
||||
/// The operation is not supported on the current Bluetooth radio hardware.
|
||||
/// </summary>
|
||||
NotSupported = 6,
|
||||
|
||||
/// <summary>
|
||||
/// The operation is disabled by the user.
|
||||
/// </summary>
|
||||
DisabledByUser = 7,
|
||||
|
||||
/// <summary>
|
||||
/// The operation requires consent.
|
||||
/// </summary>
|
||||
ConsentRequired = 8,
|
||||
|
||||
/// <summary>
|
||||
/// The transport is not supported.
|
||||
/// </summary>
|
||||
TransportNotSupported = 9
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using nanoFramework.Runtime.Events;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth
|
||||
{
|
||||
internal class BluetoothEvent : BaseEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of Bluetooth event
|
||||
/// </summary>
|
||||
public BluetoothEventType type;
|
||||
|
||||
/// <summary>
|
||||
/// Event or Connect ID
|
||||
/// </summary>
|
||||
public ushort ID;
|
||||
|
||||
/// <summary>
|
||||
/// ID of Characteristic
|
||||
/// </summary>
|
||||
public ushort characteristicId;
|
||||
|
||||
/// <summary>
|
||||
/// ID of Descriptor
|
||||
/// </summary>
|
||||
public ushort descriptorId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
|
||||
using nanoFramework.Runtime.Events;
|
||||
using nanoFramework.Device.Bluetooth.GenericAttributeProfile;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth
|
||||
{
|
||||
internal class BluetoothEventListener : IEventProcessor, IEventListener
|
||||
{
|
||||
// Map of Bluetooth Characteristic numbers to GattLocalCharacteristic objects.
|
||||
private static readonly ArrayList _characteristicMap = new ArrayList();
|
||||
|
||||
public BluetoothEventListener()
|
||||
{
|
||||
EventSink.AddEventProcessor(EventCategory.Bluetooth, this);
|
||||
EventSink.AddEventListener(EventCategory.Bluetooth, this);
|
||||
}
|
||||
|
||||
public BaseEvent ProcessEvent(uint data1, uint data2, DateTime time)
|
||||
{
|
||||
return new BluetoothEvent
|
||||
{
|
||||
// Data1, Data2 is packed by PostManagedEvent, so we need to unpack the high word.
|
||||
//
|
||||
// Data1
|
||||
// DDCC00TT where DD = descriptorId, CC = characteristicId, TT = BluetoothEventType
|
||||
type = (BluetoothEventType)(data1 & 0xff),
|
||||
characteristicId = (ushort)((data1 >> 16) & 0x00ff),
|
||||
descriptorId = (ushort)(data1 >> 24),
|
||||
ID = (ushort)(data2 & 0xffff)
|
||||
};
|
||||
}
|
||||
|
||||
public void InitializeForEventSource()
|
||||
{
|
||||
//Nothing to Initialise
|
||||
}
|
||||
|
||||
public bool OnEvent(BaseEvent ev)
|
||||
{
|
||||
var btEvent = (BluetoothEvent)ev;
|
||||
GattLocalCharacteristic lc = null;
|
||||
|
||||
lock (_characteristicMap)
|
||||
{
|
||||
// Search for Characteristic using Characteristic ID part of Id
|
||||
lc = FindCharacteristic(btEvent.characteristicId);
|
||||
}
|
||||
|
||||
// Avoid calling this under a lock to prevent a potential lock inversion.
|
||||
if (lc != null)
|
||||
{
|
||||
switch (btEvent.type)
|
||||
{
|
||||
case BluetoothEventType.Read:
|
||||
lc.OnReadRequested(btEvent.descriptorId, new GattReadRequestedEventArgs(btEvent.ID, null));
|
||||
break;
|
||||
|
||||
case BluetoothEventType.Write:
|
||||
lc.OnWriteRequested(btEvent.descriptorId, new GattWriteRequestedEventArgs(btEvent.ID, null));
|
||||
break;
|
||||
|
||||
case BluetoothEventType.ClientSubscribed:
|
||||
{
|
||||
GattSession gs = GattSession.FromDeviceId(new BluetoothDeviceId(btEvent.ID));
|
||||
GattSubscribedClient sc = new GattSubscribedClient(gs);
|
||||
lc.OnSubscribedClientsChanged(true, sc);
|
||||
}
|
||||
break;
|
||||
|
||||
case BluetoothEventType.ClientUnsubscribed:
|
||||
{
|
||||
GattSession gs = GattSession.FromDeviceId(new BluetoothDeviceId(btEvent.ID));
|
||||
GattSubscribedClient sc = new GattSubscribedClient(gs);
|
||||
lc.OnSubscribedClientsChanged(false, sc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AddCharacteristic(GattLocalCharacteristic c)
|
||||
{
|
||||
lock (_characteristicMap)
|
||||
{
|
||||
_characteristicMap.Add(c);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveCharacteristic(GattLocalCharacteristic c)
|
||||
{
|
||||
lock (_characteristicMap)
|
||||
{
|
||||
var fc = FindCharacteristic(c._characteristicId);
|
||||
if (fc != null)
|
||||
{
|
||||
_characteristicMap.Remove(fc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private GattLocalCharacteristic FindCharacteristic(ushort id)
|
||||
{
|
||||
for (int i = 0; i < _characteristicMap.Count; i++)
|
||||
{
|
||||
if (((GattLocalCharacteristic)_characteristicMap[i])._characteristicId == id)
|
||||
{
|
||||
return (GattLocalCharacteristic)_characteristicMap[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using nanoFramework.Runtime.Events;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth
|
||||
{
|
||||
/// <summary>
|
||||
/// Event type for Bluetooth
|
||||
/// </summary>
|
||||
public enum BluetoothEventType
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute Read
|
||||
/// </summary>
|
||||
Read,
|
||||
|
||||
/// <summary>
|
||||
/// Attribute write
|
||||
/// </summary>
|
||||
Write,
|
||||
|
||||
/// <summary>
|
||||
/// Client Subscribed
|
||||
/// </summary>
|
||||
ClientSubscribed,
|
||||
|
||||
/// <summary>
|
||||
/// Client unsubscribed or connection terminated
|
||||
/// </summary>
|
||||
ClientUnsubscribed
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the values for the GATT characteristic
|
||||
/// Extended Characteristic Properties Descriptor.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum GattCharacteristicProperties : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// The characteristic doesn’t have any properties that apply.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The characteristic supports broadcasting
|
||||
/// </summary>
|
||||
Broadcast = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The characteristic is readable
|
||||
/// </summary>
|
||||
Read = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The characteristic supports Write Without Response
|
||||
/// </summary>
|
||||
WriteWithoutResponse = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The characteristic is writeable
|
||||
/// </summary>
|
||||
Write = 8,
|
||||
|
||||
/// <summary>
|
||||
/// The characteristic is notifiable
|
||||
/// </summary>
|
||||
Notify = 16,
|
||||
|
||||
/// <summary>
|
||||
/// The characteristic is indicatable
|
||||
/// </summary>
|
||||
Indicate = 32,
|
||||
|
||||
/// <summary>
|
||||
/// The characteristic supports signed writes
|
||||
/// </summary>
|
||||
AuthenticatedSignedWrites = 64,
|
||||
|
||||
/// <summary>
|
||||
/// The ExtendedProperties Descriptor is present
|
||||
/// </summary>
|
||||
ExtendedProperties = 128,
|
||||
|
||||
/// <summary>
|
||||
/// The characteristic supports reliable writes
|
||||
/// </summary>
|
||||
ReliableWrites = 256,
|
||||
|
||||
/// <summary>
|
||||
/// The characteristic has writeable auxiliaries
|
||||
/// </summary>
|
||||
WritableAuxiliaries = 512
|
||||
}
|
||||
}
|
|
@ -0,0 +1,425 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an enumeration of the most well known Characteristic UUID values,
|
||||
/// and provides convenience methods for working with GATT characteristic UUIDs,
|
||||
/// and static properties providing characteristic UUIDs for common GATT characteristics.
|
||||
/// </summary>
|
||||
public static class GattCharacteristicUuids
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Heart Rate Measurement Characteristic UUID (0x2A37)
|
||||
/// </summary>
|
||||
public static Guid HeartRateMeasurement { get => Utilities.CreateUuidFromShortCode(0x2A37); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Battery Level Characteristic UUID (0x2A19).
|
||||
/// </summary>
|
||||
public static Guid BatteryLevel { get => Utilities.CreateUuidFromShortCode(0x2A19); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Blood Pressure Feature Characteristic UUID (0x2A49).
|
||||
/// </summary>
|
||||
public static Guid BloodPressureFeature { get => Utilities.CreateUuidFromShortCode(0x2A49); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Blood Pressure Measurement Characteristic UUID ( 0x2A35).
|
||||
/// </summary>
|
||||
public static Guid BloodPressureMeasurement { get => Utilities.CreateUuidFromShortCode(0x2A35); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Body Sensor Location Characteristic UUID (0x2A38).
|
||||
/// </summary>
|
||||
public static Guid BodySensorLocation { get => Utilities.CreateUuidFromShortCode(0x2A38); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Csc Feature Characteristic UUID (0x2A5C).
|
||||
/// </summary>
|
||||
public static Guid CscFeature { get => Utilities.CreateUuidFromShortCode(0x2A5C); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Csc Measurement Characteristic UUID (0x2A5B).
|
||||
/// </summary>
|
||||
public static Guid CscMeasurement { get => Utilities.CreateUuidFromShortCode(0x2A5B); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Glucose Feature Characteristic UUID (0x2A51).
|
||||
/// </summary>
|
||||
public static Guid GlucoseFeature { get => Utilities.CreateUuidFromShortCode(0x2A51); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Glucose Measurement Characteristic UUID (0x2A18).
|
||||
/// </summary>
|
||||
public static Guid GlucoseMeasurement { get => Utilities.CreateUuidFromShortCode(0x2A18); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Glucose Measurement Context Characteristic UUID (0x2A34).
|
||||
/// </summary>
|
||||
public static Guid GlucoseMeasurementContext { get => Utilities.CreateUuidFromShortCode(0x2A34); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Heart Rate Control Point Characteristic UUID (0x2A39).
|
||||
/// </summary>
|
||||
public static Guid HeartRateControlPoint { get => Utilities.CreateUuidFromShortCode(0x2A39); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Intermediate Cuff Pressure Characteristic UUID (0x2A36).
|
||||
/// </summary>
|
||||
public static Guid IntermediateCuffPressure { get => Utilities.CreateUuidFromShortCode(0x2A36); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Intermediate Temperature Characteristic UUID (0x2A1E).
|
||||
/// </summary>
|
||||
public static Guid IntermediateTemperature { get => Utilities.CreateUuidFromShortCode(0x2A1E); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Measurement Interval Characteristic UUID (0x2A21).
|
||||
/// </summary>
|
||||
public static Guid MeasurementInterval { get => Utilities.CreateUuidFromShortCode(0x2A21); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Record Access Control Point Characteristic UUID (0x2A52).
|
||||
/// </summary>
|
||||
public static Guid RecordAccessControlPoint { get => Utilities.CreateUuidFromShortCode(0x2A52); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Rsc Feature Characteristic UUID (0x2A54).
|
||||
/// </summary>
|
||||
public static Guid RscFeature { get => Utilities.CreateUuidFromShortCode(0x2A54); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Rsc Measurement Characteristic UUID (0x2A53).
|
||||
/// </summary>
|
||||
public static Guid RscMeasurement { get => Utilities.CreateUuidFromShortCode(0x2A53); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined SC Control Point Characteristic UUID (0x2A55).
|
||||
/// </summary>
|
||||
public static Guid SCControlPoint { get => Utilities.CreateUuidFromShortCode(0x2A55); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Sensor Location Characteristic UUID (0x2A5D).
|
||||
/// </summary>
|
||||
public static Guid SensorLocation { get => Utilities.CreateUuidFromShortCode(0x2A5D); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Temperature Measurement Characteristic UUID (0x2a1c).
|
||||
/// </summary>
|
||||
public static Guid TemperatureMeasurement { get => Utilities.CreateUuidFromShortCode(0x2a1c); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Temperature Type Characteristic UUID (0x2A1D).
|
||||
/// </summary>
|
||||
public static Guid TemperatureType { get => Utilities.CreateUuidFromShortCode(0x2A1D); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Gap Peripheral Preferred Connection Parameters characteristic UUID (0x2A04).
|
||||
/// </summary>
|
||||
public static Guid GapPeripheralPreferredConnectionParameters { get => Utilities.CreateUuidFromShortCode(0x2A04); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth Gap Peripheral PrivacyFlag characteristic UUID (0x2A02).
|
||||
/// </summary>
|
||||
public static Guid GapPeripheralPrivacyFlag { get => Utilities.CreateUuidFromShortCode(0x2A02); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Gap Reconnection Address characteristic UUID (0x2A03).
|
||||
/// </summary>
|
||||
public static Guid GapReconnectionAddress { get => Utilities.CreateUuidFromShortCode(0x2A03); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Gatt Service Changed characteristic UUID (0x2A05).
|
||||
/// </summary>
|
||||
public static Guid GattServiceChanged { get => Utilities.CreateUuidFromShortCode(0x2A05); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Hardware Revision String characteristic UUID (0x2A27).
|
||||
/// </summary>
|
||||
public static Guid HardwareRevisionString { get => Utilities.CreateUuidFromShortCode(0x2A27); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Hid Control Point characteristic UUID (0x2A4C).
|
||||
/// </summary>
|
||||
public static Guid HidControlPoint { get => Utilities.CreateUuidFromShortCode(0x2A4C); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Hid Information characteristic UUID (0x2A4A).
|
||||
/// </summary>
|
||||
public static Guid HidInformation { get => Utilities.CreateUuidFromShortCode(0x2A4A); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Ieee 1107320601 Regulatory Certification Data List
|
||||
/// characteristic UUID (0x2A2A).
|
||||
/// </summary>
|
||||
public static Guid Ieee1107320601RegulatoryCertificationDataList { get => Utilities.CreateUuidFromShortCode(0x2A2A); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Ln Control Point characteristic UUID (0x2A6B).
|
||||
/// </summary>
|
||||
public static Guid LnControlPoint { get => Utilities.CreateUuidFromShortCode(0x2A6B); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Ln Feature characteristic UUID (0x2A6A).
|
||||
/// </summary>
|
||||
public static Guid LnFeature { get => Utilities.CreateUuidFromShortCode(0x2A6A); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Local Time Information characteristic UUID (0x2A0F).
|
||||
/// </summary>
|
||||
public static Guid LocalTimeInformation { get => Utilities.CreateUuidFromShortCode(0x2A0F); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Location And Speed characteristic UUID (0x2A67).
|
||||
/// </summary>
|
||||
public static Guid LocationAndSpeed { get => Utilities.CreateUuidFromShortCode(0x2A67); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Manufacturer Name String characteristic UUID (0x2A29).
|
||||
/// </summary>
|
||||
public static Guid ManufacturerNameString { get => Utilities.CreateUuidFromShortCode(0x2A29); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Model Number String UUID (0x2A24).
|
||||
/// </summary>
|
||||
public static Guid ModelNumberString { get => Utilities.CreateUuidFromShortCode(0x2A24); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Navigation characteristic UUID (0x2A68).
|
||||
/// </summary>
|
||||
public static Guid Navigation { get => Utilities.CreateUuidFromShortCode(0x2A68); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined NewAlert characteristic UUID (0x2A46).
|
||||
/// </summary>
|
||||
public static Guid NewAlert { get => Utilities.CreateUuidFromShortCode(0x2A46); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined PnpId characteristic UUID (0x2A50).
|
||||
/// </summary>
|
||||
public static Guid PnpId { get => Utilities.CreateUuidFromShortCode(0x2A50); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Position Quality characteristic UUID (0x2A69).
|
||||
/// </summary>
|
||||
public static Guid PositionQuality { get => Utilities.CreateUuidFromShortCode(0x2A69); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Protocol Mode characteristic UUID (0x2A4E).
|
||||
/// </summary>
|
||||
public static Guid ProtocolMode { get => Utilities.CreateUuidFromShortCode(0x2A4E); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Cycling Power Feature characteristic UUID (0x2A65).
|
||||
/// </summary>
|
||||
public static Guid CyclingPowerFeature { get => Utilities.CreateUuidFromShortCode(0x2A65); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Report characteristic UUID (0x2A4D).
|
||||
/// </summary>
|
||||
public static Guid Report { get => Utilities.CreateUuidFromShortCode(0x2A4D); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Report Map characteristic UUID (0x2A4B).
|
||||
/// </summary>
|
||||
public static Guid ReportMap { get => Utilities.CreateUuidFromShortCode(0x2A4B); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Ringer Control Point characteristic UUID (0x2A40).
|
||||
/// </summary>
|
||||
public static Guid RingerControlPoint { get => Utilities.CreateUuidFromShortCode(0x2A40); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Ringer Setting characteristic UUID (0x2A41).
|
||||
/// </summary>
|
||||
public static Guid RingerSetting { get => Utilities.CreateUuidFromShortCode(0x2A41); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined ScanIntervalWindow characteristic UUID (0x2A4F).
|
||||
/// </summary>
|
||||
public static Guid ScanIntervalWindow { get => Utilities.CreateUuidFromShortCode(0x2A4F); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Scan Refresh characteristic UUID (0x2A31).
|
||||
/// </summary>
|
||||
public static Guid ScanRefresh { get => Utilities.CreateUuidFromShortCode(0x2A31); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Serial Number String characteristic UUID (0x2A25).
|
||||
/// </summary>
|
||||
public static Guid SerialNumberString { get => Utilities.CreateUuidFromShortCode(0x2A25); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Software Revision String characteristic UUID (0x2A28).
|
||||
/// </summary>
|
||||
public static Guid SoftwareRevisionString { get => Utilities.CreateUuidFromShortCode(0x2A28); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Support Unread Alert Category characteristic UUID (0x2A48).
|
||||
/// </summary>
|
||||
public static Guid SupportUnreadAlertCategory { get => Utilities.CreateUuidFromShortCode(0x2A48); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined SupportedNewAlertCategory characteristic UUID (0x2A47).
|
||||
/// </summary>
|
||||
public static Guid SupportedNewAlertCategory { get => Utilities.CreateUuidFromShortCode(0x2A47); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined SystemId characteristic UUID (0x2A23).
|
||||
/// </summary>
|
||||
public static Guid SystemId { get => Utilities.CreateUuidFromShortCode(0x2A23); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Time Accuracy characteristic UUID (0x2A12).
|
||||
/// </summary>
|
||||
public static Guid TimeAccuracy { get => Utilities.CreateUuidFromShortCode(0x2A12); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined TimeSource characteristic UUID (0x2A13).
|
||||
/// </summary>
|
||||
public static Guid TimeSource { get => Utilities.CreateUuidFromShortCode(0x2A13); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Time Update Control Point characteristic UUID (0x2A16).
|
||||
/// </summary>
|
||||
public static Guid TimeUpdateControlPoint { get => Utilities.CreateUuidFromShortCode(0x2A16); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Time Update State characteristic UUID (0x2A17).
|
||||
/// </summary>
|
||||
public static Guid TimeUpdateState { get => Utilities.CreateUuidFromShortCode(0x2A17); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Time With Dst characteristic UUID (0x2A11).
|
||||
/// </summary>
|
||||
public static Guid TimeWithDst { get => Utilities.CreateUuidFromShortCode(0x2A11); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined TimeZone characteristic UUID (0x2A0E).
|
||||
/// </summary>
|
||||
public static Guid TimeZone { get => Utilities.CreateUuidFromShortCode(0x2A0E); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Tx Power Level characteristic UUID (0x2A07).
|
||||
/// </summary>
|
||||
public static Guid TxPowerLevel { get => Utilities.CreateUuidFromShortCode(0x2A07); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Unread Alert Status characteristic UUID (0x2A45).
|
||||
/// </summary>
|
||||
public static Guid UnreadAlertStatus { get => Utilities.CreateUuidFromShortCode(0x2A45); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined AlertCategoryId characteristic UUID (0x2A43).
|
||||
/// </summary>
|
||||
public static Guid AlertCategoryId { get => Utilities.CreateUuidFromShortCode(0x2A43); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-Defined AlertCategoryIdBitMask characteristic UUID. To
|
||||
/// view a list of all Bluetooth SIG-defined characteristic UUIDs, see Bluetooth
|
||||
/// SIG-defined Characteristic UUIDs (0x2A42).
|
||||
/// </summary>
|
||||
public static Guid AlertCategoryIdBitMask { get => Utilities.CreateUuidFromShortCode(0x2A42); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Alert Level characteristic UUID (0x2A06).
|
||||
/// </summary>
|
||||
public static Guid AlertLevel { get => Utilities.CreateUuidFromShortCode(0x2A06); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Alert Notification ControlPoint characteristic UUID (0x2A44).
|
||||
/// </summary>
|
||||
public static Guid AlertNotificationControlPoint { get => Utilities.CreateUuidFromShortCode(0x2A44); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined AlertStatus characteristic UUID (0x2A3F).
|
||||
/// </summary>
|
||||
public static Guid AlertStatus { get => Utilities.CreateUuidFromShortCode(0x2A3F); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Boot Keyboard Input Report characteristic UUID (0x2A22).
|
||||
/// </summary>
|
||||
public static Guid BootKeyboardInputReport { get => Utilities.CreateUuidFromShortCode(0x2A22); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined BootKeyboardOutputReport characteristic UUID (0x2A32).
|
||||
/// </summary>
|
||||
public static Guid BootKeyboardOutputReport { get => Utilities.CreateUuidFromShortCode(0x2A32); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined BootMouseInputReport characteristic UUID (0x2A33).
|
||||
/// </summary>
|
||||
public static Guid BootMouseInputReport { get => Utilities.CreateUuidFromShortCode(0x2A33); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Current Time characteristic UUID (0x2A2B).
|
||||
/// </summary>
|
||||
public static Guid CurrentTime { get => Utilities.CreateUuidFromShortCode(0x2A2B); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined CyclingPowerControlPoint characteristic UUID (0x2A66).
|
||||
/// </summary>
|
||||
public static Guid CyclingPowerControlPoint { get => Utilities.CreateUuidFromShortCode(0x2A66); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Reference Time Information characteristic UUID (0x2A14).
|
||||
/// </summary>
|
||||
public static Guid ReferenceTimeInformation { get => Utilities.CreateUuidFromShortCode(0x2A14); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Cycling Power Measurement characteristic UUID (0x2A63).
|
||||
/// </summary>
|
||||
public static Guid CyclingPowerMeasurement { get => Utilities.CreateUuidFromShortCode(0x2A63); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Cycling Power Vector characteristic UUID (0x2A64).
|
||||
/// </summary>
|
||||
public static Guid CyclingPowerVector { get => Utilities.CreateUuidFromShortCode(0x2A64); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Date Time characteristic UUID (0x2A08).
|
||||
/// </summary>
|
||||
public static Guid DateTime { get => Utilities.CreateUuidFromShortCode(0x2A08); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Day Date Time characteristic UUID (0x2A0A).
|
||||
/// </summary>
|
||||
public static Guid DayDateTime { get => Utilities.CreateUuidFromShortCode(0x2A0A); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined DayOfWeek characteristic UUID (0x2A09).
|
||||
/// </summary>
|
||||
public static Guid DayOfWeek { get => Utilities.CreateUuidFromShortCode(0x2A09); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined DstOffset characteristic UUID (0x2A0D).
|
||||
/// </summary>
|
||||
public static Guid DstOffset { get => Utilities.CreateUuidFromShortCode(0x2A0D); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined ExactTime256 characteristic UUID (0x2A0C).
|
||||
/// </summary>
|
||||
public static Guid ExactTime256 { get => Utilities.CreateUuidFromShortCode(0x2A0C); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Firmware Revision String characteristic UUID (0x2A26).
|
||||
/// </summary>
|
||||
public static Guid FirmwareRevisionString { get => Utilities.CreateUuidFromShortCode(0x2A26); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Gap Appearance characteristic UUID (0x2A01).
|
||||
/// </summary>
|
||||
public static Guid GapAppearance { get => Utilities.CreateUuidFromShortCode(0x2A01); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Gap DeviceName characteristic UUID (0x2A00).
|
||||
/// </summary>
|
||||
public static Guid GapDeviceName { get => Utilities.CreateUuidFromShortCode(0x2A00); }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// The result of NotifyValue
|
||||
/// </summary>
|
||||
public class GattClientNotificationResult
|
||||
{
|
||||
private readonly byte _result;
|
||||
private readonly GattCommunicationStatus _status;
|
||||
private readonly GattSubscribedClient _client;
|
||||
private readonly ushort _bytesSent;
|
||||
|
||||
internal GattClientNotificationResult(byte result, GattCommunicationStatus status, GattSubscribedClient client, ushort bytesSent)
|
||||
{
|
||||
_result = result;
|
||||
_status = status;
|
||||
_client = client;
|
||||
_bytesSent = bytesSent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the protocol error.
|
||||
/// </summary>
|
||||
public byte ProtocolError { get => _result; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GATT communication status.
|
||||
/// </summary>
|
||||
public GattCommunicationStatus Status { get => _status; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the subscribed client.
|
||||
/// </summary>
|
||||
public GattSubscribedClient SubscribedClient { get => _client; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bytes that were sent.
|
||||
/// </summary>
|
||||
public ushort BytesSent { get => _bytesSent; }
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the return status of a GATT API related operation.
|
||||
/// </summary>
|
||||
public enum GattCommunicationStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The operation completed successfully.
|
||||
/// </summary>
|
||||
Success = 0,
|
||||
|
||||
/// <summary>
|
||||
/// No communication can be performed with the device, at this time.
|
||||
/// </summary>
|
||||
Unreachable = 1,
|
||||
|
||||
/// <summary>
|
||||
/// There was a GATT communication protocol error.
|
||||
/// </summary>
|
||||
ProtocolError = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Access is denied.
|
||||
/// </summary>
|
||||
AccessDenied = 3
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an enumeration of the most well known Descriptor UUID values, and
|
||||
/// provides convenience methods for working with GATT descriptor UUIDs, and static
|
||||
/// properties providing descriptor UUIDs for common GATT descriptors.
|
||||
/// </summary>
|
||||
public static class GattDescriptorUuids
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Characteristic Aggregate Format Descriptor UUID.
|
||||
/// </summary>
|
||||
public static Guid CharacteristicAggregateFormat { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.CharacteristicAggregateFormat); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Characteristic Extended Properties Descriptor UUID.
|
||||
/// </summary>
|
||||
public static Guid CharacteristicExtendedProperties { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.CharacteristicExtendedProperties); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Characteristic Presentation Format Descriptor
|
||||
/// </summary>
|
||||
public static Guid CharacteristicPresentationFormat { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.CharacteristicPresentationFormat); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Characteristic User Description Descriptor UUID.
|
||||
/// </summary>
|
||||
public static Guid CharacteristicUserDescription { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.CharacteristicUserDescription); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Client Characteristic Configuration Descriptor UUID.
|
||||
/// </summary>
|
||||
public static Guid ClientCharacteristicConfiguration { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.ClientCharacteristicConfiguration); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Server Characteristic Configuration Descriptor UUID.
|
||||
/// </summary>
|
||||
public static Guid ServerCharacteristicConfiguration { get => Utilities.CreateUuidFromShortCode((ushort)Utilities.GattNativeDescriptorUuid.ServerCharacteristicConfiguration); }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,401 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents a local characteristic.
|
||||
/// </summary>
|
||||
public sealed class GattLocalCharacteristic
|
||||
{
|
||||
private static ushort GattLocalCharacteristicIndex = 0;
|
||||
|
||||
// Each Characteristic will have unique _CharacteristicId for event lookup
|
||||
internal ushort _characteristicId;
|
||||
|
||||
private readonly byte[] _characteristicUuid;
|
||||
private readonly GattProtectionLevel _writeProtectionLevel;
|
||||
private readonly GattProtectionLevel _readProtectionLevel;
|
||||
private readonly GattCharacteristicProperties _properties;
|
||||
private readonly ArrayList _descriptors;
|
||||
private readonly ArrayList _subscribedClients;
|
||||
|
||||
// Built in descriptors
|
||||
private readonly string _userDescription;
|
||||
private readonly GattLocalDescriptor _userDescriptionDescriptor;
|
||||
|
||||
private readonly ArrayList _presentationFormats;
|
||||
private readonly ArrayList _presentationFormatsDescriptors; // of GattLocalDescriptor
|
||||
|
||||
private readonly Buffer _staticValue;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for Read requests
|
||||
/// </summary>
|
||||
/// <param name="sender">GattLocalCharacteristic sending event</param>
|
||||
/// <param name="ReadRequestEventArgs">Event arguments</param>
|
||||
public delegate void GattLocalCharacteristicReadEventHandler(GattLocalCharacteristic sender, GattReadRequestedEventArgs ReadRequestEventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for Write requests
|
||||
/// </summary>
|
||||
/// <param name="sender">GattLocalCharacteristic sending event</param>
|
||||
/// <param name="WriteRequestEventArgs">Event arguments</param>
|
||||
public delegate void GattLocalCharacteristicWriteEventHandler(GattLocalCharacteristic sender, GattWriteRequestedEventArgs WriteRequestEventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for Clients Changed events
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="args"></param>
|
||||
public delegate void GattLocalCharacteristicClientsChangedEventHandler(GattLocalCharacteristic sender, object args);
|
||||
|
||||
internal GattLocalCharacteristic(Guid characteristicUuid, GattLocalCharacteristicParameters parameters)
|
||||
{
|
||||
_characteristicUuid = characteristicUuid.ToByteArray();
|
||||
_writeProtectionLevel = parameters.WriteProtectionLevel;
|
||||
_readProtectionLevel = parameters.ReadProtectionLevel;
|
||||
|
||||
_properties = parameters.CharacteristicProperties;
|
||||
|
||||
_staticValue = parameters.StaticValue;
|
||||
|
||||
_descriptors = new ArrayList();
|
||||
_subscribedClients = new ArrayList();
|
||||
|
||||
// Give it next id
|
||||
_characteristicId = NextCharacteristicIndex();
|
||||
|
||||
_userDescription = parameters.UserDescription;
|
||||
if (!string.IsNullOrEmpty(_userDescription))
|
||||
{
|
||||
GattLocalDescriptorParameters dp = new GattLocalDescriptorParameters();
|
||||
|
||||
// Create Static value for User description
|
||||
DataWriter dr = new DataWriter();
|
||||
dr.WriteString(_userDescription);
|
||||
dp.StaticValue = dr.DetachBuffer();
|
||||
|
||||
_userDescriptionDescriptor = new GattLocalDescriptor(GattDescriptorUuids.CharacteristicUserDescription, dp, this);
|
||||
}
|
||||
|
||||
_presentationFormats = new ArrayList();
|
||||
_presentationFormatsDescriptors = new ArrayList();
|
||||
foreach (GattPresentationFormat gpf in parameters.PresentationFormats)
|
||||
{
|
||||
_presentationFormats.Add(gpf);
|
||||
|
||||
// Create Static value for PresentationFormat
|
||||
DataWriter dr = new DataWriter();
|
||||
|
||||
dr.WriteByte(gpf.FormatType);
|
||||
dr.WriteInt32(gpf.Exponent);
|
||||
dr.WriteUInt16(gpf.Unit);
|
||||
dr.WriteByte(gpf.Namespace);
|
||||
dr.WriteUInt16(gpf.Description);
|
||||
|
||||
GattLocalDescriptorParameters dp = new GattLocalDescriptorParameters();
|
||||
dp.StaticValue = dr.DetachBuffer();
|
||||
|
||||
_presentationFormatsDescriptors.Add(new GattLocalDescriptor(GattDescriptorUuids.CharacteristicPresentationFormat, dp, this));
|
||||
}
|
||||
|
||||
// Register with Events
|
||||
GattServiceProvider._bluetoothEventManager.AddCharacteristic(this);
|
||||
}
|
||||
|
||||
private static ushort NextCharacteristicIndex()
|
||||
{
|
||||
return ++GattLocalCharacteristicIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates descriptor for this local characteristic.
|
||||
/// </summary>
|
||||
/// <param name="descriptorUuid">The descriptor UUID.</param>
|
||||
/// <param name="parameters">The parameters for the descriptor.</param>
|
||||
/// <returns>A GattLocalDescriptorResult object.</returns>
|
||||
public GattLocalDescriptorResult CreateDescriptor(Guid descriptorUuid, GattLocalDescriptorParameters parameters)
|
||||
{
|
||||
GattLocalDescriptor decriptor = null;
|
||||
BluetoothError result = BluetoothError.Success;
|
||||
|
||||
// Validate uuid
|
||||
// Not already present in array
|
||||
foreach (GattLocalDescriptor des in _descriptors)
|
||||
{
|
||||
if (descriptorUuid.Equals(des.Uuid))
|
||||
{
|
||||
result = BluetoothError.ResourceInUse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Not a standard descriptor
|
||||
ushort suuid = Utilities.ConvertUuidToShortId(descriptorUuid);
|
||||
if (suuid == (ushort)Utilities.GattNativeDescriptorUuid.CharacteristicUserDescription ||
|
||||
suuid == (ushort)Utilities.GattNativeDescriptorUuid.CharacteristicPresentationFormat)
|
||||
{
|
||||
result = BluetoothError.ResourceInUse;
|
||||
}
|
||||
|
||||
if (result == BluetoothError.Success)
|
||||
{
|
||||
decriptor = new GattLocalDescriptor(descriptorUuid, parameters, this);
|
||||
_descriptors.Add(new GattLocalDescriptor(descriptorUuid, parameters, this));
|
||||
}
|
||||
|
||||
return new GattLocalDescriptorResult(decriptor, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send and notifies all subscribed clients a GattSubscribedClient of a value.
|
||||
/// </summary>
|
||||
/// <param name="value">The buffer that contains the value to send to the GattSubscribedClient.</param>
|
||||
/// <returns>
|
||||
/// An array of all the GattClientNotificationResult for each subscribed client.
|
||||
/// </returns>
|
||||
public GattClientNotificationResult[] NotifyValue(Buffer value)
|
||||
{
|
||||
GattClientNotificationResult[] results = new GattClientNotificationResult[_subscribedClients.Count];
|
||||
|
||||
lock (_subscribedClients)
|
||||
{
|
||||
for (int index = 0; index < _subscribedClients.Count; index++)
|
||||
{
|
||||
GattSubscribedClient client = (GattSubscribedClient)_subscribedClients[index];
|
||||
results[index] = NotifyValue(value, client);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends and notifies a GattSubscribedClient of a value.
|
||||
/// </summary>
|
||||
/// <param name="value">The buffer that contains the value to send to the GattSubscribedClient</param>
|
||||
/// <param name="subscribedClient">The subscribed client notify the value.</param>
|
||||
/// <returns></returns>
|
||||
public GattClientNotificationResult NotifyValue(Buffer value, GattSubscribedClient subscribedClient)
|
||||
{
|
||||
GattClientNotificationResult result;
|
||||
|
||||
Byte[] buffer = new byte[value.Length];
|
||||
Array.Copy(value.Data, buffer, (int)value.Length);
|
||||
|
||||
int rc = NativeNotifyClient((ushort)subscribedClient.Session.DeviceId.Id, _characteristicId, buffer);
|
||||
|
||||
result = new GattClientNotificationResult((byte)rc, rc == 0 ? GattCommunicationStatus.Success : GattCommunicationStatus.Unreachable, subscribedClient, (ushort)value.Length);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local characteristic properties.
|
||||
/// </summary>
|
||||
public GattCharacteristicProperties CharacteristicProperties { get => _properties; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a vector list of all the descriptors for this local characteristic.
|
||||
/// </summary>
|
||||
public GattLocalDescriptor[] Descriptors { get => (GattLocalDescriptor[])_descriptors.ToArray(); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the presentation formats for this local characteristic.
|
||||
/// </summary>
|
||||
public GattPresentationFormat[] PresentationFormats { get => (GattPresentationFormat[])_presentationFormats.ToArray(typeof(GattPresentationFormat)); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the read protection level of this local characteristic.
|
||||
/// </summary>
|
||||
public GattProtectionLevel ReadProtectionLevel { get => _readProtectionLevel; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the static value for this local GATT characteristic.
|
||||
/// </summary>
|
||||
public Buffer StaticValue { get => _staticValue; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array of all clients that are subscribed to this local characteristic.
|
||||
/// </summary>
|
||||
public GattSubscribedClient[] SubscribedClients { get => (GattSubscribedClient[])_subscribedClients.ToArray(typeof(GattSubscribedClient)); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user-friendly description for this local characteristic.
|
||||
/// </summary>
|
||||
public string UserDescription { get => _userDescription; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the BluetoothSIG-defined UUID for this local characteristic.
|
||||
/// </summary>
|
||||
public Guid Uuid { get => new Guid(_characteristicUuid); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the write protection level of this local characteristic.
|
||||
/// </summary>
|
||||
public GattProtectionLevel WriteProtectionLevel { get => _writeProtectionLevel; }
|
||||
|
||||
/// <summary>
|
||||
/// An event that is triggered when a GATT client requests a read operation.
|
||||
/// </summary>
|
||||
public event GattLocalCharacteristicReadEventHandler ReadRequested;
|
||||
|
||||
/// <summary>
|
||||
/// This is an event that is triggered when a write was requested.
|
||||
/// </summary>
|
||||
public event GattLocalCharacteristicWriteEventHandler WriteRequested;
|
||||
|
||||
/// <summary>
|
||||
/// An event that triggers when clients subscribed to this local characteristic changes.
|
||||
/// </summary>
|
||||
public event GattLocalCharacteristicClientsChangedEventHandler SubscribedClientsChanged;
|
||||
|
||||
internal void OnReadRequested(ushort descritorId, GattReadRequestedEventArgs e)
|
||||
{
|
||||
bool handled = false;
|
||||
|
||||
// Static value for Characteristic ?
|
||||
if (_staticValue != null && descritorId == 0)
|
||||
{
|
||||
handled = true;
|
||||
// Handle static values internally, don't fire an event
|
||||
DataWriter writer = new DataWriter();
|
||||
writer.WriteBuffer(_staticValue);
|
||||
e.GetRequest().RespondWithValue(_staticValue);
|
||||
}
|
||||
else if (descritorId != 0)
|
||||
{
|
||||
// Descriptor event, let descriptor handle it
|
||||
GattLocalDescriptor des = FindDescriptor(descritorId);
|
||||
if (des != null)
|
||||
{
|
||||
handled = des.OnReadRequested(e);
|
||||
}
|
||||
}
|
||||
else if (ReadRequested != null)
|
||||
{
|
||||
// LocalCharacteristic event ?
|
||||
handled = true;
|
||||
ReadRequested?.Invoke(this, e);
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
// No event handler, respond with error
|
||||
e.GetRequest().RespondWithProtocolError(GattProtocolError.UnlikelyError);
|
||||
}
|
||||
}
|
||||
|
||||
internal void OnWriteRequested(ushort descritorId, GattWriteRequestedEventArgs e)
|
||||
{
|
||||
bool handled = false;
|
||||
|
||||
if (WriteRequested != null)
|
||||
{
|
||||
// LocalCharacteristic event ?
|
||||
if (descritorId == 0)
|
||||
{
|
||||
handled = true;
|
||||
WriteRequested?.Invoke(this, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Descriptor event
|
||||
GattLocalDescriptor des = FindDescriptor(descritorId);
|
||||
if (des != null)
|
||||
{
|
||||
handled = des.OnWriteRequested(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
// No event handler, respond with error
|
||||
e.GetRequest().RespondWithProtocolError(GattProtocolError.UnlikelyError);
|
||||
}
|
||||
}
|
||||
|
||||
private int ClientSubscribed(GattSubscribedClient client)
|
||||
{
|
||||
lock (_subscribedClients)
|
||||
{
|
||||
for (int index = 0; index < _subscribedClients.Count; index++)
|
||||
{
|
||||
if (((GattSubscribedClient)_subscribedClients[index]).Session.DeviceId.Id == client.Session.DeviceId.Id)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
internal void OnSubscribedClientsChanged(bool subscribe, GattSubscribedClient client)
|
||||
{
|
||||
lock (_subscribedClients)
|
||||
{
|
||||
int index = ClientSubscribed(client);
|
||||
|
||||
if (subscribe)
|
||||
{
|
||||
if (index < 0)
|
||||
{
|
||||
_subscribedClients.Add(client);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index >= 0)
|
||||
{
|
||||
_subscribedClients.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SubscribedClientsChanged?.Invoke(this, null);
|
||||
}
|
||||
|
||||
private GattLocalDescriptor FindDescriptor(ushort id)
|
||||
{
|
||||
// Check In built ones first
|
||||
if (_userDescriptionDescriptor != null && _userDescriptionDescriptor._descriptorId == id)
|
||||
{
|
||||
return _userDescriptionDescriptor;
|
||||
}
|
||||
|
||||
// Check PresentationFormats
|
||||
foreach (GattLocalDescriptor desc in _presentationFormatsDescriptors)
|
||||
{
|
||||
if (desc._descriptorId == id)
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
||||
// Check other descriptors
|
||||
foreach (GattLocalDescriptor desc in _descriptors)
|
||||
{
|
||||
if (desc._descriptorId == id)
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
#region Native
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private extern int NativeNotifyClient(ushort connection, ushort CharacteristicId, byte[] notifyBuffer);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.Collections;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains the local characteristic descriptor parameters.
|
||||
/// </summary>
|
||||
public class GattLocalCharacteristicParameters
|
||||
{
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private GattProtectionLevel _writeProtectionLevel;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private GattProtectionLevel _readProtectionLevel;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private string _userDescription;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private GattCharacteristicProperties _properties;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private Buffer _staticValue;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private readonly ArrayList _presentationFormats;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GattLocalCharacteristicParameters object.
|
||||
/// </summary>
|
||||
public GattLocalCharacteristicParameters()
|
||||
{
|
||||
_writeProtectionLevel = GattProtectionLevel.Plain;
|
||||
_readProtectionLevel = GattProtectionLevel.Plain;
|
||||
_userDescription = "";
|
||||
_properties = GattCharacteristicProperties.None;
|
||||
_presentationFormats = new ArrayList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the write protection level.
|
||||
/// </summary>
|
||||
public GattProtectionLevel WriteProtectionLevel { get => _writeProtectionLevel; set => _writeProtectionLevel = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the user-friendly description.
|
||||
/// </summary>
|
||||
public string UserDescription { get => _userDescription; set => _userDescription = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the static value.
|
||||
/// </summary>
|
||||
public Buffer StaticValue { get => _staticValue; set => _staticValue = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the read protection level.
|
||||
/// </summary>
|
||||
public GattProtectionLevel ReadProtectionLevel { get => _readProtectionLevel; set => _readProtectionLevel = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the properties.
|
||||
/// </summary>
|
||||
public GattCharacteristicProperties CharacteristicProperties { get => _properties; set => _properties = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the presentation formats arrayLIst
|
||||
/// </summary>
|
||||
public GattPresentationFormat[] PresentationFormats { get => (GattPresentationFormat[])_presentationFormats.ToArray(typeof(GattPresentationFormat)); }
|
||||
|
||||
/// <summary>
|
||||
/// Create a GattPresentationFormat to the GattLocalCharacteristicParameters
|
||||
/// </summary>
|
||||
public void CreateGattPresentationFormat(byte formatType, int exponent, ushort unit, byte namespaceId, ushort decsription)
|
||||
{
|
||||
_presentationFormats.Add(new GattPresentationFormat(formatType, exponent, unit, namespaceId, decsription));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// A result of CreateCharacteristic
|
||||
/// </summary>
|
||||
public class GattLocalCharacteristicResult
|
||||
{
|
||||
private readonly GattLocalCharacteristic _characteristic;
|
||||
private readonly BluetoothError _error;
|
||||
|
||||
internal GattLocalCharacteristicResult(GattLocalCharacteristic Characteristic, BluetoothError Error)
|
||||
{
|
||||
_characteristic = Characteristic;
|
||||
_error = Error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the characteristic of the GATT service.
|
||||
/// </summary>
|
||||
public GattLocalCharacteristic Characteristic { get => _characteristic; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth error.
|
||||
/// </summary>
|
||||
public BluetoothError Error { get => _error; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class defines a descriptor of a local characteristic.
|
||||
/// </summary>
|
||||
public sealed class GattLocalDescriptor
|
||||
{
|
||||
private static ushort GattLocalDescriptorIndex = 0;
|
||||
|
||||
// Each Descriptor will have unique _descriptorId for event lookup, events for descriptors are handled by User app.
|
||||
// This comprises of characteristic ID + GattLocalDescriptorIndex in the form
|
||||
// x'DDCC' where DD is Descriptor and CC characteristic
|
||||
internal ushort _descriptorId;
|
||||
|
||||
private readonly GattLocalCharacteristic _charactisic;
|
||||
|
||||
private readonly GattProtectionLevel _writeProtectionLevel;
|
||||
private readonly GattProtectionLevel _readProtectionLevel;
|
||||
private readonly byte[] _uuid;
|
||||
|
||||
private readonly Buffer _staticValue;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for Read requests
|
||||
/// </summary>
|
||||
/// <param name="sender">GattLocalDescriptor sending event</param>
|
||||
/// <param name="ReadRequestEventArgs">Event arguments</param>
|
||||
public delegate void GattLocalDescriptorReadEventHandler(GattLocalCharacteristic sender, GattReadRequestedEventArgs ReadRequestEventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for Write requests
|
||||
/// </summary>
|
||||
/// <param name="sender">GattLocalDescriptor sending event</param>
|
||||
/// <param name="WriteRequestEventArgs">Event arguments</param>
|
||||
public delegate void GattLocalDescriptorWriteEventHandler(GattLocalCharacteristic sender, GattWriteRequestedEventArgs WriteRequestEventArgs);
|
||||
|
||||
internal GattLocalDescriptor(Guid uuid, GattLocalDescriptorParameters parameters, GattLocalCharacteristic charactisic)
|
||||
{
|
||||
_uuid = uuid.ToByteArray();
|
||||
_charactisic = charactisic;
|
||||
|
||||
_writeProtectionLevel = parameters.WriteProtectionLevel;
|
||||
_readProtectionLevel = parameters.ReadProtectionLevel;
|
||||
_staticValue = parameters.StaticValue;
|
||||
|
||||
_descriptorId = (ushort)((NextDescriptorIndex() << 8) + _charactisic._characteristicId);
|
||||
}
|
||||
|
||||
private static ushort NextDescriptorIndex()
|
||||
{
|
||||
return ++GattLocalDescriptorIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the read protection level of this local characteristic descriptor.
|
||||
/// </summary>
|
||||
public GattProtectionLevel ReadProtectionLevel { get => _readProtectionLevel; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the static value for this local characteristic descriptor.
|
||||
/// </summary>
|
||||
public Buffer StaticValue { get => _staticValue; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined UUID for this local characteristic descriptor.
|
||||
/// </summary>
|
||||
public Guid Uuid { get => new Guid(_uuid); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the write protection level.
|
||||
/// </summary>
|
||||
public GattProtectionLevel WriteProtectionLevel { get => _writeProtectionLevel; }
|
||||
|
||||
/// <summary>
|
||||
/// An event that is triggered when a GATT client requests a descriptor read operation.
|
||||
/// </summary>
|
||||
public event GattLocalDescriptorReadEventHandler ReadRequested;
|
||||
|
||||
/// <summary>
|
||||
/// This is an event that is triggered when a write descriptor was requested.
|
||||
/// </summary>
|
||||
public event GattLocalDescriptorWriteEventHandler WriteRequested;
|
||||
|
||||
internal bool OnReadRequested(GattReadRequestedEventArgs e)
|
||||
{
|
||||
if (_staticValue != null)
|
||||
{
|
||||
e.GetRequest().RespondWithValue(_staticValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ReadRequested != null)
|
||||
{
|
||||
ReadRequested?.Invoke(_charactisic, e);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal bool OnWriteRequested(GattWriteRequestedEventArgs e)
|
||||
{
|
||||
if (WriteRequested != null)
|
||||
{
|
||||
WriteRequested?.Invoke(_charactisic, e);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class defines the parameters of a descriptor.
|
||||
/// </summary>
|
||||
public sealed class GattLocalDescriptorParameters //: IGattLocalDescriptorParameters
|
||||
{
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private GattProtectionLevel _writeProtectionLevel;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private GattProtectionLevel _readProtectionLevel;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private Buffer _staticValue = null;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GattLocalDescriptorParameters object.
|
||||
/// </summary>
|
||||
public GattLocalDescriptorParameters()
|
||||
{
|
||||
_writeProtectionLevel = GattProtectionLevel.Plain;
|
||||
_readProtectionLevel = GattProtectionLevel.Plain;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the write protection level.
|
||||
/// </summary>
|
||||
public GattProtectionLevel WriteProtectionLevel { get => _writeProtectionLevel; set => _writeProtectionLevel = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the static value.
|
||||
/// </summary>
|
||||
public Buffer StaticValue { get => _staticValue; set => _staticValue = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the read protection level.
|
||||
/// </summary>
|
||||
public GattProtectionLevel ReadProtectionLevel { get => _readProtectionLevel; set => _readProtectionLevel = value; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// The result of local characteristic descriptor operations like CreateDescriptorAsync.
|
||||
/// </summary>
|
||||
public sealed class GattLocalDescriptorResult //: IGattLocalDescriptorResult
|
||||
{
|
||||
private readonly BluetoothError _error;
|
||||
private readonly GattLocalDescriptor _descriptor;
|
||||
|
||||
internal GattLocalDescriptorResult(GattLocalDescriptor descriptor, BluetoothError error)
|
||||
{
|
||||
_descriptor = descriptor;
|
||||
_error = Error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the descriptor.
|
||||
/// </summary>
|
||||
public GattLocalDescriptor Descriptor { get => _descriptor; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the error.
|
||||
/// </summary>
|
||||
public BluetoothError Error { get => _error; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents a GATT local service.
|
||||
/// </summary>
|
||||
public sealed class GattLocalService
|
||||
{
|
||||
private readonly byte[] _serviceUuid;
|
||||
private readonly ArrayList _characteristics;
|
||||
|
||||
internal GattLocalService(Guid serviceUuid)
|
||||
{
|
||||
_serviceUuid = serviceUuid.ToByteArray();
|
||||
_characteristics = new ArrayList();
|
||||
_characteristics.Add(new GattLocalCharacteristic(serviceUuid, new GattLocalCharacteristicParameters()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a characteristic for this local service.
|
||||
/// </summary>
|
||||
/// <param name="characteristicUuid">The characteristic UUID.</param>
|
||||
/// <param name="parameters">The characteristic parameters.</param>
|
||||
/// <returns>An GattLocalCharacteristicResult object</returns>
|
||||
public GattLocalCharacteristicResult CreateCharacteristic(Guid characteristicUuid, GattLocalCharacteristicParameters parameters)
|
||||
{
|
||||
GattLocalCharacteristic Characteristic = new GattLocalCharacteristic(characteristicUuid, parameters);
|
||||
_characteristics.Add(Characteristic);
|
||||
|
||||
return new GattLocalCharacteristicResult(Characteristic, BluetoothError.Success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a array of the characteristics available for this local service.
|
||||
/// </summary>
|
||||
public GattLocalCharacteristic[] Characteristics { get { return (GattLocalCharacteristic[])_characteristics.ToArray(typeof(GattLocalCharacteristic)); } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local service UUID.
|
||||
/// </summary>
|
||||
public Guid Uuid { get => new Guid(_serviceUuid); }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the value of a single Presentation Format GATT Descriptor.
|
||||
/// </summary>
|
||||
public class GattPresentationFormat
|
||||
{
|
||||
private readonly byte _formatType;
|
||||
private readonly int _exponent;
|
||||
private readonly ushort _unit;
|
||||
private readonly byte _namespaceId;
|
||||
private readonly ushort _description;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a GattPresentationFormat object from parts.
|
||||
/// </summary>
|
||||
/// <param name="formatType">The Format Type.</param>
|
||||
/// <param name="exponent">The exponent.</param>
|
||||
/// <param name="unit">The unit.</param>
|
||||
/// <param name="namespaceId">The namespace ID.</param>
|
||||
/// <param name="description">The description.</param>
|
||||
/// <returns>An instance of GattPresentationFormat.</returns>
|
||||
public static GattPresentationFormat FromParts(byte formatType, int exponent, ushort unit, byte namespaceId, ushort description)
|
||||
{
|
||||
return new GattPresentationFormat(formatType, exponent, unit, namespaceId, description);
|
||||
}
|
||||
|
||||
internal GattPresentationFormat(byte formatType, int exponent, ushort unit, byte namespaceId, ushort description)
|
||||
{
|
||||
_formatType = formatType;
|
||||
_exponent = exponent;
|
||||
_unit = unit;
|
||||
_namespaceId = namespaceId;
|
||||
_description = description;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Description of the GattPresentationFormat object.
|
||||
/// </summary>
|
||||
public ushort Description { get => _description; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Exponent of the GattPresentationFormat object.
|
||||
/// </summary>
|
||||
public int Exponent { get => _exponent; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Format Type of the GattPresentationFormat object.
|
||||
/// </summary>
|
||||
public byte FormatType { get => _formatType; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Name space of the GattPresentationFormat object.
|
||||
/// </summary>
|
||||
public byte Namespace { get => _namespaceId; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Unit of the GattPresentationFormat object.
|
||||
/// </summary>
|
||||
public ushort Unit { get => _unit; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the different well-known values that the GattPresentationFormat.FormatType
|
||||
/// property can take.
|
||||
/// </summary>
|
||||
public static class GattPresentationFormatTypes
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the value of the Bit2 Format Type.
|
||||
/// </summary>
|
||||
public static byte Bit2 { get => 0x02; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the Boolean Format Type.
|
||||
/// </summary>
|
||||
public static byte Boolean { get => 0x01; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the DUInt16 Format Type.
|
||||
/// </summary>
|
||||
public static byte DUInt16 { get => 0x18; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the Float Format Type.
|
||||
/// </summary>
|
||||
public static byte Float { get => 0x17; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the Float32 Format Type.
|
||||
/// </summary>
|
||||
public static byte Float32 { get => 0x14; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the Float64 Format Type.
|
||||
/// </summary>
|
||||
public static byte Float64 { get => 0x15; }
|
||||
/// <summary>
|
||||
/// Gets the value of the Nibble Format Type.
|
||||
/// </summary>
|
||||
public static byte Nibble { get => 0x03; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the SFloat Format Type.
|
||||
/// </summary>
|
||||
public static byte SFloat { get => 0x16; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the SInt12 Format Type.
|
||||
/// </summary>
|
||||
public static byte SInt12 { get => 0x0d; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the SInt128 Format Type.
|
||||
/// </summary>
|
||||
public static byte SInt128 { get => 0x13; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the SInt16 Format Type.
|
||||
/// </summary>
|
||||
public static byte SInt16 { get => 0x0e; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the SInt24 Format Type.
|
||||
/// </summary>
|
||||
public static byte SInt24 { get => 0x0f; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the SInt32 Format Type.
|
||||
/// </summary>
|
||||
public static byte SInt32 { get => 0x10; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the SInt48 Format Type.
|
||||
/// </summary>
|
||||
public static byte SInt48 { get => 0x11; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the SInt64 Format Type.
|
||||
/// </summary>
|
||||
public static byte SInt64 { get => 0x12; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the SInt8 Format Type.
|
||||
/// </summary>
|
||||
public static byte SInt8 { get => 0x0c; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the Struct Format Type.
|
||||
/// </summary>
|
||||
public static byte Struct { get => 0x1b; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the UInt12 Format Type.
|
||||
/// </summary>
|
||||
public static byte UInt12 { get => 0x05; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the UInt128 Format Type.
|
||||
/// </summary>
|
||||
public static byte UInt128 { get => 0x0b; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the UInt16 Format Type.
|
||||
/// </summary>
|
||||
public static byte UInt16 { get => 0x06; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the UInt24 Format Type.
|
||||
/// </summary>
|
||||
public static byte UInt24 { get => 0x07; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the UInt32 Format Type.
|
||||
/// </summary>
|
||||
public static byte UInt32 { get => 0x08; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the UInt48 Format Type.
|
||||
/// </summary>
|
||||
public static byte UInt48 { get => 0x09; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the UInt64 Format Type.
|
||||
/// </summary>
|
||||
public static byte UInt64 { get => 0x0a; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the UInt8 Format Type.
|
||||
/// </summary>
|
||||
public static byte UInt8 { get => 0x04; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the Utf16 Format Type.
|
||||
/// </summary>
|
||||
public static byte Utf16 { get => 0x1a; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the Utf8 Format Type.
|
||||
/// </summary>
|
||||
public static byte Utf8 { get => 0x8; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the desired security level.
|
||||
/// </summary>
|
||||
public enum GattProtectionLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// Uses the default protection level.
|
||||
/// </summary>
|
||||
Plain = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Require the link to be authenticated.
|
||||
/// </summary>
|
||||
AuthenticationRequired = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Require the link to be encrypted.
|
||||
/// </summary>
|
||||
EncryptionRequired = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Require the link to be encrypted and authenticated.
|
||||
/// </summary>
|
||||
EncryptionAndAuthenticationRequired = 3
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains byte values for GATT protocol errors.
|
||||
/// </summary>
|
||||
public static class GattProtocolError
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the byte value for an attribute not found error.
|
||||
/// </summary>
|
||||
public static byte AttributeNotFound { get => 10; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for an attribute not long error.
|
||||
/// </summary>
|
||||
public static byte AttributeNotLong { get => 11; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for an insufficient authentication error.
|
||||
/// </summary>
|
||||
public static byte InsufficientAuthentication { get => 5; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for an insufficient authorization error.
|
||||
/// </summary>
|
||||
public static byte InsufficientAuthorization { get => 8; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for an insufficient encryption error.
|
||||
/// </summary>
|
||||
public static byte InsufficientEncryption { get => 15; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for an insufficient encryption key size error.
|
||||
/// </summary>
|
||||
public static byte InsufficientEncryptionKeySize { get => 12; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for an insufficient resources error.
|
||||
/// </summary>
|
||||
public static byte InsufficientResources { get => 17; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for an invalid attribute value length error.
|
||||
/// </summary>
|
||||
public static byte InvalidAttributeValueLength { get => 13; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for an invalid handle error.
|
||||
/// </summary>
|
||||
public static byte InvalidHandle { get => 1; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for an invalid offset error.
|
||||
/// </summary>
|
||||
public static byte InvalidOffset { get => 7; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for an invalid PDU error.
|
||||
/// </summary>
|
||||
public static byte InvalidPdu { get => 4; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for a prepare queue full error.
|
||||
/// </summary>
|
||||
public static byte PrepareQueueFull { get => 9; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for a read not permitted error.
|
||||
/// </summary>
|
||||
public static byte ReadNotPermitted { get => 2; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for a request not supported error.
|
||||
/// </summary>
|
||||
public static byte RequestNotSupported { get => 6; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for an unlikely error.
|
||||
/// </summary>
|
||||
public static byte UnlikelyError { get => 14; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for an unsupported group type error.
|
||||
/// </summary>
|
||||
public static byte UnsupportedGroupType { get => 15; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte value for a write not permitted error.
|
||||
/// </summary>
|
||||
public static byte WriteNotPermitted { get => 3; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents a Bluetooth GATT read request.
|
||||
/// </summary>
|
||||
public class GattReadRequest
|
||||
{
|
||||
private Buffer _readValue;
|
||||
private readonly ushort _eventID;
|
||||
|
||||
internal GattReadRequest(ushort eventID)
|
||||
{
|
||||
_eventID = eventID;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Responds to a read request with a value.
|
||||
/// </summary>
|
||||
/// <param name="value"> The value to respond with.</param>
|
||||
public void RespondWithValue(Buffer value)
|
||||
{
|
||||
_readValue = value;
|
||||
|
||||
byte[] data = new byte[_readValue.Length];
|
||||
Array.Copy(_readValue.Data, data, (int)_readValue.Length);
|
||||
|
||||
NativeReadRespondWithValue(_eventID, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Responds to the read request with a protocol error.
|
||||
/// </summary>
|
||||
/// <param name="protocolError">The protocol error to send. A list of errors with the byte values can be found in GattProtocolError.</param>
|
||||
public void RespondWithProtocolError(byte protocolError)
|
||||
{
|
||||
NativeReadRespondWithProtocolError(_eventID, (byte)BluetoothError.OtherError);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the buffer length of the read request.
|
||||
/// </summary>
|
||||
public uint Length { get => _readValue.Length; }
|
||||
|
||||
#region external calls to native implementations
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private extern void NativeReadRespondWithValue(ushort eventID, byte[] value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private extern void NativeReadRespondWithProtocolError(ushort eventID, byte protocolError);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains the arguments for the StateChanged event.
|
||||
/// </summary>
|
||||
public sealed class GattReadRequestedEventArgs
|
||||
{
|
||||
private readonly ushort _eventID;
|
||||
private readonly GattSession _session = null;
|
||||
|
||||
internal GattReadRequestedEventArgs(ushort eventID, GattSession session)
|
||||
{
|
||||
_eventID = eventID;
|
||||
_session = session;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GATT read request.
|
||||
/// </summary>
|
||||
/// <returns>Returns a GattReadRequest object.</returns>
|
||||
public GattReadRequest GetRequest()
|
||||
{
|
||||
return new GattReadRequest(_eventID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the session.
|
||||
/// </summary>
|
||||
public GattSession Session { get => _session; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is used to advertise a GATT service.
|
||||
/// </summary>
|
||||
public sealed class GattServiceProvider
|
||||
{
|
||||
private readonly GattLocalService _service;
|
||||
|
||||
GattServiceProviderAdvertisementStatus _status = GattServiceProviderAdvertisementStatus.Created;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private byte[] _deviceName;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private bool _isDiscoverable = true;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private bool _isConnectable = true;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private Buffer _serviceData;
|
||||
|
||||
|
||||
internal static readonly BluetoothEventListener _bluetoothEventManager = new BluetoothEventListener();
|
||||
|
||||
internal GattServiceProvider(Guid serviceUuid)
|
||||
{
|
||||
_service = new GattLocalService(serviceUuid);
|
||||
|
||||
NativeInitService();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start advertising the GATT service.
|
||||
/// </summary>
|
||||
public void StartAdvertising()
|
||||
{
|
||||
StartAdvertising(new GattServiceProviderAdvertisingParameters());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start advertising the GATT service.
|
||||
/// </summary>
|
||||
/// <param name="parameters">The advertising parameters.</param>
|
||||
public void StartAdvertising(GattServiceProviderAdvertisingParameters parameters)
|
||||
{
|
||||
// Save parameters
|
||||
_isConnectable = parameters.IsConnectable;
|
||||
_isDiscoverable = parameters.IsDiscoverable;
|
||||
_serviceData = parameters.ServiceData;
|
||||
|
||||
_deviceName = Encoding.UTF8.GetBytes(parameters.DeviceName);
|
||||
|
||||
if (NativeStartAdvertising())
|
||||
{
|
||||
_status = GattServiceProviderAdvertisementStatus.Started;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop advertising the GATT service.
|
||||
/// </summary>
|
||||
public void StopAdvertising()
|
||||
{
|
||||
NativeStopAdvertising();
|
||||
|
||||
_status = GattServiceProviderAdvertisementStatus.Stopped;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GATT service with the specified serviceUuid
|
||||
/// </summary>
|
||||
/// <param name="serviceUuid">The service UUID.</param>
|
||||
/// <returns>A GattServiceProviderResult object.</returns>
|
||||
public static GattServiceProviderResult Create(Guid serviceUuid)
|
||||
{
|
||||
GattServiceProvider serviceProvider = new GattServiceProvider(serviceUuid);
|
||||
|
||||
return new GattServiceProviderResult(serviceProvider, BluetoothError.Success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the advertisement status of this GATT service.
|
||||
/// </summary>
|
||||
/// <Returns>The advertisement service.</Returns>
|
||||
public GattServiceProviderAdvertisementStatus AdvertisementStatus { get => _status; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GATT service.
|
||||
/// </summary>
|
||||
/// <returns>The GATT service.</returns>
|
||||
public GattLocalService Service { get => _service; }
|
||||
|
||||
#region external calls to native implementations
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private extern bool NativeInitService();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private extern bool NativeStartAdvertising();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private extern void NativeStopAdvertising();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This enumeration defines the advertisement status of a GattServiceProvider.
|
||||
/// </summary>
|
||||
public enum GattServiceProviderAdvertisementStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The GATT service was created.
|
||||
/// </summary>
|
||||
Created = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The GATT service is not advertising.
|
||||
/// </summary>
|
||||
Stopped = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The GATT service advertising has started.
|
||||
/// </summary>
|
||||
Started = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The GATT service was aborted.
|
||||
/// </summary>
|
||||
Aborted = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the system was successfully able to issue the advertisement request,
|
||||
/// but not all of the requested data could be included in the advertisement.</summary>
|
||||
StartedWithoutAllAdvertisementData = 4
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is used to define the GATT service advertisement parameters.
|
||||
/// </summary>
|
||||
public sealed class GattServiceProviderAdvertisingParameters
|
||||
{
|
||||
const string _defaultDeviceName = "nanoFramework";
|
||||
|
||||
private string _deviceName = _defaultDeviceName;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private bool _isDiscoverable = true;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private bool _isConnectable = true;
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private Buffer _serviceData;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GattServiceProviderAdvertisingParameters object.
|
||||
/// </summary>
|
||||
public GattServiceProviderAdvertisingParameters()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating that the GATT service is discoverable.
|
||||
/// </summary>
|
||||
public bool IsDiscoverable { get => _isDiscoverable; set => _isDiscoverable = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean that indicates if the GATT service is connect-able.
|
||||
/// </summary>
|
||||
public bool IsConnectable { get => _isConnectable; set => _isConnectable = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Friendly device name used for advertising service.
|
||||
/// Default "nanoFramework"
|
||||
/// </summary>
|
||||
public string DeviceName
|
||||
{
|
||||
get => _deviceName;
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
_deviceName = _defaultDeviceName;
|
||||
}
|
||||
else
|
||||
{
|
||||
_deviceName = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For Bluetooth Low Energy, this parameter adds an additional **ServiceData** section
|
||||
/// to the advertisement payload for the service's service UUID if space is available.
|
||||
/// If the service data is added to the advertisement, then the service UUID will
|
||||
/// also be included in the same section in the advertisement.
|
||||
/// </summary>
|
||||
public Buffer ServiceData { get => _serviceData; set => _serviceData = value; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is the result of the Create operation.
|
||||
/// </summary>
|
||||
public sealed class GattServiceProviderResult
|
||||
{
|
||||
private readonly GattServiceProvider _serviceProvider;
|
||||
private readonly BluetoothError _error;
|
||||
|
||||
internal GattServiceProviderResult(GattServiceProvider serviceProvider, BluetoothError error)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_error = error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the error.
|
||||
/// </summary>
|
||||
public BluetoothError Error { get => _error; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the service provider.
|
||||
/// </summary>
|
||||
public GattServiceProvider ServiceProvider { get => _serviceProvider; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an enumeration of the most well known Service UUID values, and provides
|
||||
/// convenience methods for working with GATT service UUIDs, and static properties
|
||||
/// providing service UUIDs for common GATT services. To view a list of all Bluetooth
|
||||
/// SIG-defined service UUIDs, see Bluetooth SIG-defined Service UUIDs.
|
||||
/// See:- https://btprodspecificationrefs.blob.core.windows.net/assigned-values/16-bit%20UUID%20Numbers%20Document.pdf
|
||||
/// Current Service UUID 0x1800 to 0x181D
|
||||
/// </summary>
|
||||
public static class GattServiceUuids
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined AlertNotification Service UUID.
|
||||
/// </summary>
|
||||
public static Guid AlertNotification { get => Utilities.CreateUuidFromShortCode(0x1811); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Automation IO Service UUID.
|
||||
/// </summary>
|
||||
public static Guid AutomationIO { get => Utilities.CreateUuidFromShortCode(0x1815); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Battery Service UUID.
|
||||
/// </summary>
|
||||
public static Guid Battery { get => Utilities.CreateUuidFromShortCode(0x180f); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Blood Pressure Service UUID.
|
||||
/// </summary>
|
||||
public static Guid BloodPressure { get => Utilities.CreateUuidFromShortCode(0x1810); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Body Composition Service UUID.
|
||||
/// </summary>
|
||||
public static Guid BodyComposition { get => Utilities.CreateUuidFromShortCode(0x181b); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined CurrentTime service UUID.
|
||||
/// </summary>
|
||||
public static Guid CurrentTime { get => Utilities.CreateUuidFromShortCode(0x1805); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined CyclingPower service UUID.
|
||||
/// </summary>
|
||||
public static Guid CyclingPower { get => Utilities.CreateUuidFromShortCode(0x1818); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Cycling Speed And Cadence Service UUID.
|
||||
/// </summary>
|
||||
public static Guid CyclingSpeedAndCadence { get => Utilities.CreateUuidFromShortCode(0x1816); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined DeviceInformation service UUID.
|
||||
/// </summary>
|
||||
public static Guid DeviceInformation { get => Utilities.CreateUuidFromShortCode(0x180a); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Environmental Sensing Service UUID.
|
||||
/// </summary>
|
||||
public static Guid EnvironmentalSensing { get => Utilities.CreateUuidFromShortCode(0x181a); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined UUID for the Generic Access Service.
|
||||
/// </summary>
|
||||
public static Guid GenericAccess { get => Utilities.CreateUuidFromShortCode(0x1800); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined UUID for the Generic Attribute Service.
|
||||
/// </summary>
|
||||
public static Guid GenericAttribute { get => Utilities.CreateUuidFromShortCode(0x1801); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Glucose Service UUID.
|
||||
/// </summary>
|
||||
public static Guid Glucose { get => Utilities.CreateUuidFromShortCode(0x1808); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Health Thermometer Service UUID.
|
||||
/// </summary>
|
||||
public static Guid HealthThermometer { get => Utilities.CreateUuidFromShortCode(0x1809); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Heart Rate Service UUID.
|
||||
/// </summary>
|
||||
public static Guid HeartRate { get => Utilities.CreateUuidFromShortCode(0x180d); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined HumanInterfaceDevice service UUID.
|
||||
/// </summary>
|
||||
public static Guid HumanInterfaceDevice { get => Utilities.CreateUuidFromShortCode(0x1812); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined ImmediateAlert service UUID.
|
||||
/// </summary>
|
||||
public static Guid ImmediateAlert { get => Utilities.CreateUuidFromShortCode(0x1802); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined LinkLoss service UUID.
|
||||
/// </summary>
|
||||
public static Guid LinkLoss {get => Utilities.CreateUuidFromShortCode(0x1803); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined LocationAndNavigation service UUID.
|
||||
/// </summary>
|
||||
public static Guid LocationAndNavigation { get => Utilities.CreateUuidFromShortCode(0x1819); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined NextDstChange service UUID.
|
||||
/// </summary>
|
||||
public static Guid NextDstChange { get => Utilities.CreateUuidFromShortCode(0x1807); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined PhoneAlertStatus service UUID.
|
||||
/// </summary>
|
||||
public static Guid PhoneAlertStatus { get => Utilities.CreateUuidFromShortCode(0x180e); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined ReferenceTimeUpdate service UUID.
|
||||
/// </summary>
|
||||
public static Guid ReferenceTimeUpdate { get => Utilities.CreateUuidFromShortCode(0x1806); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Running Speed And Cadence Service UUID.
|
||||
/// </summary>
|
||||
public static Guid RunningSpeedAndCadence { get => Utilities.CreateUuidFromShortCode(0x1814); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined ScanParameters service UUID.
|
||||
/// </summary>
|
||||
public static Guid ScanParameters { get => Utilities.CreateUuidFromShortCode(0x1813); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined TxPower service UUID.
|
||||
/// </summary>
|
||||
public static Guid TxPower { get => Utilities.CreateUuidFromShortCode(0x1804); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined User Data service UUID.
|
||||
/// </summary>
|
||||
public static Guid UserData { get => Utilities.CreateUuidFromShortCode(0x181c); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Bluetooth SIG-defined Weight Scale service UUID.
|
||||
/// </summary>
|
||||
public static Guid WeightScale { get => Utilities.CreateUuidFromShortCode(0x181d); }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents a GATT session.
|
||||
/// </summary>
|
||||
public sealed class GattSession : IDisposable
|
||||
{
|
||||
private readonly BluetoothDeviceId _deviceId;
|
||||
|
||||
/// <summary>
|
||||
/// Dispose GattSession object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
// not used yet
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GattSession object from the specified deviceId.
|
||||
/// </summary>
|
||||
/// <param name="deviceId">The deviceId.</param>
|
||||
/// <returns> A new GattSession object.</returns>
|
||||
public static GattSession FromDeviceId(BluetoothDeviceId deviceId)
|
||||
{
|
||||
return new GattSession(deviceId);
|
||||
}
|
||||
|
||||
internal GattSession(BluetoothDeviceId deviceId)
|
||||
{
|
||||
_deviceId = deviceId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the device ID.
|
||||
/// </summary>
|
||||
public BluetoothDeviceId DeviceId { get => _deviceId; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This enumeration defines a GattSession status.
|
||||
/// </summary>
|
||||
public enum GattSessionStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The GATT session is closed.
|
||||
/// </summary>
|
||||
Closed = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The GATT session is active.
|
||||
/// </summary>
|
||||
Active = 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents a subscribed client of a GATT session.
|
||||
/// </summary>
|
||||
public sealed class GattSubscribedClient
|
||||
{
|
||||
private readonly GattSession _session;
|
||||
|
||||
internal GattSubscribedClient(GattSession session)
|
||||
{
|
||||
_session = session;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum notification size.
|
||||
/// </summary>
|
||||
public ushort MaxNotificationSize { get => 1024; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the session of the subscribed client.
|
||||
/// </summary>
|
||||
public GattSession Session { get => _session; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates what type of write operation is to be performed.
|
||||
/// </summary>
|
||||
public enum GattWriteOption
|
||||
{
|
||||
/// <summary>
|
||||
/// The default GATT write procedure shall be used.
|
||||
/// </summary>
|
||||
WriteWithResponse = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The Write Without Response procedure shall be used.
|
||||
/// </summary>
|
||||
WriteWithoutResponse = 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents a GATT write request.
|
||||
/// </summary>
|
||||
public sealed class GattWriteRequest
|
||||
{
|
||||
private readonly GattWriteOption _option = GattWriteOption.WriteWithResponse;
|
||||
private readonly uint _offset = 0;
|
||||
private readonly Buffer _value = null;
|
||||
|
||||
private readonly ushort _eventID;
|
||||
|
||||
internal GattWriteRequest(ushort eventID)
|
||||
{
|
||||
_eventID = eventID;
|
||||
|
||||
// Get a copy of data from Native for this event
|
||||
byte[] data = NativeWriteGetData(eventID);
|
||||
|
||||
// and save it
|
||||
_value = new Buffer(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Responds to the write request.
|
||||
/// </summary>
|
||||
public void Respond()
|
||||
{
|
||||
NativeWriteRespond(_eventID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Responds with a protocol error.
|
||||
/// </summary>
|
||||
/// <param name="protocolError">Error byte</param>
|
||||
public void RespondWithProtocolError(byte protocolError)
|
||||
{
|
||||
NativeWriteRespondWithProtocolError(_eventID, protocolError);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the offset.
|
||||
/// </summary>
|
||||
public uint Offset { get => _offset; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the write request option.
|
||||
/// </summary>
|
||||
public GattWriteOption Option { get => _option; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the buffer value of the write request.
|
||||
/// </summary>
|
||||
public Buffer Value { get => _value; }
|
||||
|
||||
#region external calls to native implementations
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private extern byte[] NativeWriteGetData(ushort eventID);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private extern void NativeWriteRespond(ushort eventID);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private extern void NativeWriteRespondWithProtocolError(ushort eventID, byte protocolError);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.GenericAttributeProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents the event arguments for WriteRequested.
|
||||
/// </summary>
|
||||
public sealed class GattWriteRequestedEventArgs //: IGattWriteRequestedEventArgs
|
||||
{
|
||||
private readonly ushort _eventID;
|
||||
private readonly GattSession _session = null;
|
||||
|
||||
internal GattWriteRequestedEventArgs(ushort eventID, GattSession session)
|
||||
{
|
||||
_eventID = eventID;
|
||||
_session = session;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the write request.
|
||||
/// </summary>
|
||||
/// <returns>Returns a write request.</returns>
|
||||
public GattWriteRequest GetRequest()
|
||||
{
|
||||
return new GattWriteRequest(_eventID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the session.
|
||||
/// </summary>
|
||||
public GattSession Session { get => _session; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a referenced array of bytes used by byte stream read and write interfaces.
|
||||
/// </summary>
|
||||
public class Buffer
|
||||
{
|
||||
/// <summary>
|
||||
/// Byte buffer
|
||||
/// </summary>
|
||||
private byte[] _buffer;
|
||||
|
||||
/// <summary>
|
||||
/// Length of data in byte buffer.
|
||||
/// </summary>
|
||||
protected uint _length;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for Buffer with a specific capacity.
|
||||
/// </summary>
|
||||
/// <param name="capacity"></param>
|
||||
public Buffer(uint capacity)
|
||||
{
|
||||
_buffer = new byte[capacity];
|
||||
_length = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for Buffer with an external byte buffer.
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
public Buffer(byte[] array)
|
||||
{
|
||||
_buffer = array;
|
||||
_length = (uint)array.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum number of bytes that the buffer can hold.
|
||||
/// </summary>
|
||||
public uint Capacity { get => (uint)_buffer.Length; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bytes currently in use in the buffer.
|
||||
/// </summary>
|
||||
public uint Length
|
||||
{
|
||||
get => _length;
|
||||
set
|
||||
{
|
||||
if (value > _buffer.Length || value < 0)
|
||||
{
|
||||
throw new ArgumentException("Length greater than current buffer");
|
||||
}
|
||||
|
||||
_length = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure buffer has a certain capacity. If to small it will be expanded
|
||||
/// </summary>
|
||||
/// <param name="newCapacity">New capacity required</param>
|
||||
public void EnsureCapacity(uint newCapacity)
|
||||
{
|
||||
if (newCapacity > _buffer.Length)
|
||||
{
|
||||
Byte[] newBuffer = new Byte[newCapacity];
|
||||
Array.Copy(_buffer, 0, newBuffer, 0, _buffer.Length);
|
||||
_buffer = newBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
internal byte[] Data { get => _buffer; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,295 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads data from an input buffer.
|
||||
/// </summary>
|
||||
public sealed class DataReader
|
||||
{
|
||||
private Buffer _buffer;
|
||||
private int _currentReadPosition;
|
||||
|
||||
const int defaultBufferSize = 32;
|
||||
|
||||
private DataReader(Buffer buffer)
|
||||
{
|
||||
_buffer = buffer;
|
||||
_currentReadPosition = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the data reader with data from the specified buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <returns>The data reader.</returns>
|
||||
public static DataReader FromBuffer(Buffer buffer)
|
||||
{
|
||||
return new DataReader(buffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the buffer that has not been read.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the buffer that has not been read, in bytes.
|
||||
/// </value>
|
||||
public uint UnconsumedBufferLength { get => _buffer.Length - (uint)_currentReadPosition; }
|
||||
|
||||
/// <summary>
|
||||
/// Reads a Boolean value from the input buffer.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
public bool ReadBoolean()
|
||||
{
|
||||
var value = _buffer.Data[IncreaseReadPosition(1)] > 0;
|
||||
|
||||
CheckReadPosition();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a buffer from the input buffer.
|
||||
/// </summary>
|
||||
/// <param name="length">The length of the buffer, in bytes.</param>
|
||||
/// <returns>The buffer.</returns>
|
||||
public Buffer ReadBuffer(uint length)
|
||||
{
|
||||
Buffer buffer = new Buffer(length);
|
||||
|
||||
Array.Copy(_buffer.Data, IncreaseReadPosition((int)length), buffer.Data, 0, (int)length);
|
||||
|
||||
CheckReadPosition();
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a byte value from the input buffer.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
public byte ReadByte()
|
||||
{
|
||||
var value = _buffer.Data[IncreaseReadPosition(1)];
|
||||
|
||||
CheckReadPosition();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an array of byte values from the input buffer.
|
||||
/// </summary>
|
||||
/// <param name="value">The array of values.</param>
|
||||
public void ReadBytes(Byte[] value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("Argument is null");
|
||||
}
|
||||
|
||||
Array.Copy(_buffer.Data, IncreaseReadPosition(value.Length), value, 0, value.Length);
|
||||
|
||||
CheckReadPosition();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a date and time value from the input buffer.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
public DateTime ReadDateTime()
|
||||
{
|
||||
// read position update and check are performed on the call
|
||||
return new DateTime(ReadInt64());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a floating-point value from the input buffer.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
public double ReadDouble()
|
||||
{
|
||||
var value = BitConverter.ToDouble(_buffer.Data, IncreaseReadPosition(8));
|
||||
|
||||
CheckReadPosition();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a GUID value from the input buffer.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
public Guid ReadGuid()
|
||||
{
|
||||
byte[] byteArray = new byte[16];
|
||||
|
||||
// read position update and check are performed on the call
|
||||
ReadBytes(byteArray);
|
||||
|
||||
return new Guid(byteArray);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 16-bit integer value from the input buffer.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
public short ReadInt16()
|
||||
{
|
||||
var value = BitConverter.ToInt16(_buffer.Data, IncreaseReadPosition(2));
|
||||
|
||||
CheckReadPosition();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 32-bit integer value from the input buffer.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
public int ReadInt32()
|
||||
{
|
||||
var value = BitConverter.ToInt32(_buffer.Data, IncreaseReadPosition(4));
|
||||
|
||||
CheckReadPosition();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 64-bit integer value from the input buffer.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
public long ReadInt64()
|
||||
{
|
||||
var value = BitConverter.ToInt64(_buffer.Data, IncreaseReadPosition(8));
|
||||
|
||||
CheckReadPosition();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a floating-point value from the input buffer.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
public float ReadSingle()
|
||||
{
|
||||
var value = BitConverter.ToSingle(_buffer.Data, IncreaseReadPosition(4));
|
||||
|
||||
CheckReadPosition();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a string value from the input buffer.
|
||||
/// </summary>
|
||||
/// <param name="codeUnitCount">The length of the string.</param>
|
||||
/// <returns>The value.</returns>
|
||||
public string ReadString(uint codeUnitCount)
|
||||
{
|
||||
Char[] buffer = new Char[codeUnitCount];
|
||||
|
||||
int readPosition = IncreaseReadPosition((int)codeUnitCount);
|
||||
|
||||
Encoding.UTF8.GetDecoder().Convert(_buffer.Data, readPosition, (int)codeUnitCount, buffer, 0, (int)codeUnitCount, false, out Int32 bytesUsed, out Int32 charsUsed, out Boolean completed);
|
||||
var value = new String(buffer, 0, charsUsed);
|
||||
|
||||
CheckReadPosition();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a time interval from the input buffer.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
public TimeSpan ReadTimeSpan()
|
||||
{
|
||||
// read position update and check are performed on the call
|
||||
return new TimeSpan(ReadInt64());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 16-bit unsigned integer from the input buffer.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
public ushort ReadUInt16()
|
||||
{
|
||||
var value = BitConverter.ToUInt16(_buffer.Data, IncreaseReadPosition(2));
|
||||
|
||||
CheckReadPosition();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 32-bit unsigned integer from the input buffer.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
public uint ReadUInt32()
|
||||
{
|
||||
var value = BitConverter.ToUInt32(_buffer.Data, IncreaseReadPosition(4));
|
||||
|
||||
CheckReadPosition();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 64-bit unsigned integer from the input buffer.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
public ulong ReadUInt64()
|
||||
{
|
||||
var value = BitConverter.ToUInt64(_buffer.Data, IncreaseReadPosition(8));
|
||||
|
||||
CheckReadPosition();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increases the backing buffer read position.
|
||||
/// </summary>
|
||||
/// <param name="count">How many bytes to read from the backing buffer.</param>
|
||||
/// <returns>
|
||||
/// The current buffer position before increasing it by <para>count</para>.
|
||||
/// </returns>
|
||||
private int IncreaseReadPosition(int count)
|
||||
{
|
||||
if (UnconsumedBufferLength < count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("count", "No data in buffer");
|
||||
}
|
||||
|
||||
// save current read position
|
||||
int newPosition = _currentReadPosition;
|
||||
|
||||
// increase by count request
|
||||
_currentReadPosition += count;
|
||||
|
||||
return newPosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks current read position and resets the backing buffer if all bytes have been read
|
||||
/// </summary>
|
||||
private void CheckReadPosition()
|
||||
{
|
||||
if (_currentReadPosition == _buffer.Length)
|
||||
{
|
||||
_buffer = new Buffer(defaultBufferSize);
|
||||
_currentReadPosition = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes data to an output stream.
|
||||
/// </summary>
|
||||
public sealed class DataWriter : Buffer
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates and initializes a new instance of the data writer.
|
||||
/// </summary>
|
||||
public DataWriter() : base(32)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of a string.
|
||||
/// </summary>
|
||||
/// <param name="value">The string.</param>
|
||||
/// <returns>The size of the string, in bytes.</returns>
|
||||
public uint MeasureString(String value)
|
||||
{
|
||||
Encoding encoding = Encoding.UTF8;
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("value");
|
||||
}
|
||||
return (uint)encoding.GetBytes(value).Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a Boolean value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteBoolean(Boolean value)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a number of bytes from a buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The value to write.</param>
|
||||
public void WriteBuffer(Buffer buffer)
|
||||
{
|
||||
WriteBuffer(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a range of bytes from a buffer to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="start">The starting byte to be written.</param>
|
||||
/// <param name="count">The number of bytes to write.</param>
|
||||
public void WriteBuffer(Buffer buffer, uint start, uint count)
|
||||
{
|
||||
byte[] copyBuffer = new byte[count];
|
||||
Array.Copy(buffer.Data, (int)start, copyBuffer, 0, (int)count);
|
||||
|
||||
WriteBytes(copyBuffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a byte value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteByte(Byte value)
|
||||
{
|
||||
WriteBytes(new byte[] { value });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an array of byte values to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteBytes(Byte[] value)
|
||||
{
|
||||
EnsureCapacity((uint)(base.Length + value.Length));
|
||||
|
||||
Array.Copy(value, 0, base.Data, (int)base.Length, value.Length);
|
||||
base.Length += (uint)value.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a date and time value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteDateTime(DateTime value)
|
||||
{
|
||||
WriteInt64(value.Ticks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a floating-point value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteDouble(Double value)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a GUID value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteGuid(Guid value)
|
||||
{
|
||||
WriteBytes(value.ToByteArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 16-bit integer value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteInt16(Int16 value)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 32-bit integer value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteInt32(Int32 value)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 64-bit integer value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteInt64(Int64 value)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a floating-point value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteSingle(Single value)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a string value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
/// <returns>The length of the string.</returns>
|
||||
public uint WriteString(String value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("value");
|
||||
}
|
||||
byte[] strBytes = Encoding.UTF8.GetBytes(value);
|
||||
WriteBytes(strBytes);
|
||||
return (uint)strBytes.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a time interval value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteTimeSpan(TimeSpan value)
|
||||
{
|
||||
WriteInt64(value.Ticks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 16-bit unsigned integer value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteUInt16(UInt16 value)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 32-bit unsigned integer value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteUInt32(uint value)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 64-bit unsigned integer value to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
public void WriteUInt64(UInt64 value)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns byte buffer of data in buffer
|
||||
/// </summary>
|
||||
/// <returns>Buffer</returns>
|
||||
public Buffer DetachBuffer()
|
||||
{
|
||||
return (Buffer)this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("nanoFramework.Device.Bluetooth")]
|
||||
[assembly: AssemblyCompany("nanoFramework Contributors")]
|
||||
[assembly: AssemblyProduct("nanoFramework.Device.Bluetooth")]
|
||||
[assembly: AssemblyCopyright("Copyright (c) .NET Foundation and Contributors")]
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// update this whenever the native assembly signature changes //
|
||||
[assembly: AssemblyNativeVersion("100.0.0.1")]
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.Spp
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for Bluetooth Serial Profile (SPP)
|
||||
/// </summary>
|
||||
public interface IBluetoothSpp
|
||||
{
|
||||
/// <summary>
|
||||
/// Receive data delegate.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="ReadDataEventArgs"></param>
|
||||
public delegate void RxDataEventHandler(IBluetoothSpp sender, SppReceivedDataEventArgs ReadDataEventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// Connected client status changed delegate.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
public delegate void ConnectedEventHandler(IBluetoothSpp sender, EventArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Received data event. Event is fired when data is received.
|
||||
/// </summary>
|
||||
public event RxDataEventHandler ReceivedData;
|
||||
|
||||
/// <summary>
|
||||
/// Connected client status changed event, Fired when client connects or disconnects.
|
||||
/// Check isConnected property for current status.
|
||||
/// </summary>
|
||||
public event ConnectedEventHandler ConnectedEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true is a client is connected.
|
||||
/// </summary>
|
||||
bool IsConnected{ get; }
|
||||
|
||||
/// <summary>
|
||||
/// Start the SPP advertising.
|
||||
/// </summary>
|
||||
/// <param name="deviceName">Device name to use in advert.</param>
|
||||
/// <returns></returns>
|
||||
bool Start(string deviceName);
|
||||
|
||||
/// <summary>
|
||||
/// Stop advertising and close down.
|
||||
/// </summary>
|
||||
void Stop();
|
||||
|
||||
/// <summary>
|
||||
/// Send bytes to connected client.
|
||||
/// </summary>
|
||||
/// <param name="data">Byte[] to send.</param>
|
||||
/// <returns>True if send was successful.</returns>
|
||||
bool SendBytes(byte[] data);
|
||||
|
||||
/// <summary>
|
||||
/// Send string to connected client.
|
||||
/// </summary>
|
||||
/// <param name="data">String data to send.</param>
|
||||
/// <returns>True if send was successful.</returns>
|
||||
bool SendString(string data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,176 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using nanoFramework.Device.Bluetooth.GenericAttributeProfile;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.Spp
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of Nordic Serial SPP profile.
|
||||
/// </summary>
|
||||
public class NordicSpp : IBluetoothSpp
|
||||
{
|
||||
// UUID for Nordic UART service
|
||||
// https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/libraries/bluetooth_services/services/nus.html#id4
|
||||
private Guid ServiceUUID = new Guid("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
|
||||
private Guid RxCharacteristicUUID = new Guid("6E400002-B5A3-F393-E0A9-E50E24DCCA9E");
|
||||
private Guid TxCharacteristicUUID = new Guid("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");
|
||||
|
||||
private readonly GattServiceProvider _serviceProvider;
|
||||
private readonly GattLocalCharacteristic _txCharacteristic;
|
||||
private bool _isConnected = false;
|
||||
|
||||
/// <summary>
|
||||
/// Return true id client connected
|
||||
/// </summary>
|
||||
public bool IsConnected { get => _isConnected; }
|
||||
|
||||
/// <summary>
|
||||
/// Event handler for receiving data
|
||||
/// </summary>
|
||||
public event IBluetoothSpp.RxDataEventHandler ReceivedData;
|
||||
|
||||
/// <summary>
|
||||
/// Event Handler for connection state change
|
||||
/// </summary>
|
||||
public event IBluetoothSpp.ConnectedEventHandler ConnectedEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for Nordic serial SPP profile
|
||||
/// </summary>
|
||||
public NordicSpp()
|
||||
{
|
||||
GattServiceProviderResult gspr = GattServiceProvider.Create(ServiceUUID);
|
||||
if (gspr.Error != nanoFramework.Device.Bluetooth.BluetoothError.Success)
|
||||
{
|
||||
throw new ArgumentException("Unable to create service");
|
||||
}
|
||||
|
||||
_serviceProvider = gspr.ServiceProvider;
|
||||
|
||||
// Define RX characteristic
|
||||
GattLocalCharacteristicParameters rxParam = new GattLocalCharacteristicParameters()
|
||||
{
|
||||
UserDescription = "RX Characteristic",
|
||||
CharacteristicProperties = GattCharacteristicProperties.Write | GattCharacteristicProperties.WriteWithoutResponse
|
||||
};
|
||||
|
||||
GattLocalCharacteristicResult rxCharRes = _serviceProvider.Service.CreateCharacteristic(RxCharacteristicUUID, rxParam);
|
||||
if (rxCharRes.Error != nanoFramework.Device.Bluetooth.BluetoothError.Success)
|
||||
{
|
||||
throw new ArgumentException("Unable to create RX Characteristic");
|
||||
}
|
||||
|
||||
GattLocalCharacteristic rxCharacteristic = rxCharRes.Characteristic;
|
||||
rxCharacteristic.WriteRequested += RxCharacteristic_WriteRequested;
|
||||
|
||||
|
||||
// Define TX characteristic
|
||||
GattLocalCharacteristicParameters txParam = new GattLocalCharacteristicParameters()
|
||||
{
|
||||
UserDescription = "TX Characteristic",
|
||||
CharacteristicProperties = GattCharacteristicProperties.Notify
|
||||
};
|
||||
|
||||
GattLocalCharacteristicResult txCharRes = _serviceProvider.Service.CreateCharacteristic(TxCharacteristicUUID, txParam);
|
||||
if (txCharRes.Error != nanoFramework.Device.Bluetooth.BluetoothError.Success)
|
||||
{
|
||||
throw new ArgumentException("Unable to create TX Characteristic");
|
||||
}
|
||||
|
||||
_txCharacteristic = txCharRes.Characteristic;
|
||||
_txCharacteristic.SubscribedClientsChanged += _txCharacteristic_SubscribedClientsChanged;
|
||||
}
|
||||
|
||||
private void _txCharacteristic_SubscribedClientsChanged(GattLocalCharacteristic sender, object args)
|
||||
{
|
||||
_isConnected = (sender.SubscribedClients.Length > 0);
|
||||
|
||||
// Fire event when connection state changes
|
||||
ConnectedEvent?.Invoke(this, new EventArgs());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start device advertising
|
||||
/// </summary>
|
||||
/// <param name="deviceName">Device name for Advertising</param>
|
||||
/// <returns></returns>
|
||||
public bool Start(string deviceName)
|
||||
{
|
||||
GattServiceProviderAdvertisingParameters advParameters = new GattServiceProviderAdvertisingParameters
|
||||
{
|
||||
DeviceName = deviceName,
|
||||
IsDiscoverable = true,
|
||||
IsConnectable = true
|
||||
};
|
||||
|
||||
_serviceProvider.StartAdvertising(advParameters);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop Nordic SPP UART device
|
||||
/// Stop advertising.
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
_serviceProvider?.StopAdvertising();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send data bytes to connected client
|
||||
/// </summary>
|
||||
/// <param name="data">byte array to send</param>
|
||||
/// <returns></returns>
|
||||
public bool SendBytes(byte[] data)
|
||||
{
|
||||
DataWriter dr = new DataWriter();
|
||||
dr.WriteBytes(data);
|
||||
GattClientNotificationResult[] results = _txCharacteristic.NotifyValue(dr.DetachBuffer());
|
||||
if (results.Length > 0 && results[0].ProtocolError == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send data as string
|
||||
/// </summary>
|
||||
/// <param name="data">string to send</param>
|
||||
/// <returns></returns>
|
||||
public bool SendString(string data)
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(data);
|
||||
return SendBytes(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler for Received data
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="WriteRequestEventArgs"></param>
|
||||
private void RxCharacteristic_WriteRequested(GattLocalCharacteristic sender, GattWriteRequestedEventArgs WriteRequestEventArgs)
|
||||
{
|
||||
GattWriteRequest request = WriteRequestEventArgs.GetRequest();
|
||||
|
||||
byte[] data = new byte[request.Value.Length];
|
||||
|
||||
DataReader rdr = DataReader.FromBuffer(request.Value);
|
||||
rdr.ReadBytes(data);
|
||||
|
||||
ReceivedData?.Invoke(this, new SppReceivedDataEventArgs(data));
|
||||
|
||||
if (request.Option == GattWriteOption.WriteWithResponse)
|
||||
{
|
||||
request.Respond();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth.Spp
|
||||
{
|
||||
/// <summary>
|
||||
/// Event argument for SPP receive data events
|
||||
/// </summary>
|
||||
public sealed class SppReceivedDataEventArgs
|
||||
{
|
||||
private readonly byte[] _data;
|
||||
|
||||
internal SppReceivedDataEventArgs(byte[] data)
|
||||
{
|
||||
_data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Received data as byte[].
|
||||
/// </summary>
|
||||
public byte[] DataBytes { get => _data; }
|
||||
|
||||
/// <summary>
|
||||
/// Received data as string.
|
||||
/// </summary>
|
||||
public String DataString { get => Encoding.UTF8.GetString(_data, 0, _data.Length); }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Device.Bluetooth
|
||||
{
|
||||
/// <summary>
|
||||
/// Bluetooth library utilities
|
||||
/// </summary>
|
||||
public static class Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// This enum assists in finding a string representation of a BT SIG assigned value for Descriptor UUIDs
|
||||
/// Reference: https://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorsHomePage.aspx
|
||||
/// </summary>
|
||||
public enum GattNativeDescriptorUuid : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// CharacteristicExtendedProperties
|
||||
/// </summary>
|
||||
CharacteristicExtendedProperties = 0x2900,
|
||||
|
||||
/// <summary>
|
||||
/// CharacteristicUserDescription
|
||||
/// </summary>
|
||||
CharacteristicUserDescription = 0x2901,
|
||||
|
||||
/// <summary>
|
||||
/// ClientCharacteristicConfiguration
|
||||
/// </summary>
|
||||
ClientCharacteristicConfiguration = 0x2902,
|
||||
|
||||
/// <summary>
|
||||
/// ServerCharacteristicConfiguration
|
||||
/// </summary>
|
||||
ServerCharacteristicConfiguration = 0x2903,
|
||||
|
||||
/// <summary>
|
||||
/// CharacteristicPresentationFormat
|
||||
/// </summary>
|
||||
CharacteristicPresentationFormat = 0x2904,
|
||||
|
||||
/// <summary>
|
||||
/// CharacteristicAggregateFormat
|
||||
/// </summary>
|
||||
CharacteristicAggregateFormat = 0x2905,
|
||||
|
||||
/// <summary>
|
||||
/// ValidRange
|
||||
/// </summary>
|
||||
ValidRange = 0x2906,
|
||||
|
||||
/// <summary>
|
||||
/// ExternalReportReference
|
||||
/// </summary>
|
||||
ExternalReportReference = 0x2907,
|
||||
|
||||
/// <summary>
|
||||
/// ReportReference
|
||||
/// </summary>
|
||||
ReportReference = 0x2908
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts from standard 128bit UUID to the assigned 16bit UUID. Makes it easy to compare services
|
||||
/// that devices expose to the standard list.
|
||||
/// </summary>
|
||||
/// <param name="uuid">UUID to convert to 16 bit short code Uuid</param>
|
||||
/// <returns></returns>
|
||||
public static ushort ConvertUuidToShortId(Guid uuid)
|
||||
{
|
||||
// Get the short Uuid
|
||||
var bytes = uuid.ToByteArray();
|
||||
var shortUuid = (ushort)(bytes[0] | (bytes[1] << 8));
|
||||
return shortUuid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a Uuid/Guid from a short Bluetooth SIG short UUID
|
||||
/// </summary>
|
||||
/// <param name="uuid16">Bluetooth Short code UUID</param>
|
||||
/// <returns>A Guid using Bluetooth SIG UUID</returns>
|
||||
public static Guid CreateUuidFromShortCode(ushort uuid16)
|
||||
{
|
||||
// UUID is the name used by Bluetooth SIG for a Guid
|
||||
// This is the base UUID for all standard Bluetooth SIG UUIDs
|
||||
const string baseUuid = "00000000-0000-1000-8000-00805f9b34fb";
|
||||
|
||||
Guid temp = new Guid(baseUuid);
|
||||
|
||||
byte[] bytes = temp.ToByteArray();
|
||||
|
||||
bytes[0] = (byte)(0x00ff & uuid16);
|
||||
bytes[1] = (byte)(uuid16 >> 8);
|
||||
|
||||
return new Guid(bytes);
|
||||
}
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
|
@ -0,0 +1,115 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<ProjectGuid>3e3dfd1b-89f3-455d-83d4-c34c7fc5422e</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<RootNamespace>nanoFramework.Device.Bluetooth</RootNamespace>
|
||||
<AssemblyName>nanoFramework.Device.Bluetooth</AssemblyName>
|
||||
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
|
||||
<NF_IsCoreLibrary>True</NF_IsCoreLibrary>
|
||||
<DocumentationFile>bin\$(Configuration)\nanoFramework.Device.Bluetooth.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<DelaySign>false</DelaySign>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<!-- override default options for MetaDataProcessor -->
|
||||
<NF_GenerateStubsDirectory>bin\$(Configuration)\Stubs</NF_GenerateStubsDirectory>
|
||||
<NF_GenerateSkeletonProjectName>sys_dev_ble_native</NF_GenerateSkeletonProjectName>
|
||||
<Name>System.Device.Bluetooth</Name>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
|
||||
<ItemGroup>
|
||||
<Compile Include="BluetoothDeviceId.cs" />
|
||||
<Compile Include="BluetoothError.cs" />
|
||||
<Compile Include="BluetoothEvent.cs" />
|
||||
<Compile Include="BluetoothEventListener.cs" />
|
||||
<Compile Include="BluetoothEventType.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattCharacteristicProperties.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattCharacteristicUuids.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattClientNotificationResult.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattCommunicationStatus.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattDescriptorUuid.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattLocalCharacteristic.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattLocalCharacteristicParameters.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattLocalCharacteristicResult.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattLocalDescriptor.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattLocalDescriptorParameters.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattLocalDescriptorResult.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattLocalService.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattPresentationFormat.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattPresentationFormatTypes.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattProtectionLevel.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattProtocolError.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattReadRequest.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattReadRequestedEventArgs.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattServiceProvider.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattServiceProviderAdvertisementStatus.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattServiceProviderAdvertisingParameters.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattServiceProviderResult.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattServiceUuids.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattSession.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattSessionStatus.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattSubscribedClient.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattWriteOption.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattWriteRequest.cs" />
|
||||
<Compile Include="GenericAttributeProfile\GattWriteRequestedEventArgs.cs" />
|
||||
<Compile Include="SPP\IBluetoothSpp.cs" />
|
||||
<Compile Include="SPP\NordicSpp.cs" />
|
||||
<Compile Include="SPP\SppReceiveEventArgs.cs" />
|
||||
<Compile Include="IO\Buffer.cs" />
|
||||
<Compile Include="IO\DataReader.cs" />
|
||||
<Compile Include="IO\DataWriter.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Utilities.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="key.snk" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib, Version=1.10.5.4, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.CoreLibrary.1.10.5\lib\mscorlib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<SpecificVersion>True</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.Runtime.Events, Version=1.9.2.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.Runtime.Events.1.9.2-preview.8\lib\nanoFramework.Runtime.Events.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<SpecificVersion>True</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.System.Text, Version=1.1.1.3, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.System.Text.1.1.1\lib\nanoFramework.System.Text.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<SpecificVersion>True</SpecificVersion>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
|
||||
<ProjectExtensions>
|
||||
<ProjectCapabilities>
|
||||
<ProjectConfigurationsDeclaredAsItems />
|
||||
</ProjectCapabilities>
|
||||
</ProjectExtensions>
|
||||
<Import Project="..\packages\Nerdbank.GitVersioning.3.4.231\build\Nerdbank.GitVersioning.targets" Condition="Exists('..\packages\Nerdbank.GitVersioning.3.4.231\build\Nerdbank.GitVersioning.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Nerdbank.GitVersioning.3.4.231\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Nerdbank.GitVersioning.3.4.231\build\Nerdbank.GitVersioning.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="nanoFramework.CoreLibrary" version="1.10.5" targetFramework="netnanoframework10" />
|
||||
<package id="nanoFramework.Runtime.Events" version="1.9.2-preview.8" targetFramework="netnanoframework10" />
|
||||
<package id="nanoFramework.System.Text" version="1.1.1" targetFramework="netnanoframework10" />
|
||||
<package id="Nerdbank.GitVersioning" version="3.4.231" developmentDependency="true" targetFramework="netnanoframework10" />
|
||||
</packages>
|
|
@ -0,0 +1,74 @@
|
|||
<UserSettings>
|
||||
<ApplicationIdentity version="12.0"/>
|
||||
<ToolsOptions>
|
||||
<ToolsOptionsCategory name="TextEditor" RegisteredName="TextEditor">
|
||||
<ToolsOptionsSubCategory name="AllLanguages" RegisteredName="AllLanguages" PackageName="Text Management Package"/>
|
||||
<ToolsOptionsSubCategory name="CSharp" RegisteredName="CSharp" PackageName="Text Management Package">
|
||||
<PropertyValue name="TabSize">4</PropertyValue>
|
||||
<PropertyValue name="InsertTabs">false</PropertyValue>
|
||||
<PropertyValue name="IndentSize">4</PropertyValue>
|
||||
<PropertyValue name="BraceCompletion">true</PropertyValue>
|
||||
</ToolsOptionsSubCategory>
|
||||
<ToolsOptionsSubCategory name="CSharp-Specific" RegisteredName="CSharp-Specific" PackageName="Visual C# Language Service Package">
|
||||
<PropertyValue name="NewLines_QueryExpression_EachClause">1</PropertyValue>
|
||||
<PropertyValue name="Space_Normalize">0</PropertyValue>
|
||||
<PropertyValue name="Space_AroundBinaryOperator">1</PropertyValue>
|
||||
<PropertyValue name="Formatting_TriggerOnPaste">1</PropertyValue>
|
||||
<PropertyValue name="NewLines_Braces_Method">1</PropertyValue>
|
||||
<PropertyValue name="Indent_CaseLabels">1</PropertyValue>
|
||||
<PropertyValue name="Formatting_TriggerOnBlockCompletion">1</PropertyValue>
|
||||
<PropertyValue name="CodeDefinitionWindow_DocumentationComment_IndentOffset">2</PropertyValue>
|
||||
<PropertyValue name="NewLines_Braces_ControlFlow">1</PropertyValue>
|
||||
<PropertyValue name="NewLines_Braces_AnonymousMethod">0</PropertyValue>
|
||||
<PropertyValue name="Space_WithinOtherParentheses">0</PropertyValue>
|
||||
<PropertyValue name="Wrapping_KeepStatementsOnSingleLine">1</PropertyValue>
|
||||
<PropertyValue name="Space_AfterBasesColon">1</PropertyValue>
|
||||
<PropertyValue name="Indent_Braces">0</PropertyValue>
|
||||
<PropertyValue name="Wrapping_IgnoreSpacesAroundVariableDeclaration">0</PropertyValue>
|
||||
<PropertyValue name="Space_WithinMethodCallParentheses">0</PropertyValue>
|
||||
<PropertyValue name="Space_AfterCast">0</PropertyValue>
|
||||
<PropertyValue name="NewLines_Braces_CollectionInitializer">0</PropertyValue>
|
||||
<PropertyValue name="NewLines_AnonymousTypeInitializer_EachMember">1</PropertyValue>
|
||||
<PropertyValue name="NewLines_Keywords_Catch">1</PropertyValue>
|
||||
<PropertyValue name="NewLines_Braces_ObjectInitializer">0</PropertyValue>
|
||||
<PropertyValue name="NewLines_Braces_ArrayInitializer">0</PropertyValue>
|
||||
<PropertyValue name="Space_WithinExpressionParentheses">0</PropertyValue>
|
||||
<PropertyValue name="Space_InControlFlowConstruct">1</PropertyValue>
|
||||
<PropertyValue name="Formatting_TriggerOnStatementCompletion">0</PropertyValue>
|
||||
<PropertyValue name="NewLines_Keywords_Finally">1</PropertyValue>
|
||||
<PropertyValue name="Space_BetweenEmptyMethodDeclarationParentheses">0</PropertyValue>
|
||||
<PropertyValue name="Indent_UnindentLabels">0</PropertyValue>
|
||||
<PropertyValue name="NewLines_ObjectInitializer_EachMember">1</PropertyValue>
|
||||
<PropertyValue name="NewLines_Keywords_Else">1</PropertyValue>
|
||||
<PropertyValue name="Space_WithinMethodDeclarationParentheses">0</PropertyValue>
|
||||
<PropertyValue name="Space_BetweenEmptyMethodCallParentheses">0</PropertyValue>
|
||||
<PropertyValue name="Space_BeforeSemicolonsInForStatement">0</PropertyValue>
|
||||
<PropertyValue name="Space_BeforeComma">0</PropertyValue>
|
||||
<PropertyValue name="Space_AfterMethodCallName">0</PropertyValue>
|
||||
<PropertyValue name="Space_AfterComma">1</PropertyValue>
|
||||
<PropertyValue name="Wrapping_IgnoreSpacesAroundBinaryOperators">0</PropertyValue>
|
||||
<PropertyValue name="Space_BeforeBasesColon">1</PropertyValue>
|
||||
<PropertyValue name="Space_AfterMethodDeclarationName">0</PropertyValue>
|
||||
<PropertyValue name="Space_AfterDot">0</PropertyValue>
|
||||
<PropertyValue name="NewLines_Braces_Type">1</PropertyValue>
|
||||
<PropertyValue name="Space_AfterLambdaArrow">1</PropertyValue>
|
||||
<PropertyValue name="NewLines_Braces_LambdaExpressionBody">0</PropertyValue>
|
||||
<PropertyValue name="Space_WithinSquares">0</PropertyValue>
|
||||
<PropertyValue name="Space_BeforeLambdaArrow">1</PropertyValue>
|
||||
<PropertyValue name="NewLines_Braces_AnonymousTypeInitializer">0</PropertyValue>
|
||||
<PropertyValue name="Space_WithinCastParentheses">0</PropertyValue>
|
||||
<PropertyValue name="Space_AfterSemicolonsInForStatement">1</PropertyValue>
|
||||
<PropertyValue name="Indent_CaseContents">0</PropertyValue>
|
||||
<PropertyValue name="Indent_FlushLabelsLeft">1</PropertyValue>
|
||||
<PropertyValue name="Wrapping_PreserveSingleLine">1</PropertyValue>
|
||||
<PropertyValue name="Space_BetweenEmptySquares">0</PropertyValue>
|
||||
<PropertyValue name="Space_BeforeOpenSquare">0</PropertyValue>
|
||||
<PropertyValue name="Space_BeforeDot">0</PropertyValue>
|
||||
<PropertyValue name="Indent_BlockContents">1</PropertyValue>
|
||||
<PropertyValue name="SortUsings_PlaceSystemFirst">1</PropertyValue>
|
||||
<PropertyValue name="SortUsings">1</PropertyValue>
|
||||
<PropertyValue name="RemoveUnusedUsings">1</PropertyValue>
|
||||
</ToolsOptionsSubCategory>
|
||||
</ToolsOptionsCategory>
|
||||
</ToolsOptions>
|
||||
</UserSettings>
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
|
||||
"version": "1.0.0-preview.{height}",
|
||||
"assemblyVersion": {
|
||||
"precision": "revision"
|
||||
},
|
||||
"semVer1NumericIdentifierPadding": 3,
|
||||
"nuGetPackageVersion": {
|
||||
"semVer": 2.0
|
||||
},
|
||||
"publicReleaseRefSpec": [
|
||||
"^refs/heads/main$",
|
||||
"^refs/heads/v\\d+(?:\\.\\d+)?$"
|
||||
],
|
||||
"cloudBuild": {
|
||||
"setAllVariables": true,
|
||||
"buildNumber": null
|
||||
},
|
||||
"release": {
|
||||
"branchName": "release-v{version}",
|
||||
"versionIncrement": "build",
|
||||
"firstUnstableTag": "preview"
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче