├── .gitattributes
├── .gitignore
├── BluetoothBeyondBeacons
├── README.md
└── cs
│ ├── BeyondBeacons.csproj
│ ├── BeyondBeacons.sln
│ ├── Package.appxmanifest
│ ├── SampleConfiguration.cs
│ ├── Scenario1_BeaconProximity.xaml
│ ├── Scenario1_BeaconProximity.xaml.cs
│ ├── Tasks
│ ├── AdvertisementWatcherTask.cs
│ ├── BackgroundTasks.csproj
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── project.json
│ └── project.json
├── BluetoothInAppGATT
├── README.md
└── cs
│ ├── BluetoothInAppGATT.csproj
│ ├── BluetoothInAppGATT.sln
│ ├── Package.appxmanifest
│ ├── SampleConfiguration.cs
│ ├── Scenario1_InAppGATT.xaml
│ ├── Scenario1_InAppGATT.xaml.cs
│ └── project.json
├── BuildQuickStart
├── BtAvatar
│ └── BtAvatar
│ │ ├── BtAvatar.sln
│ │ └── BtAvatar
│ │ ├── App.xaml
│ │ ├── App.xaml.cs
│ │ ├── Assets
│ │ ├── LockScreenLogo.scale-200.png
│ │ ├── SplashScreen.scale-200.png
│ │ ├── Square150x150Logo.scale-200.png
│ │ ├── Square44x44Logo.scale-200.png
│ │ ├── Square44x44Logo.targetsize-24_altform-unplated.png
│ │ ├── StoreLogo.png
│ │ └── Wide310x150Logo.scale-200.png
│ │ ├── BtAvatar.csproj
│ │ ├── MainPage.xaml
│ │ ├── MainPage.xaml.cs
│ │ ├── Package.appxmanifest
│ │ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ └── Default.rd.xml
│ │ └── project.json
├── BtSensor
│ ├── AvatarSensor.sln
│ └── AvatarSensor
│ │ ├── App.xaml
│ │ ├── App.xaml.cs
│ │ ├── Assets
│ │ ├── LockScreenLogo.scale-200.png
│ │ ├── SplashScreen.scale-200.png
│ │ ├── Square150x150Logo.scale-200.png
│ │ ├── Square44x44Logo.scale-200.png
│ │ ├── Square44x44Logo.targetsize-24_altform-unplated.png
│ │ ├── StoreLogo.png
│ │ └── Wide310x150Logo.scale-200.png
│ │ ├── AvatarSensor.csproj
│ │ ├── MainPage.xaml
│ │ ├── MainPage.xaml.cs
│ │ ├── Package.appxmanifest
│ │ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ └── Default.rd.xml
│ │ └── project.json
└── README.md
├── README.md
└── SharedContent
├── cs
├── App.xaml.cs
├── AssemblyInfo.cs
├── Default.rd.xml
├── Library.rd.xml
├── MainPage.xaml
└── MainPage.xaml.cs
├── media
├── microsoft-sdk.png
├── placeholder-sdk.png
├── smalltile-sdk.png
├── splash-sdk.png
├── squaretile-sdk.png
├── storelogo-sdk.png
├── storelogo-sdk.scale-100.png
├── tile-sdk.png
└── windows-sdk.png
└── xaml
├── App.xaml
└── Styles.xaml
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | [Gg]enerated Files/
19 | x64/
20 | x86/
21 | build/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 |
26 | # Visual Studo 2015 cache/options directory
27 | .vs/
28 |
29 | # MSTest test Results
30 | [Tt]est[Rr]esult*/
31 | [Bb]uild[Ll]og.*
32 |
33 | # NUNIT
34 | *.VisualState.xml
35 | TestResult.xml
36 |
37 | # Build Results of an ATL Project
38 | [Dd]ebugPS/
39 | [Rr]eleasePS/
40 | dlldata.c
41 |
42 | *_i.c
43 | *_p.c
44 | *_i.h
45 | *.ilk
46 | *.meta
47 | *.obj
48 | *.pch
49 | *.pdb
50 | *.pgc
51 | *.pgd
52 | *.rsp
53 | *.sbr
54 | *.tlb
55 | *.tli
56 | *.tlh
57 | *.tmp
58 | *.tmp_proj
59 | *.log
60 | *.vspscc
61 | *.vssscc
62 | .builds
63 | *.pidb
64 | *.svclog
65 | *.scc
66 |
67 | # Chutzpah Test files
68 | _Chutzpah*
69 |
70 | # Visual C++ cache files
71 | ipch/
72 | *.aps
73 | *.ncb
74 | *.opensdf
75 | *.sdf
76 | *.cachefile
77 |
78 | # Visual Studio profiler
79 | *.psess
80 | *.vsp
81 | *.vspx
82 |
83 | # TFS 2012 Local Workspace
84 | $tf/
85 |
86 | # Guidance Automation Toolkit
87 | *.gpState
88 |
89 | # ReSharper is a .NET coding add-in
90 | _ReSharper*/
91 | *.[Rr]e[Ss]harper
92 | *.DotSettings.user
93 |
94 | # JustCode is a .NET coding addin-in
95 | .JustCode
96 |
97 | # TeamCity is a build add-in
98 | _TeamCity*
99 |
100 | # DotCover is a Code Coverage Tool
101 | *.dotCover
102 |
103 | # NCrunch
104 | _NCrunch_*
105 | .*crunch*.local.xml
106 |
107 | # MightyMoose
108 | *.mm.*
109 | AutoTest.Net/
110 |
111 | # Web workbench (sass)
112 | .sass-cache/
113 |
114 | # Installshield output folder
115 | [Ee]xpress/
116 |
117 | # DocProject is a documentation generator add-in
118 | DocProject/buildhelp/
119 | DocProject/Help/*.HxT
120 | DocProject/Help/*.HxC
121 | DocProject/Help/*.hhc
122 | DocProject/Help/*.hhk
123 | DocProject/Help/*.hhp
124 | DocProject/Help/Html2
125 | DocProject/Help/html
126 |
127 | # Click-Once directory
128 | publish/
129 |
130 | # Publish Web Output
131 | *.[Pp]ublish.xml
132 | *.azurePubxml
133 | # TODO: Comment the next line if you want to checkin your web deploy settings
134 | # but database connection strings (with potential passwords) will be unencrypted
135 | *.pubxml
136 | *.publishproj
137 |
138 | # NuGet Packages
139 | *.nupkg
140 | # The packages folder can be ignored because of Package Restore
141 | **/packages/*
142 | # except build/, which is used as an MSBuild target.
143 | !**/packages/build/
144 | # Uncomment if necessary however generally it will be regenerated when needed
145 | #!**/packages/repositories.config
146 |
147 | # Windows Azure Build Output
148 | csx/
149 | *.build.csdef
150 |
151 | # Windows Store app package directory
152 | AppPackages/
153 |
154 | # Others
155 | *.[Cc]ache
156 | ClientBin/
157 | [Ss]tyle[Cc]op.*
158 | ~$*
159 | *~
160 | *.dbmdl
161 | *.dbproj.schemaview
162 | *.pfx
163 | *.publishsettings
164 | node_modules/
165 | bower_components/
166 |
167 | # RIA/Silverlight projects
168 | Generated_Code/
169 |
170 | # Backup & report files from converting an old project file
171 | # to a newer Visual Studio version. Backup files are not needed,
172 | # because we have git ;-)
173 | _UpgradeReport_Files/
174 | Backup*/
175 | UpgradeLog*.XML
176 | UpgradeLog*.htm
177 |
178 | # SQL Server files
179 | *.mdf
180 | *.ldf
181 |
182 | # Business Intelligence projects
183 | *.rdl.data
184 | *.bim.layout
185 | *.bim_*.settings
186 |
187 | # Microsoft Fakes
188 | FakesAssemblies/
189 |
190 | # Node.js Tools for Visual Studio
191 | .ntvs_analysis.dat
192 |
193 | # Visual Studio 6 build log
194 | *.plg
195 |
196 | # Visual Studio 6 workspace options file
197 | *.opt
198 |
199 | # Custom ignores
200 | gallery.xml
201 | project.lock.json
202 |
203 |
--------------------------------------------------------------------------------
/BluetoothBeyondBeacons/README.md:
--------------------------------------------------------------------------------
1 | # Bluetooth Beyond Beacons
2 | Code sample for Bluetooth Beyond Beacon: https://channel9.msdn.com/events/Build/2016/P416
3 |
4 | ## Run the sample
5 |
6 | The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
7 |
8 | ### Deploying the sample
9 |
10 | - Select Build > Deploy Solution.
11 |
12 | ### Deploying and running the sample
13 |
14 | - To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging.
15 |
--------------------------------------------------------------------------------
/BluetoothBeyondBeacons/cs/BeyondBeacons.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}
8 | AppContainerExe
9 | Properties
10 | SDKTemplate
11 | BluetoothRfcommChat
12 | en-US
13 | UAP
14 | 10.0.14267.0
15 | 10.0.10240.0
16 | 14
17 | true
18 | 512
19 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
20 | true
21 | True
22 | arm
23 |
24 |
25 | true
26 | bin\ARM\Debug\
27 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
28 | ;2008
29 | full
30 | ARM
31 | false
32 | prompt
33 | true
34 |
35 |
36 | bin\ARM\Release\
37 | TRACE;NETFX_CORE;WINDOWS_UAP
38 | true
39 | ;2008
40 | pdbonly
41 | ARM
42 | false
43 | prompt
44 | true
45 | true
46 |
47 |
48 | true
49 | bin\x64\Debug\
50 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
51 | ;2008
52 | full
53 | x64
54 | false
55 | prompt
56 | true
57 |
58 |
59 | bin\x64\Release\
60 | TRACE;NETFX_CORE;WINDOWS_UAP
61 | true
62 | ;2008
63 | pdbonly
64 | x64
65 | false
66 | prompt
67 | true
68 | true
69 |
70 |
71 | true
72 | bin\x86\Debug\
73 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
74 | ;2008
75 | full
76 | x86
77 | false
78 | prompt
79 | true
80 |
81 |
82 | bin\x86\Release\
83 | TRACE;NETFX_CORE;WINDOWS_UAP
84 | true
85 | ;2008
86 | pdbonly
87 | x86
88 | false
89 | prompt
90 | true
91 | true
92 |
93 |
94 |
95 | App.xaml.cs
96 | App.xaml
97 |
98 |
99 | MainPage.xaml.cs
100 | MainPage.xaml
101 |
102 |
103 | Properties\AssemblyInfo.cs
104 |
105 |
106 |
107 | Scenario1_BeaconProximity.xaml
108 |
109 |
110 |
111 |
112 | Designer
113 |
114 |
115 |
116 |
117 | App.xaml
118 | MSBuild:Compile
119 | Designer
120 |
121 |
122 | MainPage.xaml
123 | MSBuild:Compile
124 | Designer
125 |
126 |
127 | MSBuild:Compile
128 | Designer
129 |
130 |
131 | Styles\Styles.xaml
132 | MSBuild:Compile
133 | Designer
134 |
135 |
136 |
137 |
138 | {13331b5b-97d7-4290-a230-67baeae415c5}
139 | BackgroundTasks
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 | Assets\microsoft-sdk.png
148 |
149 |
150 | Assets\placeholder-sdk.png
151 |
152 |
153 | Assets\smalltile-sdk.png
154 |
155 |
156 | Assets\splash-sdk.png
157 |
158 |
159 | Assets\squaretile-sdk.png
160 |
161 |
162 | Assets\storelogo-sdk.png
163 |
164 |
165 | Assets\tile-sdk.png
166 |
167 |
168 | Assets\windows-sdk.png
169 |
170 |
171 |
172 | 14.0
173 |
174 |
175 |
182 |
--------------------------------------------------------------------------------
/BluetoothBeyondBeacons/cs/BeyondBeacons.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.23107.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeyondBeacons", "BeyondBeacons.csproj", "{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackgroundTasks", "Tasks\BackgroundTasks.csproj", "{13331B5B-97D7-4290-A230-67BAEAE415C5}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|ARM = Debug|ARM
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|ARM = Release|ARM
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.ActiveCfg = Debug|ARM
21 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Build.0 = Debug|ARM
22 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Deploy.0 = Debug|ARM
23 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.ActiveCfg = Debug|x64
24 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Build.0 = Debug|x64
25 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Deploy.0 = Debug|x64
26 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.ActiveCfg = Debug|x86
27 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Build.0 = Debug|x86
28 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Deploy.0 = Debug|x86
29 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.ActiveCfg = Release|ARM
30 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Build.0 = Release|ARM
31 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Deploy.0 = Release|ARM
32 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.ActiveCfg = Release|x64
33 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Build.0 = Release|x64
34 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Deploy.0 = Release|x64
35 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.ActiveCfg = Release|x86
36 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Build.0 = Release|x86
37 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Deploy.0 = Release|x86
38 | {13331B5B-97D7-4290-A230-67BAEAE415C5}.Debug|ARM.ActiveCfg = Debug|ARM
39 | {13331B5B-97D7-4290-A230-67BAEAE415C5}.Debug|ARM.Build.0 = Debug|ARM
40 | {13331B5B-97D7-4290-A230-67BAEAE415C5}.Debug|x64.ActiveCfg = Debug|x64
41 | {13331B5B-97D7-4290-A230-67BAEAE415C5}.Debug|x64.Build.0 = Debug|x64
42 | {13331B5B-97D7-4290-A230-67BAEAE415C5}.Debug|x86.ActiveCfg = Debug|x86
43 | {13331B5B-97D7-4290-A230-67BAEAE415C5}.Debug|x86.Build.0 = Debug|x86
44 | {13331B5B-97D7-4290-A230-67BAEAE415C5}.Release|ARM.ActiveCfg = Release|ARM
45 | {13331B5B-97D7-4290-A230-67BAEAE415C5}.Release|ARM.Build.0 = Release|ARM
46 | {13331B5B-97D7-4290-A230-67BAEAE415C5}.Release|x64.ActiveCfg = Release|x64
47 | {13331B5B-97D7-4290-A230-67BAEAE415C5}.Release|x64.Build.0 = Release|x64
48 | {13331B5B-97D7-4290-A230-67BAEAE415C5}.Release|x86.ActiveCfg = Release|x86
49 | {13331B5B-97D7-4290-A230-67BAEAE415C5}.Release|x86.Build.0 = Release|x86
50 | EndGlobalSection
51 | GlobalSection(SolutionProperties) = preSolution
52 | HideSolutionNode = FALSE
53 | EndGlobalSection
54 | EndGlobal
55 |
--------------------------------------------------------------------------------
/BluetoothBeyondBeacons/cs/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | BeyondBeacons
7 | Microsoft Corporation
8 | Assets\StoreLogo-sdk.png
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/BluetoothBeyondBeacons/cs/SampleConfiguration.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************
2 | //
3 | // Copyright (c) Microsoft. All rights reserved.
4 | // This code is licensed under the MIT License (MIT).
5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
9 | //
10 | //*********************************************************
11 |
12 | using System;
13 | using System.Collections.Generic;
14 | using Windows.UI.Xaml.Controls;
15 |
16 | namespace SDKTemplate
17 | {
18 | public partial class MainPage : Page
19 | {
20 | public const string FEATURE_NAME = "Bluetooth Beyond Beacons";
21 |
22 | List scenarios = new List
23 | {
24 | new Scenario()
25 | {
26 | Title = "Beacon Proximity",
27 | ClassType = typeof(Scenario1_BeaconProximity)
28 | },
29 | };
30 | }
31 |
32 | public class Scenario
33 | {
34 | public string Title { get; set; }
35 | public Type ClassType { get; set; }
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/BluetoothBeyondBeacons/cs/Scenario1_BeaconProximity.xaml:
--------------------------------------------------------------------------------
1 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
39 |
40 |
41 |
47 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/BluetoothBeyondBeacons/cs/Scenario1_BeaconProximity.xaml.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************
2 | //
3 | // Copyright (c) Microsoft. All rights reserved.
4 | // This code is licensed under the MIT License (MIT).
5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
9 | //
10 | //*********************************************************
11 |
12 | using System;
13 | using Windows.Storage;
14 | using Windows.UI.Xaml;
15 | using Windows.UI.Xaml.Controls;
16 | using Windows.UI.Xaml.Navigation;
17 | using Windows.ApplicationModel.Background;
18 | using Windows.Devices.Bluetooth;
19 | using Windows.Devices.Enumeration;
20 |
21 | namespace SDKTemplate
22 | {
23 | public sealed partial class Scenario1_BeaconProximity : Page
24 | {
25 | // A pointer back to the main page is required to display status messages.
26 | private MainPage rootPage = MainPage.Current;
27 |
28 | // The background task registration for the background advertisement watcher
29 | private IBackgroundTaskRegistration taskRegistration;
30 | // The watcher trigger used to configure the background task registration
31 | private BluetoothLEAdvertisementWatcherTrigger trigger;
32 | // A name is given to the task in order for it to be identifiable across context.
33 | private string taskName = "Beacon_BackgroundTask";
34 | // Entry point for the background task.
35 | private string taskEntryPoint = "BackgroundTasks.AdvertisementWatcherTask";
36 | // Local Name of the peripheral device, used to get permission to the device
37 | private string peripheralDeviceName = "LPF2 Smart Hub 2 I/O";
38 | // A service GUID on the peripheral device, used in the background watcher to find it
39 | private Guid peripheralDeviceServiceGUID = new Guid("00001523-1212-efde-1523-785feabcd123");
40 |
41 | public Scenario1_BeaconProximity()
42 | {
43 | this.InitializeComponent();
44 | this.initBluetoothAdvertisementWatcherTrigger();
45 | }
46 |
47 | private void initBluetoothAdvertisementWatcherTrigger()
48 | {
49 | this.trigger = new BluetoothLEAdvertisementWatcherTrigger();
50 |
51 | // Background advertisements require 1 advertisement filter. Here we filter by Guid in the Advertisement
52 | trigger.AdvertisementFilter.Advertisement.ServiceUuids.Add(peripheralDeviceServiceGUID);
53 |
54 | // Only activate the watcher when we're recieving values >= -80
55 | trigger.SignalStrengthFilter.InRangeThresholdInDBm = -80;
56 |
57 | // Stop watching if the value drops below -90 (user walked away)
58 | trigger.SignalStrengthFilter.OutOfRangeThresholdInDBm = -90;
59 |
60 | // Wait 5 seconds to make sure the device is really out of range
61 | trigger.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(5000);
62 | trigger.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(2000);
63 | }
64 |
65 | ///
66 | /// Handle background task completion.
67 | ///
68 | /// The task that is reporting completion.
69 | /// Arguments of the completion report.
70 | private async void OnBackgroundTaskCompleted(BackgroundTaskRegistration task, BackgroundTaskCompletedEventArgs eventArgs)
71 | {
72 | // We get the advertisement(s) processed by the background task
73 | if (ApplicationData.Current.LocalSettings.Values.Keys.Contains(taskName))
74 | {
75 | string backgroundMessage = (string)ApplicationData.Current.LocalSettings.Values[taskName];
76 | // Serialize UI update to the main UI thread
77 | await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
78 | {
79 | // Write the message to console
80 | System.Diagnostics.Debug.WriteLine(backgroundMessage);
81 | });
82 | }
83 | }
84 |
85 | protected override void OnNavigatedTo(NavigationEventArgs e)
86 | {
87 | rootPage = MainPage.Current;
88 |
89 | // Get the existing task if already registered
90 | if (taskRegistration == null)
91 | {
92 | // Find the task if we previously registered it
93 | foreach (var task in BackgroundTaskRegistration.AllTasks.Values)
94 | {
95 | if (task.Name == taskName)
96 | {
97 | taskRegistration = task;
98 | taskRegistration.Completed += OnBackgroundTaskCompleted;
99 | break;
100 | }
101 | }
102 | }
103 | else
104 | {
105 | taskRegistration.Completed += OnBackgroundTaskCompleted;
106 | }
107 |
108 | // Attach handlers for suspension to stop the watcher when the App is suspended.
109 | App.Current.Suspending += App_Suspending;
110 | App.Current.Resuming += App_Resuming;
111 |
112 | rootPage.NotifyUser("Press Run to register watcher.", NotifyType.StatusMessage);
113 | }
114 |
115 | protected override void OnNavigatedFrom(NavigationEventArgs e)
116 | {
117 | // Remove local suspension handlers from the App since this page is no longer active.
118 | App.Current.Suspending -= App_Suspending;
119 | App.Current.Resuming -= App_Resuming;
120 |
121 | // Since the watcher is registered in the background, the background task will be triggered when the App is closed
122 | // or in the background. To unregister the task, press the Stop button.
123 | if (taskRegistration != null)
124 | {
125 | // Always unregister the handlers to release the resources to prevent leaks.
126 | taskRegistration.Completed -= OnBackgroundTaskCompleted;
127 | }
128 | }
129 |
130 | ///
131 | /// Invoked when application execution is being resumed.
132 | ///
133 | /// The source of the resume request.
134 | ///
135 | private void App_Resuming(object sender, object e)
136 | {
137 | // Get the existing task if already registered
138 | if (taskRegistration == null)
139 | {
140 | // Find the task if we previously registered it
141 | foreach (var task in BackgroundTaskRegistration.AllTasks.Values)
142 | {
143 | if (task.Name == taskName)
144 | {
145 | taskRegistration = task;
146 | taskRegistration.Completed += OnBackgroundTaskCompleted;
147 | break;
148 | }
149 | }
150 | }
151 | else
152 | {
153 | taskRegistration.Completed += OnBackgroundTaskCompleted;
154 | }
155 | }
156 |
157 | ///
158 | /// Invoked when application execution is being suspended.
159 | ///
160 | /// The source of the suspend request.
161 | ///
162 | void App_Suspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e)
163 | {
164 | if (taskRegistration != null)
165 | {
166 | // Always unregister the handlers to release the resources to prevent leaks.
167 | taskRegistration.Completed -= OnBackgroundTaskCompleted;
168 | }
169 | rootPage.NotifyUser("App suspending.", NotifyType.StatusMessage);
170 | }
171 |
172 | ///
173 | /// When the user presses the request button, ask for permission to use the given device. This
174 | /// may take 30 seconds.
175 | ///
176 | /// Instance that triggered the event.
177 | /// Event data describing the conditions that led to the event.
178 | private async void RequestButton_Click(object sender, RoutedEventArgs e)
179 | {
180 | rootPage.NotifyUser("Getting permission to device..", NotifyType.StatusMessage);
181 |
182 | // Find the device
183 | string deviceSelector = BluetoothLEDevice.GetDeviceSelectorFromDeviceName(this.peripheralDeviceName);
184 | var devices = await DeviceInformation.FindAllAsync(deviceSelector);
185 |
186 | // Return if we don't find a device - this will happen if the device we are searching for is not paired
187 | if (devices.Count == 0)
188 | {
189 | rootPage.NotifyUser("Device not found. Make sure it is paired.", NotifyType.ErrorMessage);
190 | return;
191 | }
192 |
193 | // Try to access the device to trigger the permissions dialogue. Immediately dispose the device so it is not
194 | // connected to us and we can view advertisements from it in the background.
195 | DeviceInformation firstDevice = devices[0];
196 | BluetoothLEDevice device = await BluetoothLEDevice.FromIdAsync(firstDevice.Id);
197 | device.Dispose();
198 |
199 | rootPage.NotifyUser("Received permission to device.", NotifyType.StatusMessage);
200 | }
201 |
202 | ///
203 | /// When the user presses the stop button, unregister the background task
204 | ///
205 | /// Instance that triggered the event.
206 | /// Event data describing the conditions that led to the event.
207 | private void StopButton_Click(object sender, RoutedEventArgs e)
208 | {
209 | // Unregistering the background task will stop scanning if this is the only client requesting scan
210 | // First get the existing tasks to see if we already registered for it
211 | if (taskRegistration != null)
212 | {
213 | taskRegistration.Unregister(true);
214 | taskRegistration = null;
215 | rootPage.NotifyUser("Background watcher unregistered.", NotifyType.StatusMessage);
216 | }
217 | else
218 | {
219 | // At this point we assume we haven't found any existing tasks matching the one we want to unregister
220 | rootPage.NotifyUser("No registered background watcher found.", NotifyType.StatusMessage);
221 | }
222 | }
223 |
224 | ///
225 | /// When the user presses the run button, start the background watcher or alert the user that one is already registered
226 | ///
227 | /// Instance that triggered the event.
228 | /// Event data describing the conditions that led to the event.
229 | private async void RunButton_Click(object sender, RoutedEventArgs e)
230 | {
231 | // Registering a background trigger if it is not already registered. It will start background scanning.
232 | // First get the existing tasks to see if we already registered for it
233 | if (taskRegistration != null)
234 | {
235 | rootPage.NotifyUser("Background watcher already registered.", NotifyType.StatusMessage);
236 | return;
237 | }
238 | else
239 | {
240 | rootPage.NotifyUser("Registering background watcher.", NotifyType.StatusMessage);
241 |
242 | // Applications registering for background trigger must request for permission.
243 | BackgroundAccessStatus backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();
244 |
245 | // Here, we do not fail the registration even if the access is not granted. Instead, we allow
246 | // the trigger to be registered and when the access is granted for the Application at a later time,
247 | // the trigger will automatically start working again.
248 |
249 | // At this point we assume we haven't found any existing tasks matching the one we want to register
250 | // First, configure the task entry point, trigger and name
251 | var builder = new BackgroundTaskBuilder();
252 | builder.TaskEntryPoint = taskEntryPoint;
253 | builder.SetTrigger(trigger);
254 | builder.Name = taskName;
255 |
256 | // Now perform the registration. The registration can throw an exception if the current
257 | // hardware does not support background advertisement offloading
258 | try
259 | {
260 | taskRegistration = builder.Register();
261 |
262 | // For this scenario, attach an event handler to display the result processed from the background task
263 | taskRegistration.Completed += OnBackgroundTaskCompleted;
264 |
265 | // Even though the trigger is registered successfully, it might be blocked. Notify the user if that is the case.
266 | if ((backgroundAccessStatus == BackgroundAccessStatus.Denied) || (backgroundAccessStatus == BackgroundAccessStatus.Unspecified))
267 | {
268 | rootPage.NotifyUser("Not able to run in background. Application must given permission to be added to lock screen.",
269 | NotifyType.ErrorMessage);
270 | }
271 | else
272 | {
273 | rootPage.NotifyUser("Background watcher registered.", NotifyType.StatusMessage);
274 | }
275 | }
276 | catch (Exception ex)
277 | {
278 | switch ((uint)ex.HResult)
279 | {
280 | case (0x80070032): // ERROR_NOT_SUPPORTED
281 | rootPage.NotifyUser("The hardware does not support background advertisement offload.", NotifyType.ErrorMessage);
282 | break;
283 | default:
284 | System.Diagnostics.Debug.WriteLine(ex.Message);
285 | throw ex;
286 | }
287 | }
288 | }
289 | }
290 | }
291 | }
292 |
--------------------------------------------------------------------------------
/BluetoothBeyondBeacons/cs/Tasks/AdvertisementWatcherTask.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************
2 | //
3 | // Copyright (c) Microsoft. All rights reserved.
4 | // This code is licensed under the MIT License (MIT).
5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
9 | //
10 | //*********************************************************
11 |
12 | using System;
13 | using System.Collections.Generic;
14 | using System.Threading.Tasks;
15 | using Windows.ApplicationModel.Background;
16 | using Windows.Devices.Bluetooth;
17 | using Windows.Devices.Bluetooth.Background;
18 | using Windows.Devices.Bluetooth.Advertisement;
19 | using Windows.Storage.Streams;
20 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
21 |
22 | namespace BackgroundTasks
23 | {
24 | // A background task always implements the IBackgroundTask interface.
25 | public sealed class AdvertisementWatcherTask : IBackgroundTask
26 | {
27 | private IBackgroundTaskInstance backgroundTaskInstance;
28 |
29 | // GUID for the motor characteristic on the Lego device
30 | private static Guid OutputCommandCharacteristicGuid = new Guid("00001565-1212-efde-1523-785feabcd123");
31 |
32 | // GUID for the I/O service on the Lego device
33 | private static Guid IoServiceUuid = new Guid("00004F0E-1212-efde-1523-785feabcd123");
34 |
35 | // Min RSSI needed to activate the motor.
36 | // Decrease this to activate the motor when the device is further away.
37 | private static int WriteCharacteristicMinRSSI = -40;
38 |
39 | // Number of seconds the motor will spin for
40 | private static int MotorSpinSeconds = 2;
41 |
42 | ///
43 | /// Write to the motor telling it to spin
44 | ///
45 | /// The characteristic to write to.
46 | private async Task writeToCharacteristic(GattCharacteristic outputCommandCharacteristic)
47 | {
48 | DataWriter writer = new DataWriter();
49 | byte[] data = new byte[]
50 | {
51 | 1, // connectId - 1/2
52 | 1, // commandId - 1 is for writing motor power
53 | 1, // data size in bytes
54 | 100 // data, in this case - motor power - (100) full speed forward
55 | };
56 | writer.WriteBytes(data);
57 | var buf = writer.DetachBuffer();
58 | return await outputCommandCharacteristic.WriteValueAsync(buf);
59 | }
60 |
61 | ///
62 | /// The entry point of a background task.
63 | ///
64 | /// The current background task instance.
65 | public async void Run(IBackgroundTaskInstance taskInstance)
66 | {
67 | backgroundTaskInstance = taskInstance;
68 |
69 | // Get the details of the trigger
70 | var details = taskInstance.TriggerDetails as BluetoothLEAdvertisementWatcherTriggerDetails;
71 | if (details != null)
72 | {
73 | // If the background watcher stopped unexpectedly, an error will be available here.
74 | var error = details.Error;
75 |
76 | if (error == BluetoothError.Success)
77 | {
78 | // The Advertisements property is a list of all advertisement events received
79 | // since the last task triggered. The list of advertisements here might be valid even if
80 | // the Error status is not Success since advertisements are stored until this task is triggered
81 | IReadOnlyList advertisements = details.Advertisements;
82 |
83 | // The signal strength filter configuration of the trigger is returned such that further
84 | // processing can be performed here using these values if necessary. They are read-only here.
85 | var rssiFilter = details.SignalStrengthFilter;
86 |
87 | // Make sure we have advertisements to work with
88 | if (advertisements.Count == 0) return;
89 |
90 | // Grab the first advertisement
91 | var eventArg = advertisements[0];
92 |
93 | if (eventArg.RawSignalStrengthInDBm > WriteCharacteristicMinRSSI)
94 | {
95 | // Get a deferral so we can use the await operator without the background task returning and closing the thread
96 | BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
97 |
98 | // Get a connection to the device and get the service that we're looking for
99 | BluetoothLEDevice device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArg.BluetoothAddress);
100 |
101 | // Get the service and characteristic we're looking for
102 | var service = device.GetGattService(IoServiceUuid);
103 | var characteristic = service.GetCharacteristics(OutputCommandCharacteristicGuid)[0];
104 |
105 | // Write to the motor characteristic telling it to spin
106 | GattCommunicationStatus status = await this.writeToCharacteristic(characteristic);
107 |
108 | // Wait a couple seconds before we disconnect so we can see the motor spin
109 | await Task.Delay(TimeSpan.FromSeconds(MotorSpinSeconds));
110 |
111 | // Disconnect from the device so the motor stops
112 | device.Dispose();
113 |
114 | // Let the system know that we've finished the background task
115 | deferral.Complete();
116 | }
117 | }
118 | }
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/BluetoothBeyondBeacons/cs/Tasks/BackgroundTasks.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {13331B5B-97D7-4290-A230-67BAEAE415C5}
8 | winmdobj
9 | Properties
10 | BackgroundTasks
11 | BackgroundTasks
12 | en-US
13 | UAP
14 | 10.0.10586.0
15 | 10.0.10240.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 |
20 |
21 | ARM
22 | true
23 | bin\ARM\Debug\
24 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
25 | ;2008
26 | full
27 | ARM
28 | false
29 | prompt
30 | true
31 |
32 |
33 | ARM
34 | bin\ARM\Release\
35 | TRACE;NETFX_CORE;WINDOWS_UAP
36 | true
37 | ;2008
38 | pdbonly
39 | ARM
40 | false
41 | prompt
42 | true
43 |
44 |
45 | x64
46 | true
47 | bin\x64\Debug\
48 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
49 | ;2008
50 | full
51 | x64
52 | false
53 | prompt
54 | true
55 |
56 |
57 | x64
58 | bin\x64\Release\
59 | TRACE;NETFX_CORE;WINDOWS_UAP
60 | true
61 | ;2008
62 | pdbonly
63 | x64
64 | false
65 | prompt
66 | true
67 |
68 |
69 | x86
70 | true
71 | bin\x86\Debug\
72 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
73 | ;2008
74 | full
75 | x86
76 | false
77 | prompt
78 | true
79 |
80 |
81 | x86
82 | bin\x86\Release\
83 | TRACE;NETFX_CORE;WINDOWS_UAP
84 | true
85 | ;2008
86 | pdbonly
87 | x86
88 | false
89 | prompt
90 | true
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | 14.0
102 |
103 |
104 |
111 |
--------------------------------------------------------------------------------
/BluetoothBeyondBeacons/cs/Tasks/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Tasks")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Tasks")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/BluetoothBeyondBeacons/cs/Tasks/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
4 | },
5 | "frameworks": {
6 | "uap10.0": {}
7 | },
8 | "runtimes": {
9 | "win10-arm": {},
10 | "win10-arm-aot": {},
11 | "win10-x86": {},
12 | "win10-x86-aot": {},
13 | "win10-x64": {},
14 | "win10-x64-aot": {}
15 | }
16 | }
--------------------------------------------------------------------------------
/BluetoothBeyondBeacons/cs/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
4 | },
5 | "frameworks": {
6 | "uap10.0": {}
7 | },
8 | "runtimes": {
9 | "win10-arm": {},
10 | "win10-arm-aot": {},
11 | "win10-x86": {},
12 | "win10-x86-aot": {},
13 | "win10-x64": {},
14 | "win10-x64-aot": {}
15 | }
16 | }
--------------------------------------------------------------------------------
/BluetoothInAppGATT/README.md:
--------------------------------------------------------------------------------
1 | # Bluetooth Device Companion Sample App
2 |
3 | ## Run the sample
4 |
5 | The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
6 |
7 | ### Deploying the sample
8 |
9 | - Select Build > Deploy Solution.
10 |
11 | ### Deploying and running the sample
12 |
13 | - To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging.
14 |
--------------------------------------------------------------------------------
/BluetoothInAppGATT/cs/BluetoothInAppGATT.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}
8 | AppContainerExe
9 | Properties
10 | SDKTemplate
11 | BluetoothInAppGATT
12 | en-US
13 | UAP
14 | 10.0.10586.0
15 | 10.0.10240.0
16 | 14
17 | true
18 | 512
19 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
20 | true
21 | True
22 | arm
23 |
24 |
25 | true
26 | bin\ARM\Debug\
27 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
28 | ;2008
29 | full
30 | ARM
31 | false
32 | prompt
33 | true
34 |
35 |
36 | bin\ARM\Release\
37 | TRACE;NETFX_CORE;WINDOWS_UAP
38 | true
39 | ;2008
40 | pdbonly
41 | ARM
42 | false
43 | prompt
44 | true
45 | true
46 |
47 |
48 | true
49 | bin\x64\Debug\
50 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
51 | ;2008
52 | full
53 | x64
54 | false
55 | prompt
56 | true
57 |
58 |
59 | bin\x64\Release\
60 | TRACE;NETFX_CORE;WINDOWS_UAP
61 | true
62 | ;2008
63 | pdbonly
64 | x64
65 | false
66 | prompt
67 | true
68 | true
69 |
70 |
71 | true
72 | bin\x86\Debug\
73 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
74 | ;2008
75 | full
76 | x86
77 | false
78 | prompt
79 | true
80 |
81 |
82 | bin\x86\Release\
83 | TRACE;NETFX_CORE;WINDOWS_UAP
84 | true
85 | ;2008
86 | pdbonly
87 | x86
88 | false
89 | prompt
90 | true
91 | true
92 |
93 |
94 |
95 | App.xaml.cs
96 | App.xaml
97 |
98 |
99 | MainPage.xaml.cs
100 | MainPage.xaml
101 |
102 |
103 | Properties\AssemblyInfo.cs
104 |
105 |
106 |
107 | Scenario1_InAppGATT.xaml
108 |
109 |
110 |
111 |
112 | Designer
113 |
114 |
115 |
116 |
117 | App.xaml
118 | MSBuild:Compile
119 | Designer
120 |
121 |
122 | MainPage.xaml
123 | MSBuild:Compile
124 | Designer
125 |
126 |
127 | MSBuild:Compile
128 | Designer
129 |
130 |
131 | Styles\Styles.xaml
132 | MSBuild:Compile
133 | Designer
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 | Assets\microsoft-sdk.png
143 |
144 |
145 | Assets\placeholder-sdk.png
146 |
147 |
148 | Assets\smalltile-sdk.png
149 |
150 |
151 | Assets\splash-sdk.png
152 |
153 |
154 | Assets\squaretile-sdk.png
155 |
156 |
157 | Assets\storelogo-sdk.png
158 |
159 |
160 | Assets\tile-sdk.png
161 |
162 |
163 | Assets\windows-sdk.png
164 |
165 |
166 |
167 | 14.0
168 |
169 |
170 | true
171 |
172 |
173 | InAppGatt.snk
174 |
175 |
176 |
183 |
--------------------------------------------------------------------------------
/BluetoothInAppGATT/cs/BluetoothInAppGATT.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.23107.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BluetoothInAppGATT", "BluetoothInAppGATT.csproj", "{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|ARM = Debug|ARM
11 | Debug|x64 = Debug|x64
12 | Debug|x86 = Debug|x86
13 | Release|ARM = Release|ARM
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.ActiveCfg = Debug|ARM
19 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Build.0 = Debug|ARM
20 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Deploy.0 = Debug|ARM
21 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.ActiveCfg = Debug|x64
22 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Build.0 = Debug|x64
23 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Deploy.0 = Debug|x64
24 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.ActiveCfg = Debug|x86
25 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Build.0 = Debug|x86
26 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Deploy.0 = Debug|x86
27 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.ActiveCfg = Release|ARM
28 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Build.0 = Release|ARM
29 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Deploy.0 = Release|ARM
30 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.ActiveCfg = Release|x64
31 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Build.0 = Release|x64
32 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Deploy.0 = Release|x64
33 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.ActiveCfg = Release|x86
34 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Build.0 = Release|x86
35 | {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Deploy.0 = Release|x86
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/BluetoothInAppGATT/cs/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Bluetooth Pairing and GATT Client C# Sample
7 | Microsoft Corporation
8 | Assets\StoreLogo-sdk.png
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/BluetoothInAppGATT/cs/SampleConfiguration.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************
2 | //
3 | // Copyright (c) Microsoft. All rights reserved.
4 | // This code is licensed under the MIT License (MIT).
5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
9 | //
10 | //*********************************************************
11 |
12 | using System;
13 | using System.Collections.Generic;
14 | using Windows.UI.Xaml.Controls;
15 |
16 | namespace SDKTemplate
17 | {
18 | public partial class MainPage : Page
19 | {
20 | public const string FEATURE_NAME = "Bluetooth in app pairing and GATT Client";
21 |
22 | List scenarios = new List
23 | {
24 | new Scenario()
25 | {
26 | Title = "In app pairing and GATT Client",
27 | ClassType = typeof(Scenario1_InAppGATT)
28 | },
29 | };
30 | }
31 |
32 | public class Scenario
33 | {
34 | public string Title { get; set; }
35 | public Type ClassType { get; set; }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/BluetoothInAppGATT/cs/Scenario1_InAppGATT.xaml:
--------------------------------------------------------------------------------
1 |
13 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
44 |
45 |
46 |
47 |
48 |
49 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | Enumerates all Bluetooth LE devices that are discoverable to Windows and connects to the selected one.
73 |
74 |
75 |
81 |
88 |
96 |
104 |
105 |
106 |
107 |
115 |
123 |
131 |
132 |
133 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
147 |
148 |
149 |
150 |
151 |
152 |
--------------------------------------------------------------------------------
/BluetoothInAppGATT/cs/Scenario1_InAppGATT.xaml.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************
2 | //
3 | // Copyright (c) Microsoft. All rights reserved.
4 | // This code is licensed under the MIT License (MIT).
5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
9 | //
10 | //*********************************************************
11 |
12 | using System;
13 | using System.Threading;
14 | using System.Collections.Generic;
15 | using Windows.Devices.Bluetooth;
16 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
17 | using Windows.Devices.Enumeration;
18 | using Windows.Foundation;
19 | using Windows.UI.Core;
20 | using Windows.UI.Xaml;
21 | using Windows.UI.Xaml.Controls;
22 | using Windows.UI.Xaml.Navigation;
23 | using System.ComponentModel;
24 | using Windows.UI.Xaml.Media.Imaging;
25 | using System.Collections.ObjectModel;
26 | using Windows.UI.Xaml.Data;
27 | using Windows.Storage.Streams;
28 |
29 | namespace SDKTemplate
30 | {
31 | public sealed partial class Scenario1_InAppGATT : Page
32 | {
33 | // A pointer back to the main page is required to display status messages.
34 | private MainPage rootPage = MainPage.Current;
35 |
36 | // Used to display list of available devices
37 | public ObservableCollection ResultCollection
38 | {
39 | get;
40 | private set;
41 | }
42 |
43 | private DeviceWatcher deviceWatcher = null;
44 | private DeviceWatcher gattServiceWatcher = null;
45 | private static Guid IoServiceUuid = new Guid("00004F0E-1212-efde-1523-785feabcd123");
46 | private static Guid OutputCommandCharacteristicGuid = new Guid("00001565-1212-efde-1523-785feabcd123");
47 | private GattDeviceService weDoIoService = null;
48 | private GattCharacteristic outputCommandCharacteristic = null;
49 |
50 | public Scenario1_InAppGATT()
51 | {
52 | this.InitializeComponent();
53 | App.Current.Suspending += App_Suspending;
54 | }
55 |
56 | protected override void OnNavigatedTo(NavigationEventArgs e)
57 | {
58 | rootPage = MainPage.Current;
59 | ResultCollection = new ObservableCollection();
60 | DataContext = this;
61 | }
62 |
63 | protected override void OnNavigatedFrom(NavigationEventArgs e)
64 | {
65 | StopBleDeviceWatcher();
66 | StopGattServiceWatcher();
67 | }
68 |
69 | private void StopBleDeviceWatcher()
70 | {
71 | StopWatcherButton.IsEnabled = false;
72 |
73 | if (null != deviceWatcher)
74 | {
75 | if (DeviceWatcherStatus.Started == deviceWatcher.Status ||
76 | DeviceWatcherStatus.EnumerationCompleted == deviceWatcher.Status)
77 | {
78 | deviceWatcher.Stop();
79 | }
80 | }
81 |
82 | StartWatcherButton.IsEnabled = true;
83 | }
84 |
85 | void App_Suspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e)
86 | {
87 | // Make sure we clean up resources on suspend.
88 | StopBleDeviceWatcher();
89 | StopGattServiceWatcher();
90 | }
91 |
92 | ///
93 | /// When the user presses the Start Watcher button, query for all Bluetooth LE devices
94 | ///
95 | /// Instance that triggered the event.
96 | /// Event data describing the conditions that led to the event.
97 | private void StartWatcherButton_Click(object sender, RoutedEventArgs e)
98 | {
99 | // Disable the button while the watcher is active so the user can't run twice.
100 | var button = sender as Button;
101 | button.IsEnabled = false;
102 | StopWatcherButton.IsEnabled = true;
103 |
104 | // Clear any previous messages
105 | rootPage.NotifyUser("", NotifyType.StatusMessage);
106 |
107 | // Enumerate all Bluetooth LE devices and display them in a list
108 | StartBleDeviceWatcher();
109 | }
110 | private void StopWatcherButton_Click(object sender, RoutedEventArgs e)
111 | {
112 | StopBleDeviceWatcher();
113 | }
114 |
115 | private void StartBleDeviceWatcher()
116 | {
117 | //Reset displayed results
118 | ResultCollection.Clear();
119 |
120 | // Request additional properties
121 | string[] requestedProperties = new string[] {"System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected"};
122 |
123 | deviceWatcher = DeviceInformation.CreateWatcher("(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")",
124 | requestedProperties,
125 | DeviceInformationKind.AssociationEndpoint);
126 |
127 | // Hook up handlers for the watcher events before starting the watcher
128 | deviceWatcher.Added += new TypedEventHandler(async (watcher, deviceInfo) =>
129 | {
130 | // Since we have the collection databound to a UI element, we need to update the collection on the UI thread.
131 | await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
132 | {
133 | ResultCollection.Add(new BluetoothLEDeviceDisplay(deviceInfo));
134 |
135 | rootPage.NotifyUser(
136 | String.Format("{0} devices found.", ResultCollection.Count),
137 | NotifyType.StatusMessage);
138 | });
139 | });
140 |
141 | deviceWatcher.Updated += new TypedEventHandler(async (watcher, deviceInfoUpdate) =>
142 | {
143 | await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
144 | {
145 | foreach (BluetoothLEDeviceDisplay bleInfoDisp in ResultCollection)
146 | {
147 | if (bleInfoDisp.Id == deviceInfoUpdate.Id)
148 | {
149 | bleInfoDisp.Update(deviceInfoUpdate);
150 |
151 | // If the item being updated is currently "selected", then update the pairing buttons
152 | BluetoothLEDeviceDisplay selectedDeviceInfoDisp = (BluetoothLEDeviceDisplay)resultsListView.SelectedItem;
153 | if (bleInfoDisp == selectedDeviceInfoDisp)
154 | {
155 | UpdateButtons();
156 | }
157 |
158 | break;
159 | }
160 | }
161 | });
162 | });
163 |
164 | deviceWatcher.EnumerationCompleted += new TypedEventHandler(async (watcher, obj) =>
165 | {
166 | await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
167 | {
168 | rootPage.NotifyUser(
169 | String.Format("{0} devices found. Enumeration completed. Watching for updates...", ResultCollection.Count),
170 | NotifyType.StatusMessage);
171 | });
172 | });
173 |
174 | deviceWatcher.Removed += new TypedEventHandler(async (watcher, deviceInfoUpdate) =>
175 | {
176 | // Since we have the collection databound to a UI element, we need to update the collection on the UI thread.
177 | await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
178 | {
179 | // Find the corresponding DeviceInformation in the collection and remove it
180 | foreach (BluetoothLEDeviceDisplay bleInfoDisp in ResultCollection)
181 | {
182 | if (bleInfoDisp.Id == deviceInfoUpdate.Id)
183 | {
184 | ResultCollection.Remove(bleInfoDisp);
185 | break;
186 | }
187 | }
188 |
189 | rootPage.NotifyUser(
190 | String.Format("{0} devices found.", ResultCollection.Count),
191 | NotifyType.StatusMessage);
192 | });
193 | });
194 |
195 | deviceWatcher.Stopped += new TypedEventHandler(async (watcher, obj) =>
196 | {
197 | await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
198 | {
199 | rootPage.NotifyUser(
200 | String.Format("{0} devices found. Watcher {1}.",
201 | ResultCollection.Count,
202 | DeviceWatcherStatus.Aborted == watcher.Status ? "aborted" : "stopped"),
203 | NotifyType.StatusMessage);
204 | });
205 | });
206 |
207 | deviceWatcher.Start();
208 | }
209 |
210 | private void StopGattServiceWatcher()
211 | {
212 | if (null != gattServiceWatcher)
213 | {
214 | if (DeviceWatcherStatus.Started == gattServiceWatcher.Status ||
215 | DeviceWatcherStatus.EnumerationCompleted == gattServiceWatcher.Status)
216 | {
217 | gattServiceWatcher.Stop();
218 | }
219 | }
220 | }
221 |
222 | private async void StartGattServiceWatcher()
223 | {
224 | //Get the Bluetooth address for filtering the watcher
225 | BluetoothLEDeviceDisplay deviceInfoDisp = resultsListView.SelectedItem as BluetoothLEDeviceDisplay;
226 | BluetoothLEDevice bleDevice = await BluetoothLEDevice.FromIdAsync(deviceInfoDisp.Id);
227 | string selector = "(" + GattDeviceService.GetDeviceSelectorFromUuid(IoServiceUuid) + ")"
228 | + " AND (System.DeviceInterface.Bluetooth.DeviceAddress:=\""
229 | + bleDevice.BluetoothAddress.ToString("X") + "\")";
230 |
231 | gattServiceWatcher = DeviceInformation.CreateWatcher(selector);
232 |
233 | // Hook up handlers for the watcher events before starting the watcher
234 | gattServiceWatcher.Added += new TypedEventHandler(async (watcher, deviceInfo) =>
235 | {
236 | // If the selected device is a WeDo device, enable the controls
237 | await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
238 | {
239 | weDoIoService = await GattDeviceService.FromIdAsync(deviceInfo.Id);
240 | outputCommandCharacteristic = weDoIoService.GetCharacteristics(OutputCommandCharacteristicGuid)[0];
241 | ForwardButton.IsEnabled = true;
242 | StopButton.IsEnabled = true;
243 | BackwardButton.IsEnabled = true;
244 | });
245 | });
246 |
247 | gattServiceWatcher.Updated += new TypedEventHandler(async (watcher, deviceInfoUpdate) =>
248 | {
249 | await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
250 | {
251 | //Do nothing
252 | });
253 | });
254 |
255 | gattServiceWatcher.EnumerationCompleted += new TypedEventHandler(async (watcher, obj) =>
256 | {
257 | await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
258 | {
259 | //Do nothing
260 | });
261 | });
262 |
263 | gattServiceWatcher.Removed += new TypedEventHandler(async (watcher, deviceInfoUpdate) =>
264 | {
265 | await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
266 | {
267 | //Do nothing
268 | });
269 | });
270 |
271 | gattServiceWatcher.Stopped += new TypedEventHandler(async (watcher, obj) =>
272 | {
273 | await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
274 | {
275 | //Do nothing
276 | });
277 | });
278 |
279 | gattServiceWatcher.Start();
280 | }
281 |
282 | private void ResultsListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
283 | {
284 | UpdateButtons();
285 | }
286 |
287 | private async void PairButton_Click(object sender, RoutedEventArgs e)
288 | {
289 | // Gray out the pair button and results view while pairing is in progress.
290 | resultsListView.IsEnabled = false;
291 | PairButton.IsEnabled = false;
292 | rootPage.NotifyUser("Pairing started. Please wait...", NotifyType.StatusMessage);
293 |
294 | // Get the device selected for pairing
295 | BluetoothLEDeviceDisplay deviceInfoDisp = resultsListView.SelectedItem as BluetoothLEDeviceDisplay;
296 | DevicePairingResult result = null;
297 |
298 | result = await deviceInfoDisp.DeviceInformation.Pairing.PairAsync();
299 |
300 | rootPage.NotifyUser(
301 | "Pairing result = " + result.Status.ToString(),
302 | result.Status == DevicePairingResultStatus.Paired ? NotifyType.StatusMessage : NotifyType.ErrorMessage);
303 |
304 | UpdateButtons();
305 | resultsListView.IsEnabled = true;
306 | }
307 |
308 | private async void UnpairButton_Click(object sender, RoutedEventArgs e)
309 | {
310 | // Gray out the unpair button and results view while unpairing is in progress.
311 | resultsListView.IsEnabled = false;
312 | UnpairButton.IsEnabled = false;
313 | rootPage.NotifyUser("Unpairing started. Please wait...", NotifyType.StatusMessage);
314 |
315 | BluetoothLEDeviceDisplay deviceInfoDisp = resultsListView.SelectedItem as BluetoothLEDeviceDisplay;
316 |
317 | DeviceUnpairingResult dupr = await deviceInfoDisp.DeviceInformation.Pairing.UnpairAsync();
318 |
319 | rootPage.NotifyUser(
320 | "Unpairing result = " + dupr.Status.ToString(),
321 | dupr.Status == DeviceUnpairingResultStatus.Unpaired ? NotifyType.StatusMessage : NotifyType.ErrorMessage);
322 |
323 | UpdateButtons();
324 | resultsListView.IsEnabled = true;
325 | }
326 |
327 | private async void ForwardButton_Click(object sender, RoutedEventArgs e)
328 | {
329 | DataWriter writer = new DataWriter();
330 | byte[] data = new byte[]
331 | {
332 | 1, // connectId - 1/2
333 | 1, // commandId - 1 is for writing motor power
334 | 1, // data size in bytes
335 | 100 // data, in this case - motor power - (100) full speed forward
336 | };
337 | writer.WriteBytes(data);
338 |
339 | GattCommunicationStatus status = await outputCommandCharacteristic.WriteValueAsync(
340 | writer.DetachBuffer());
341 | }
342 |
343 | private async void StopButton_Click(object sender, RoutedEventArgs e)
344 | {
345 | DataWriter writer = new DataWriter();
346 | byte[] data = new byte[]
347 | {
348 | 1, // connectId - 1/2
349 | 1, // commandId - 1 is for writing motor power
350 | 1, // data size in bytes
351 | 0 // data, in this case - motor power - (0) stop
352 | };
353 | writer.WriteBytes(data);
354 |
355 | GattCommunicationStatus status = await outputCommandCharacteristic.WriteValueAsync(
356 | writer.DetachBuffer());
357 | }
358 |
359 | private async void BackwardButton_Click(object sender, RoutedEventArgs e)
360 | {
361 | DataWriter writer = new DataWriter();
362 | byte[] data = new byte[]
363 | {
364 | 1, // connectId - 1/2
365 | 1, // commandId - 1 is for writing motor power
366 | 1, // data size in bytes
367 | 0x9C // data, in this case - motor power - (-100) full speed backward
368 | };
369 | writer.WriteBytes(data);
370 |
371 | GattCommunicationStatus status = await outputCommandCharacteristic.WriteValueAsync(
372 | writer.DetachBuffer());
373 | }
374 |
375 | private void UpdateButtons()
376 | {
377 | BluetoothLEDeviceDisplay deviceInfoDisp = (BluetoothLEDeviceDisplay)resultsListView.SelectedItem;
378 |
379 | //Reset the device control buttons to disabled
380 | ForwardButton.IsEnabled = false;
381 | StopButton.IsEnabled = false;
382 | BackwardButton.IsEnabled = false;
383 |
384 | //Update pairing buttons based on IsPaired state
385 | if (null != deviceInfoDisp && !deviceInfoDisp.DeviceInformation.Pairing.IsPaired)
386 | {
387 | PairButton.IsEnabled = true;
388 | }
389 | else
390 | {
391 | PairButton.IsEnabled = false;
392 | }
393 |
394 | if (null != deviceInfoDisp &&
395 | deviceInfoDisp.DeviceInformation.Pairing.IsPaired)
396 | {
397 | UnpairButton.IsEnabled = true;
398 | }
399 | else
400 | {
401 | UnpairButton.IsEnabled = false;
402 | }
403 |
404 | //Stop any existing service watcher
405 | if (gattServiceWatcher != null)
406 | {
407 | StopGattServiceWatcher();
408 | }
409 |
410 | //If there is a paired device selected, look for the WeDo service and enable controls if found
411 | if (deviceInfoDisp != null)
412 | {
413 | if (deviceInfoDisp.IsPaired == true)
414 | {
415 | StartGattServiceWatcher();
416 | }
417 | }
418 |
419 | }
420 | }
421 |
422 | public class BluetoothLEDeviceDisplay : INotifyPropertyChanged
423 | {
424 | private DeviceInformation deviceInfo;
425 |
426 | public BluetoothLEDeviceDisplay(DeviceInformation deviceInfoIn)
427 | {
428 | deviceInfo = deviceInfoIn;
429 | UpdateGlyphBitmapImage();
430 | }
431 |
432 | public DeviceInformation DeviceInformation
433 | {
434 | get
435 | {
436 | return deviceInfo;
437 | }
438 |
439 | private set
440 | {
441 | deviceInfo = value;
442 | }
443 | }
444 |
445 | public string Id
446 | {
447 | get
448 | {
449 | return deviceInfo.Id;
450 | }
451 | }
452 |
453 | public string Name
454 | {
455 | get
456 | {
457 | return deviceInfo.Name;
458 | }
459 | }
460 | public bool IsPaired
461 | {
462 | get
463 | {
464 | return deviceInfo.Pairing.IsPaired;
465 | }
466 | }
467 |
468 | public IReadOnlyDictionary Properties
469 | {
470 | get
471 | {
472 | return deviceInfo.Properties;
473 | }
474 | }
475 |
476 | public BitmapImage GlyphBitmapImage
477 | {
478 | get;
479 | private set;
480 | }
481 |
482 | public void Update(DeviceInformationUpdate deviceInfoUpdate)
483 | {
484 | deviceInfo.Update(deviceInfoUpdate);
485 |
486 | OnPropertyChanged("Id");
487 | OnPropertyChanged("Name");
488 | OnPropertyChanged("DeviceInformation");
489 | OnPropertyChanged("IsPaired");
490 | OnPropertyChanged("Properties");
491 |
492 | UpdateGlyphBitmapImage();
493 | }
494 |
495 | private async void UpdateGlyphBitmapImage()
496 | {
497 | DeviceThumbnail deviceThumbnail = await deviceInfo.GetGlyphThumbnailAsync();
498 | BitmapImage glyphBitmapImage = new BitmapImage();
499 | await glyphBitmapImage.SetSourceAsync(deviceThumbnail);
500 | GlyphBitmapImage = glyphBitmapImage;
501 | OnPropertyChanged("GlyphBitmapImage");
502 | }
503 |
504 | public event PropertyChangedEventHandler PropertyChanged;
505 | protected void OnPropertyChanged(string name)
506 | {
507 | PropertyChangedEventHandler handler = PropertyChanged;
508 | if (handler != null)
509 | {
510 | handler(this, new PropertyChangedEventArgs(name));
511 | }
512 | }
513 | }
514 |
515 | public class GeneralPropertyValueConverter : IValueConverter
516 | {
517 | public object Convert(object value, Type targetType, object parameter, string language)
518 | {
519 | object property = null;
520 |
521 | if (value is IReadOnlyDictionary &&
522 | parameter is string &&
523 | !String.IsNullOrEmpty((string)parameter))
524 | {
525 | IReadOnlyDictionary properties = value as IReadOnlyDictionary;
526 | string propertyName = parameter as string;
527 |
528 | property = properties[propertyName];
529 | }
530 |
531 | return property;
532 | }
533 |
534 | public object ConvertBack(object value, Type targetType, object parameter, string language)
535 | {
536 | throw new NotImplementedException();
537 | }
538 | }
539 | }
540 |
--------------------------------------------------------------------------------
/BluetoothInAppGATT/cs/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
4 | },
5 | "frameworks": {
6 | "uap10.0": {}
7 | },
8 | "runtimes": {
9 | "win10-arm": {},
10 | "win10-arm-aot": {},
11 | "win10-x86": {},
12 | "win10-x86-aot": {},
13 | "win10-x64": {},
14 | "win10-x64-aot": {}
15 | }
16 | }
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.23107.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BtAvatar", "BtAvatar\BtAvatar.csproj", "{4CAA4048-47E9-4B2C-BCD9-EA669009705C}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|ARM = Debug|ARM
11 | Debug|x64 = Debug|x64
12 | Debug|x86 = Debug|x86
13 | Release|ARM = Release|ARM
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Debug|ARM.ActiveCfg = Debug|ARM
19 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Debug|ARM.Build.0 = Debug|ARM
20 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Debug|ARM.Deploy.0 = Debug|ARM
21 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Debug|x64.ActiveCfg = Debug|x64
22 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Debug|x64.Build.0 = Debug|x64
23 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Debug|x64.Deploy.0 = Debug|x64
24 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Debug|x86.ActiveCfg = Debug|x86
25 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Debug|x86.Build.0 = Debug|x86
26 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Debug|x86.Deploy.0 = Debug|x86
27 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Release|ARM.ActiveCfg = Release|ARM
28 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Release|ARM.Build.0 = Release|ARM
29 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Release|ARM.Deploy.0 = Release|ARM
30 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Release|x64.ActiveCfg = Release|x64
31 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Release|x64.Build.0 = Release|x64
32 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Release|x64.Deploy.0 = Release|x64
33 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Release|x86.ActiveCfg = Release|x86
34 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Release|x86.Build.0 = Release|x86
35 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}.Release|x86.Deploy.0 = Release|x86
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.ApplicationModel;
7 | using Windows.ApplicationModel.Activation;
8 | using Windows.Foundation;
9 | using Windows.Foundation.Collections;
10 | using Windows.UI.Xaml;
11 | using Windows.UI.Xaml.Controls;
12 | using Windows.UI.Xaml.Controls.Primitives;
13 | using Windows.UI.Xaml.Data;
14 | using Windows.UI.Xaml.Input;
15 | using Windows.UI.Xaml.Media;
16 | using Windows.UI.Xaml.Navigation;
17 |
18 | namespace BtAvatar
19 | {
20 | ///
21 | /// Provides application-specific behavior to supplement the default Application class.
22 | ///
23 | sealed partial class App : Application
24 | {
25 | ///
26 | /// Initializes the singleton application object. This is the first line of authored code
27 | /// executed, and as such is the logical equivalent of main() or WinMain().
28 | ///
29 | public App()
30 | {
31 | this.InitializeComponent();
32 | this.Suspending += OnSuspending;
33 | }
34 |
35 | ///
36 | /// Invoked when the application is launched normally by the end user. Other entry points
37 | /// will be used such as when the application is launched to open a specific file.
38 | ///
39 | /// Details about the launch request and process.
40 | protected override void OnLaunched(LaunchActivatedEventArgs e)
41 | {
42 |
43 | #if DEBUG
44 | if (System.Diagnostics.Debugger.IsAttached)
45 | {
46 | this.DebugSettings.EnableFrameRateCounter = true;
47 | }
48 | #endif
49 |
50 | Frame rootFrame = Window.Current.Content as Frame;
51 |
52 | // Do not repeat app initialization when the Window already has content,
53 | // just ensure that the window is active
54 | if (rootFrame == null)
55 | {
56 | // Create a Frame to act as the navigation context and navigate to the first page
57 | rootFrame = new Frame();
58 |
59 | rootFrame.NavigationFailed += OnNavigationFailed;
60 |
61 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
62 | {
63 | //TODO: Load state from previously suspended application
64 | }
65 |
66 | // Place the frame in the current Window
67 | Window.Current.Content = rootFrame;
68 | }
69 |
70 | if (rootFrame.Content == null)
71 | {
72 | // When the navigation stack isn't restored navigate to the first page,
73 | // configuring the new page by passing required information as a navigation
74 | // parameter
75 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
76 | }
77 | // Ensure the current window is active
78 | Window.Current.Activate();
79 | }
80 |
81 | ///
82 | /// Invoked when Navigation to a certain page fails
83 | ///
84 | /// The Frame which failed navigation
85 | /// Details about the navigation failure
86 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
87 | {
88 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
89 | }
90 |
91 | ///
92 | /// Invoked when application execution is being suspended. Application state is saved
93 | /// without knowing whether the application will be terminated or resumed with the contents
94 | /// of memory still intact.
95 | ///
96 | /// The source of the suspend request.
97 | /// Details about the suspend request.
98 | private void OnSuspending(object sender, SuspendingEventArgs e)
99 | {
100 | var deferral = e.SuspendingOperation.GetDeferral();
101 | //TODO: Save application state and stop any background activity
102 | deferral.Complete();
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/BtAvatar.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {4CAA4048-47E9-4B2C-BCD9-EA669009705C}
8 | AppContainerExe
9 | Properties
10 | BtAvatar
11 | BtAvatar
12 | en-US
13 | UAP
14 | 10.0.14267.0
15 | 10.0.14257.0
16 | 14
17 | true
18 | 512
19 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
20 | BtAvatar_TemporaryKey.pfx
21 | True
22 | x64
23 |
24 |
25 | true
26 | bin\ARM\Debug\
27 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
28 | ;2008
29 | full
30 | ARM
31 | false
32 | prompt
33 | true
34 |
35 |
36 | bin\ARM\Release\
37 | TRACE;NETFX_CORE;WINDOWS_UWP
38 | true
39 | ;2008
40 | pdbonly
41 | ARM
42 | false
43 | prompt
44 | true
45 | true
46 |
47 |
48 | true
49 | bin\x64\Debug\
50 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
51 | ;2008
52 | full
53 | x64
54 | false
55 | prompt
56 | true
57 |
58 |
59 | bin\x64\Release\
60 | TRACE;NETFX_CORE;WINDOWS_UWP
61 | true
62 | ;2008
63 | pdbonly
64 | x64
65 | false
66 | prompt
67 | true
68 | true
69 |
70 |
71 | true
72 | bin\x86\Debug\
73 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
74 | ;2008
75 | full
76 | x86
77 | false
78 | prompt
79 | true
80 |
81 |
82 | bin\x86\Release\
83 | TRACE;NETFX_CORE;WINDOWS_UWP
84 | true
85 | ;2008
86 | pdbonly
87 | x86
88 | false
89 | prompt
90 | true
91 | true
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | App.xaml
100 |
101 |
102 | MainPage.xaml
103 |
104 |
105 |
106 |
107 |
108 | Designer
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | MSBuild:Compile
124 | Designer
125 |
126 |
127 | MSBuild:Compile
128 | Designer
129 |
130 |
131 |
132 | 14.0
133 |
134 |
135 |
142 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Devices.Bluetooth;
7 | using Windows.Devices.Bluetooth.Rfcomm;
8 | using Windows.Foundation;
9 | using Windows.Foundation.Collections;
10 | using Windows.Media.Core;
11 | using Windows.Networking.Sockets;
12 | using Windows.Storage;
13 | using Windows.Storage.Pickers;
14 | using Windows.Storage.Streams;
15 | using Windows.UI.Xaml;
16 | using Windows.UI.Xaml.Controls;
17 | using Windows.UI.Xaml.Controls.Primitives;
18 | using Windows.UI.Xaml.Data;
19 | using Windows.UI.Xaml.Input;
20 | using Windows.UI.Xaml.Media;
21 | using Windows.UI.Xaml.Navigation;
22 |
23 | // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
24 |
25 | namespace BtAvatar
26 | {
27 |
28 | ///
29 | /// An empty page that can be used on its own or navigated to within a Frame.
30 | ///
31 | public sealed partial class MainPage : Page
32 | {
33 | private StreamSocket socket;
34 | private DataWriter writer;
35 | private RfcommServiceProvider rfcommProvider;
36 | private StreamSocketListener socketListener;
37 | private readonly Guid rfcommChatServiceUuid = Guid.Parse("87bf52c0-4595-43b3-a5b0-702de8d5dbba");
38 |
39 | public const UInt16 SdpServiceNameAttributeId = 0x100;
40 | public const byte SdpServiceNameAttributeType = (4 << 3) | 5;
41 | public const string SdpServiceName = "Sensor Avatar Service";
42 |
43 | public MainPage()
44 | {
45 | this.InitializeComponent();
46 | }
47 |
48 | protected override void OnNavigatedTo(NavigationEventArgs e)
49 | {
50 |
51 |
52 |
53 | }
54 |
55 | private void ListenButton_Click(object sender, RoutedEventArgs e)
56 | {
57 | InitializeRfcommServer();
58 | }
59 | ///
60 | /// Initializes the server using RfcommServiceProvider to advertise the Chat Service UUID and start listening
61 | /// for incoming connections.
62 | ///
63 | private async void InitializeRfcommServer()
64 | {
65 |
66 | try
67 | {
68 | rfcommProvider = await RfcommServiceProvider.CreateAsync(RfcommServiceId.FromUuid(rfcommChatServiceUuid));
69 | }
70 | catch (Exception e)
71 | {
72 | // If you aren't able to get a reference to an RfcommServiceProvider, tell the user why. Usually throws an exception if the Bluetooth radio is off.
73 | Status.Text = e.Message;
74 | return;
75 | }
76 |
77 |
78 | // Create a listener for this service and start listening
79 | socketListener = new StreamSocketListener();
80 | socketListener.ConnectionReceived += OnConnectionReceived;
81 |
82 | await socketListener.BindServiceNameAsync(rfcommProvider.ServiceId.AsString(),
83 | SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);
84 |
85 | // Set the SDP attributes and start Bluetooth advertising
86 | InitializeServiceSdpAttributes(rfcommProvider);
87 |
88 | try
89 | {
90 | rfcommProvider.StartAdvertising(socketListener, true);
91 | }
92 | catch (Exception e)
93 | {
94 | Status.Text = e.Message;
95 | return;
96 | }
97 |
98 |
99 | Status.Text = "Listening for incoming connections";
100 | }
101 |
102 | ///
103 | /// Creates the SDP record that will be revealed to the Client device when pairing occurs.
104 | ///
105 | /// The RfcommServiceProvider that is being used to initialize the server
106 | private void InitializeServiceSdpAttributes(RfcommServiceProvider rfcommProvider)
107 | {
108 | var sdpWriter = new DataWriter();
109 |
110 | // Write the Service Name Attribute.
111 | sdpWriter.WriteByte(SdpServiceNameAttributeType);
112 |
113 | // The length of the UTF-8 encoded Service Name SDP Attribute.
114 | sdpWriter.WriteByte((byte)SdpServiceName.Length);
115 |
116 | // The UTF-8 encoded Service Name value.
117 | sdpWriter.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
118 | sdpWriter.WriteString(SdpServiceName);
119 |
120 | // Set the SDP Attribute on the RFCOMM Service Provider.
121 | rfcommProvider.SdpRawAttributes.Add(SdpServiceNameAttributeId, sdpWriter.DetachBuffer());
122 | }
123 |
124 | ///
125 | /// Invoked when the socket listener accepts an incoming Bluetooth connection.
126 | ///
127 | /// The socket listener that accepted the connection.
128 | /// The connection accept parameters, which contain the connected socket.
129 | private async void OnConnectionReceived(
130 | StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
131 | {
132 | // Don't need the listener anymore
133 | socketListener.Dispose();
134 | socketListener = null;
135 |
136 | try
137 | {
138 | socket = args.Socket;
139 | }
140 | catch (Exception e)
141 | {
142 | await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
143 | {
144 | Status.Text = e.Message;
145 | });
146 | Disconnect();
147 | return;
148 | }
149 |
150 | // Note - this is the supported way to get a Bluetooth device from a given socket
151 | var remoteDevice = await BluetoothDevice.FromHostNameAsync(socket.Information.RemoteHostName);
152 |
153 | writer = new DataWriter(socket.OutputStream);
154 | var reader = new DataReader(socket.InputStream);
155 | var remoteDisconnection = false;
156 |
157 | await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
158 | {
159 | Status.Text = "Connected to Client: " + remoteDevice.Name;
160 | });
161 |
162 | // Infinite read buffer loop
163 | while (true)
164 | {
165 | try
166 | {
167 | // Based on the protocol we've defined, the first uint is the size of the message
168 | uint readLength = await reader.LoadAsync(sizeof(uint));
169 |
170 | // Check if the size of the data is expected (otherwise the remote has already terminated the connection)
171 | if (readLength < sizeof(uint))
172 | {
173 | remoteDisconnection = true;
174 | break;
175 | }
176 | uint currentLength = reader.ReadUInt32();
177 |
178 | // Load the rest of the message since you already know the length of the data expected.
179 | readLength = await reader.LoadAsync(currentLength);
180 |
181 | // Check if the size of the data is expected (otherwise the remote has already terminated the connection)
182 | if (readLength < currentLength)
183 | {
184 | remoteDisconnection = true;
185 | break;
186 | }
187 | string message = reader.ReadString(currentLength);
188 |
189 | await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
190 | {
191 |
192 | switch (message)
193 | {
194 | case ("Walking"):
195 | mediaElement.Pause();
196 | mediaElement.Play();
197 | mediaElement.PlaybackRate = 1.0;
198 | break;
199 | case ("Running"):
200 | mediaElement.Pause();
201 | mediaElement.Play();
202 | mediaElement.PlaybackRate = 1.5;
203 | break;
204 | case ("Stationary"):
205 | mediaElement.Pause();
206 | break;
207 | default:
208 | mediaElement.Pause();
209 | break;
210 | }
211 |
212 | Status.Text = "Activity: " + message + "PlaybackRate= " + mediaElement.PlaybackRate;
213 | });
214 |
215 |
216 | }
217 | catch (Exception ex)
218 | {
219 | Status.Text = ex.Message + "Remote Disconnection: " + remoteDisconnection;
220 |
221 | }
222 | }
223 | }
224 |
225 | private void Disconnect()
226 | {
227 | if (rfcommProvider != null)
228 | {
229 | rfcommProvider.StopAdvertising();
230 | rfcommProvider = null;
231 | }
232 |
233 | if (socketListener != null)
234 | {
235 | socketListener.Dispose();
236 | socketListener = null;
237 | }
238 |
239 | if (writer != null)
240 | {
241 | writer.DetachStream();
242 | writer = null;
243 | }
244 |
245 | if (socket != null)
246 | {
247 | socket.Dispose();
248 | socket = null;
249 | }
250 | }
251 |
252 | private async void ChooseAvatar_Click(object sender, RoutedEventArgs e)
253 | {
254 | // Create and open the file picker
255 | FileOpenPicker openPicker = new FileOpenPicker();
256 | openPicker.ViewMode = PickerViewMode.Thumbnail;
257 | openPicker.SuggestedStartLocation = PickerLocationId.VideosLibrary;
258 | openPicker.FileTypeFilter.Add(".mp4");
259 | openPicker.FileTypeFilter.Add(".mkv");
260 | openPicker.FileTypeFilter.Add(".avi");
261 |
262 | StorageFile file = await openPicker.PickSingleFileAsync();
263 | if (file != null)
264 | {
265 | Status.Text = "Picked video: " + file.Name;
266 | mediaElement.SetPlaybackSource(MediaSource.CreateFromStorageFile(file));
267 | mediaElement.Play();
268 | }
269 | else
270 | {
271 | Status.Text = "Operation cancelled";
272 | }
273 | }
274 |
275 | int clickNum = 0;
276 | private void TogglePlayState_Click(object sender, RoutedEventArgs e)
277 | {
278 |
279 |
280 |
281 | switch (clickNum % 3)
282 | {
283 | case (0):
284 | mediaElement.Pause();
285 | mediaElement.Play();
286 | mediaElement.PlaybackRate = 1.0;
287 | break;
288 | case (1):
289 | mediaElement.Pause();
290 | mediaElement.Play();
291 | mediaElement.PlaybackRate = 2.0;
292 | break;
293 | case (2):
294 | mediaElement.Pause();
295 | break;
296 | default:
297 | mediaElement.Pause();
298 | break;
299 | }
300 |
301 | System.Diagnostics.Debug.WriteLine("PlayState: " + mediaElement.CurrentState + " PlaybackRate: " + mediaElement.PlaybackRate);
302 | clickNum += 1;
303 |
304 | }
305 | }
306 | }
307 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | BtAvatar
7 | kipathak
8 | Assets\StoreLogo.png
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("BtAvatar")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("BtAvatar")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtAvatar/BtAvatar/BtAvatar/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "Microsoft.ApplicationInsights": "1.0.0",
4 | "Microsoft.ApplicationInsights.PersistenceChannel": "1.0.0",
5 | "Microsoft.ApplicationInsights.WindowsApps": "1.0.0",
6 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
7 | },
8 | "frameworks": {
9 | "uap10.0": {}
10 | },
11 | "runtimes": {
12 | "win10-arm": {},
13 | "win10-arm-aot": {},
14 | "win10-x86": {},
15 | "win10-x86-aot": {},
16 | "win10-x64": {},
17 | "win10-x64-aot": {}
18 | }
19 | }
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.23107.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvatarSensor", "AvatarSensor\AvatarSensor.csproj", "{319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|ARM = Debug|ARM
11 | Debug|x64 = Debug|x64
12 | Debug|x86 = Debug|x86
13 | Release|ARM = Release|ARM
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Debug|ARM.ActiveCfg = Debug|ARM
19 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Debug|ARM.Build.0 = Debug|ARM
20 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Debug|ARM.Deploy.0 = Debug|ARM
21 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Debug|x64.ActiveCfg = Debug|x64
22 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Debug|x64.Build.0 = Debug|x64
23 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Debug|x64.Deploy.0 = Debug|x64
24 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Debug|x86.ActiveCfg = Debug|x86
25 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Debug|x86.Build.0 = Debug|x86
26 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Debug|x86.Deploy.0 = Debug|x86
27 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Release|ARM.ActiveCfg = Release|ARM
28 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Release|ARM.Build.0 = Release|ARM
29 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Release|ARM.Deploy.0 = Release|ARM
30 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Release|x64.ActiveCfg = Release|x64
31 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Release|x64.Build.0 = Release|x64
32 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Release|x64.Deploy.0 = Release|x64
33 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Release|x86.ActiveCfg = Release|x86
34 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Release|x86.Build.0 = Release|x86
35 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}.Release|x86.Deploy.0 = Release|x86
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.ApplicationModel;
7 | using Windows.ApplicationModel.Activation;
8 | using Windows.Foundation;
9 | using Windows.Foundation.Collections;
10 | using Windows.UI.Xaml;
11 | using Windows.UI.Xaml.Controls;
12 | using Windows.UI.Xaml.Controls.Primitives;
13 | using Windows.UI.Xaml.Data;
14 | using Windows.UI.Xaml.Input;
15 | using Windows.UI.Xaml.Media;
16 | using Windows.UI.Xaml.Navigation;
17 |
18 | namespace AvatarSensor
19 | {
20 | ///
21 | /// Provides application-specific behavior to supplement the default Application class.
22 | ///
23 | sealed partial class App : Application
24 | {
25 | ///
26 | /// Initializes the singleton application object. This is the first line of authored code
27 | /// executed, and as such is the logical equivalent of main() or WinMain().
28 | ///
29 | public App()
30 | {
31 | this.InitializeComponent();
32 | this.Suspending += OnSuspending;
33 | }
34 |
35 | ///
36 | /// Invoked when the application is launched normally by the end user. Other entry points
37 | /// will be used such as when the application is launched to open a specific file.
38 | ///
39 | /// Details about the launch request and process.
40 | protected override void OnLaunched(LaunchActivatedEventArgs e)
41 | {
42 |
43 | #if DEBUG
44 | if (System.Diagnostics.Debugger.IsAttached)
45 | {
46 | this.DebugSettings.EnableFrameRateCounter = true;
47 | }
48 | #endif
49 |
50 | Frame rootFrame = Window.Current.Content as Frame;
51 |
52 | // Do not repeat app initialization when the Window already has content,
53 | // just ensure that the window is active
54 | if (rootFrame == null)
55 | {
56 | // Create a Frame to act as the navigation context and navigate to the first page
57 | rootFrame = new Frame();
58 |
59 | rootFrame.NavigationFailed += OnNavigationFailed;
60 |
61 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
62 | {
63 | //TODO: Load state from previously suspended application
64 | }
65 |
66 | // Place the frame in the current Window
67 | Window.Current.Content = rootFrame;
68 | }
69 |
70 | if (rootFrame.Content == null)
71 | {
72 | // When the navigation stack isn't restored navigate to the first page,
73 | // configuring the new page by passing required information as a navigation
74 | // parameter
75 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
76 | }
77 | // Ensure the current window is active
78 | Window.Current.Activate();
79 | }
80 |
81 | ///
82 | /// Invoked when Navigation to a certain page fails
83 | ///
84 | /// The Frame which failed navigation
85 | /// Details about the navigation failure
86 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
87 | {
88 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
89 | }
90 |
91 | ///
92 | /// Invoked when application execution is being suspended. Application state is saved
93 | /// without knowing whether the application will be terminated or resumed with the contents
94 | /// of memory still intact.
95 | ///
96 | /// The source of the suspend request.
97 | /// Details about the suspend request.
98 | private void OnSuspending(object sender, SuspendingEventArgs e)
99 | {
100 | var deferral = e.SuspendingOperation.GetDeferral();
101 | //TODO: Save application state and stop any background activity
102 | deferral.Complete();
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtSensor/AvatarSensor/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtSensor/AvatarSensor/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtSensor/AvatarSensor/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtSensor/AvatarSensor/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtSensor/AvatarSensor/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtSensor/AvatarSensor/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/BuildQuickStart/BtSensor/AvatarSensor/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/AvatarSensor.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {319DE1AE-5A37-4DF9-B0B6-CFFD287438EA}
8 | AppContainerExe
9 | Properties
10 | AvatarSensor
11 | AvatarSensor
12 | en-US
13 | UAP
14 | 10.0.14267.0
15 | 10.0.14257.0
16 | 14
17 | true
18 | 512
19 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
20 | AvatarSensor_TemporaryKey.pfx
21 |
22 |
23 | true
24 | bin\ARM\Debug\
25 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
26 | ;2008
27 | full
28 | ARM
29 | false
30 | prompt
31 | true
32 |
33 |
34 | bin\ARM\Release\
35 | TRACE;NETFX_CORE;WINDOWS_UWP
36 | true
37 | ;2008
38 | pdbonly
39 | ARM
40 | false
41 | prompt
42 | true
43 | true
44 |
45 |
46 | true
47 | bin\x64\Debug\
48 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
49 | ;2008
50 | full
51 | x64
52 | false
53 | prompt
54 | true
55 |
56 |
57 | bin\x64\Release\
58 | TRACE;NETFX_CORE;WINDOWS_UWP
59 | true
60 | ;2008
61 | pdbonly
62 | x64
63 | false
64 | prompt
65 | true
66 | true
67 |
68 |
69 | true
70 | bin\x86\Debug\
71 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
72 | ;2008
73 | full
74 | x86
75 | false
76 | prompt
77 | true
78 |
79 |
80 | bin\x86\Release\
81 | TRACE;NETFX_CORE;WINDOWS_UWP
82 | true
83 | ;2008
84 | pdbonly
85 | x86
86 | false
87 | prompt
88 | true
89 | true
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | App.xaml
98 |
99 |
100 | MainPage.xaml
101 |
102 |
103 |
104 |
105 |
106 | Designer
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | MSBuild:Compile
122 | Designer
123 |
124 |
125 | MSBuild:Compile
126 | Designer
127 |
128 |
129 |
130 | 14.0
131 |
132 |
133 |
140 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Windows.Foundation;
3 | using Windows.UI.Xaml;
4 | using Windows.UI.Xaml.Controls;
5 |
6 | using Windows.Devices.Bluetooth;
7 | using Windows.Devices.Bluetooth.Rfcomm;
8 | using Windows.Devices.Sensors;
9 | using Windows.Devices.Enumeration;
10 | using Windows.Networking.Sockets;
11 | using Windows.Storage.Streams;
12 | using System.ComponentModel;
13 | using System.Collections.ObjectModel;
14 | using Windows.UI.Core;
15 | // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
16 |
17 | namespace AvatarSensor
18 | {
19 | ///
20 | /// An empty page that can be used on its own or navigated to within a Frame.
21 | ///
22 | public sealed partial class MainPage : Page
23 | {
24 | private DeviceWatcher deviceWatcher;
25 | private StreamSocket chatSocket;
26 | private DataWriter chatWriter;
27 | private RfcommDeviceService chatService;
28 |
29 | // Common class ID for activity sensors
30 | Guid ActivitySensorClassId = new Guid("9D9E0118-1807-4F2E-96E4-2CE57142E196");
31 | private ActivitySensor activitySensor;
32 | private readonly Guid avatarServiceUUID = Guid.Parse("87bf52c0-4595-43b3-a5b0-702de8d5dbba");
33 |
34 | // Used to display list of available devices to chat with
35 | public ObservableCollection ResultCollection
36 | {
37 | get;
38 | private set;
39 | }
40 |
41 | public MainPage()
42 | {
43 | this.InitializeComponent();
44 |
45 | ResultCollection = new ObservableCollection();
46 | DataContext = this;
47 | }
48 |
49 | private void RunButton_Click(object sender, RoutedEventArgs e)
50 | {
51 | Status.Text = "Looking for nearby devices";
52 |
53 | deviceWatcher = DeviceInformation.CreateWatcher(BluetoothDevice.GetDeviceSelectorFromPairingState(false), null);
54 | // Hook up handlers for the watcher events before starting the watcher
55 | deviceWatcher.Added += new TypedEventHandler(async (watcher, deviceInfo) =>
56 | {
57 | await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
58 | {
59 | // Make sure device name isn't blank
60 | if (deviceInfo.Name != "")
61 | {
62 | ResultCollection.Add(new AvatarDeviceDisplay(deviceInfo));
63 | System.Diagnostics.Debug.WriteLine(resultsListView.Items.Count);
64 |
65 | }
66 |
67 | });
68 | });
69 |
70 | deviceWatcher.Updated += new TypedEventHandler(async (watcher, deviceInfoUpdate) =>
71 | {
72 | await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
73 | {
74 | foreach (AvatarDeviceDisplay avatarInfoDisp in ResultCollection)
75 | {
76 | if (avatarInfoDisp.Id == deviceInfoUpdate.Id)
77 | {
78 | avatarInfoDisp.Update(deviceInfoUpdate);
79 | break;
80 | }
81 | }
82 | });
83 | });
84 |
85 | deviceWatcher.EnumerationCompleted += new TypedEventHandler((watcher, obj) =>
86 | {
87 |
88 | });
89 |
90 | deviceWatcher.Removed += new TypedEventHandler(async (watcher, deviceInfoUpdate) =>
91 | {
92 | await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
93 | {
94 | // Find the corresponding DeviceInformation in the collection and remove it
95 | foreach (AvatarDeviceDisplay avatarInfoDisp in ResultCollection)
96 | {
97 | if (avatarInfoDisp.Id == deviceInfoUpdate.Id)
98 | {
99 | ResultCollection.Remove(avatarInfoDisp);
100 | break;
101 | }
102 | }
103 | });
104 | });
105 |
106 | deviceWatcher.Stopped += new TypedEventHandler(async (watcher, obj) =>
107 | {
108 | await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
109 | {
110 | // Find the corresponding DeviceInformation in the collection and remove it
111 | ResultCollection.Clear();
112 | Status.Text = "Watcher Stopped";
113 | RunButton.IsEnabled = true;
114 | });
115 |
116 | });
117 |
118 | deviceWatcher.Start();
119 | }
120 |
121 | private async void ConnectButton_Click(object sender, RoutedEventArgs e)
122 | {
123 |
124 | AvatarDeviceDisplay deviceInfoDisp = resultsListView.SelectedItem as AvatarDeviceDisplay;
125 |
126 |
127 | var bluetoothDevice = await BluetoothDevice.FromIdAsync(deviceInfoDisp.Id); ;
128 |
129 | var rfcommServices = await bluetoothDevice.GetRfcommServicesForIdAsync(
130 | RfcommServiceId.FromUuid(avatarServiceUUID), BluetoothCacheMode.Uncached);
131 |
132 | if (rfcommServices.Services.Count > 0)
133 | {
134 | chatService = rfcommServices.Services[0];
135 | }
136 | else
137 | {
138 | Status.Text = "Could not discover the avatar service on the remote device";
139 | return;
140 | }
141 |
142 | deviceWatcher.Stop();
143 |
144 |
145 |
146 | lock (this)
147 | {
148 | chatSocket = new StreamSocket();
149 | }
150 | try
151 | {
152 | await chatSocket.ConnectAsync(chatService.ConnectionHostName, chatService.ConnectionServiceName);
153 |
154 | chatWriter = new DataWriter(chatSocket.OutputStream);
155 |
156 | EnableActivityDetectionAsync();
157 | }
158 | catch (Exception ex)
159 | {
160 | switch ((uint)ex.HResult)
161 | {
162 | case (0x80070490): // ERROR_ELEMENT_NOT_FOUND
163 | Status.Text = "Please verify that you are running the Avatar server.";
164 | RunButton.IsEnabled = true;
165 | break;
166 | default:
167 | throw;
168 | }
169 | }
170 |
171 | }
172 |
173 | private async void EnableActivityDetectionAsync()
174 | {
175 | var deviceAccessInfo = DeviceAccessInformation.CreateFromDeviceClassId(ActivitySensorClassId);
176 | // Determine if we can access activity sensors
177 | if (deviceAccessInfo.CurrentStatus == DeviceAccessStatus.Allowed)
178 | {
179 | if (activitySensor == null)
180 | {
181 | activitySensor = await ActivitySensor.GetDefaultAsync();
182 | }
183 |
184 | if (activitySensor != null)
185 | {
186 | activitySensor.SubscribedActivities.Add(ActivityType.Walking);
187 | activitySensor.SubscribedActivities.Add(ActivityType.Running);
188 | activitySensor.SubscribedActivities.Add(ActivityType.Fidgeting);
189 | activitySensor.SubscribedActivities.Add(ActivityType.Stationary);
190 |
191 |
192 | activitySensor.ReadingChanged += new TypedEventHandler(ReadingChanged);
193 |
194 | Status.Text = "Subscribed to reading changes";
195 | }
196 | else
197 | {
198 | Status.Text = "No activity sensor found";
199 | }
200 | }
201 | else
202 | {
203 | Status.Text = "Access denied to activity sensors";
204 | }
205 | }
206 |
207 | private void DisableActivityDetection()
208 | {
209 | if (activitySensor != null)
210 | {
211 | activitySensor.ReadingChanged -= new TypedEventHandler(ReadingChanged);
212 | Status.Text = "Unsubscribed from reading changes";
213 | }
214 | }
215 | private async void ReadingChanged(ActivitySensor sender, ActivitySensorReadingChangedEventArgs args)
216 | {
217 | await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
218 | {
219 | ActivitySensorReading reading = args.Reading;
220 |
221 | SendMessage(reading.Activity.ToString());
222 | });
223 | }
224 |
225 | private async void SendMessage(string message)
226 | {
227 | try
228 | {
229 | if (message.Length != 0)
230 | {
231 | chatWriter.WriteUInt32((uint)message.Length);
232 | chatWriter.WriteString(message);
233 |
234 | Status.Text = message;
235 | await chatWriter.StoreAsync();
236 |
237 | }
238 | }
239 | catch (Exception ex)
240 | {
241 | Status.Text = "Error: " + ex.HResult.ToString() + " - " + ex.Message;
242 | }
243 | }
244 |
245 | int clickNum = 0;
246 | private void MessageToggle_Click(object sender, RoutedEventArgs e)
247 | {
248 | switch (clickNum % 3)
249 | {
250 | case (0):
251 | SendMessage("Walking");
252 | break;
253 | case (1):
254 | SendMessage("Running");
255 | break;
256 | case (2):
257 | SendMessage("Stationary");
258 | break;
259 | default:
260 | SendMessage("Car");
261 | break;
262 | }
263 |
264 | System.Diagnostics.Debug.WriteLine("Message sent: " + clickNum);
265 | clickNum += 1;
266 | }
267 | }
268 |
269 | public class AvatarDeviceDisplay : INotifyPropertyChanged
270 | {
271 | private DeviceInformation deviceInfo;
272 |
273 | public AvatarDeviceDisplay(DeviceInformation deviceInfoIn)
274 | {
275 | deviceInfo = deviceInfoIn;
276 | }
277 |
278 | public DeviceInformation DeviceInformation
279 | {
280 | get
281 | {
282 | return deviceInfo;
283 | }
284 |
285 | private set
286 | {
287 | deviceInfo = value;
288 | }
289 | }
290 |
291 | public string Id
292 | {
293 | get
294 | {
295 | return deviceInfo.Id;
296 | }
297 | }
298 |
299 | public string Name
300 | {
301 | get
302 | {
303 | return deviceInfo.Name;
304 | }
305 | }
306 |
307 | public void Update(DeviceInformationUpdate deviceInfoUpdate)
308 | {
309 | deviceInfo.Update(deviceInfoUpdate);
310 | }
311 |
312 |
313 | public event PropertyChangedEventHandler PropertyChanged;
314 | protected void OnPropertyChanged(string name)
315 | {
316 | PropertyChangedEventHandler handler = PropertyChanged;
317 | if (handler != null)
318 | {
319 | handler(this, new PropertyChangedEventArgs(name));
320 | }
321 | }
322 |
323 | }
324 | }
325 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 |
16 |
17 | AvatarSensor
18 | kipathak
19 | Assets\StoreLogo.png
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("AvatarSensor")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("AvatarSensor")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/BuildQuickStart/BtSensor/AvatarSensor/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
4 | },
5 | "frameworks": {
6 | "uap10.0": {}
7 | },
8 | "runtimes": {
9 | "win10-arm": {},
10 | "win10-arm-aot": {},
11 | "win10-x86": {},
12 | "win10-x86-aot": {},
13 | "win10-x64": {},
14 | "win10-x64-aot": {}
15 | }
16 | }
--------------------------------------------------------------------------------
/BuildQuickStart/README.md:
--------------------------------------------------------------------------------
1 | # Bluetooth quick start sample code
2 |
3 | ## Run the sample
4 |
5 | The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
6 |
7 | - BtAvatar should be deployed on a PC or larger screen device
8 | - BtSensor should be deployed on a phone that supports activity detection (currently only the Lumia 950 and 950 XL)
9 |
10 | ### Deploying the sample
11 |
12 | - Select Build > Deploy Solution.
13 |
14 | ### Deploying and running the sample
15 |
16 | - To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging.
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Build2016BluetoothCodeSamples
2 | Code samples for Bluetooth @ Build 2016. The code here is discussed in the following videos:
3 |
4 | [Bluetooth Device Companion apps](https://channel9.msdn.com/Events/Build/2016/P415)
5 |
6 | [Intro to Bluetooth Background Communication](https://channel9.msdn.com/Events/Build/2016/P460)
7 |
8 | [Beyond Beacons](https://channel9.msdn.com/Events/Build/2016/P416)
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/SharedContent/cs/App.xaml.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************
2 | //
3 | // Copyright (c) Microsoft. All rights reserved.
4 | // This code is licensed under the MIT License (MIT).
5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
9 | //
10 | //*********************************************************
11 |
12 | using System;
13 | using Windows.ApplicationModel;
14 | using Windows.ApplicationModel.Activation;
15 | using Windows.UI.Xaml;
16 | using Windows.UI.Xaml.Controls;
17 | using Windows.UI.Xaml.Navigation;
18 |
19 | // The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=402347&clcid=0x409
20 |
21 | namespace SDKTemplate
22 | {
23 | ///
24 | /// Provides application-specific behavior to supplement the default Application class.
25 | ///
26 | sealed partial class App : Application
27 | {
28 | ///
29 | /// Initializes the singleton application object. This is the first line of authored code
30 | /// executed, and as such is the logical equivalent of main() or WinMain().
31 | ///
32 | public App()
33 | {
34 | this.InitializeComponent();
35 | this.Construct();
36 | }
37 |
38 | ///
39 | /// Invoked when the application is launched normally by the end user. Other entry points
40 | /// will be used such as when the application is launched to open a specific file.
41 | ///
42 | /// Details about the launch request and process.
43 | protected override void OnLaunched(LaunchActivatedEventArgs e)
44 | {
45 |
46 | #if DEBUG
47 | if (System.Diagnostics.Debugger.IsAttached)
48 | {
49 | this.DebugSettings.EnableFrameRateCounter = false;
50 | }
51 | #endif
52 |
53 | Frame rootFrame = Window.Current.Content as Frame;
54 |
55 | // Do not repeat app initialization when the Window already has content,
56 | // just ensure that the window is active
57 | if (rootFrame == null)
58 | {
59 | // Create a Frame to act as the navigation context and navigate to the first page
60 | rootFrame = new Frame();
61 | // Set the default language
62 | rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];
63 |
64 | rootFrame.NavigationFailed += OnNavigationFailed;
65 |
66 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
67 | {
68 | //TODO: Load state from previously suspended application
69 | }
70 |
71 | // Place the frame in the current Window
72 | Window.Current.Content = rootFrame;
73 | }
74 |
75 | if (rootFrame.Content == null)
76 | {
77 | // When the navigation stack isn't restored navigate to the first page,
78 | // configuring the new page by passing required information as a navigation
79 | // parameter
80 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
81 | }
82 | // Ensure the current window is active
83 | Window.Current.Activate();
84 | }
85 |
86 | private Frame CreateRootFrame()
87 | {
88 | Frame rootFrame = Window.Current.Content as Frame;
89 |
90 | // Do not repeat app initialization when the Window already has content,
91 | // just ensure that the window is active
92 | if (rootFrame == null)
93 | {
94 | // Create a Frame to act as the navigation context and navigate to the first page
95 | rootFrame = new Frame();
96 |
97 | // Set the default language
98 | rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];
99 | rootFrame.NavigationFailed += OnNavigationFailed;
100 |
101 | // Place the frame in the current Window
102 | Window.Current.Content = rootFrame;
103 | }
104 |
105 | return rootFrame;
106 | }
107 |
108 | ///
109 | /// Invoked when Navigation to a certain page fails
110 | ///
111 | /// The Frame which failed navigation
112 | /// Details about the navigation failure
113 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
114 | {
115 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
116 | }
117 |
118 | // Add any application contructor code in here.
119 | partial void Construct();
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/SharedContent/cs/AssemblyInfo.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/SharedContent/cs/AssemblyInfo.cs
--------------------------------------------------------------------------------
/SharedContent/cs/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/SharedContent/cs/Library.rd.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/SharedContent/cs/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
13 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
50 |
51 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/SharedContent/cs/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************
2 | //
3 | // Copyright (c) Microsoft. All rights reserved.
4 | // This code is licensed under the MIT License (MIT).
5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
9 | //
10 | //*********************************************************
11 |
12 | using System;
13 | using System.Collections.Generic;
14 | using Windows.UI.Xaml;
15 | using Windows.UI.Xaml.Controls;
16 | using Windows.UI.Xaml.Data;
17 | using Windows.UI.Xaml.Media;
18 | using Windows.UI.Xaml.Navigation;
19 |
20 | // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
21 |
22 | namespace SDKTemplate
23 | {
24 | ///
25 | /// An empty page that can be used on its own or navigated to within a Frame.
26 | ///
27 | public sealed partial class MainPage : Page
28 | {
29 | public static MainPage Current;
30 |
31 | public MainPage()
32 | {
33 | this.InitializeComponent();
34 |
35 | // This is a static public property that allows downstream pages to get a handle to the MainPage instance
36 | // in order to call methods that are in this class.
37 | Current = this;
38 | SampleTitle.Text = FEATURE_NAME;
39 | }
40 |
41 | protected override void OnNavigatedTo(NavigationEventArgs e)
42 | {
43 | // Populate the scenario list from the SampleConfiguration.cs file
44 | ScenarioControl.ItemsSource = scenarios;
45 | if (Window.Current.Bounds.Width < 640)
46 | {
47 | ScenarioControl.SelectedIndex = -1;
48 | }
49 | else
50 | {
51 | ScenarioControl.SelectedIndex = 0;
52 | }
53 | }
54 |
55 | ///
56 | /// Called whenever the user changes selection in the scenarios list. This method will navigate to the respective
57 | /// sample scenario page.
58 | ///
59 | ///
60 | ///
61 | private void ScenarioControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
62 | {
63 | // Clear the status block when navigating scenarios.
64 | NotifyUser(String.Empty, NotifyType.StatusMessage);
65 |
66 | ListBox scenarioListBox = sender as ListBox;
67 | Scenario s = scenarioListBox.SelectedItem as Scenario;
68 | if (s != null)
69 | {
70 | ScenarioFrame.Navigate(s.ClassType);
71 | if (Window.Current.Bounds.Width < 640)
72 | {
73 | Splitter.IsPaneOpen = false;
74 | }
75 | }
76 | }
77 |
78 | public List Scenarios
79 | {
80 | get { return this.scenarios; }
81 | }
82 |
83 | ///
84 | /// Used to display messages to the user
85 | ///
86 | ///
87 | ///
88 | public void NotifyUser(string strMessage, NotifyType type)
89 | {
90 | switch (type)
91 | {
92 | case NotifyType.StatusMessage:
93 | StatusBorder.Background = new SolidColorBrush(Windows.UI.Colors.Green);
94 | break;
95 | case NotifyType.ErrorMessage:
96 | StatusBorder.Background = new SolidColorBrush(Windows.UI.Colors.Red);
97 | break;
98 | }
99 | StatusBlock.Text = strMessage;
100 |
101 | // Collapse the StatusBlock if it has no text to conserve real estate.
102 | StatusBorder.Visibility = (StatusBlock.Text != String.Empty) ? Visibility.Visible : Visibility.Collapsed;
103 | if (StatusBlock.Text != String.Empty)
104 | {
105 | StatusBorder.Visibility = Visibility.Visible;
106 | StatusPanel.Visibility = Visibility.Visible;
107 | }
108 | else
109 | {
110 | StatusBorder.Visibility = Visibility.Collapsed;
111 | StatusPanel.Visibility = Visibility.Collapsed;
112 | }
113 | }
114 |
115 | async void Footer_Click(object sender, RoutedEventArgs e)
116 | {
117 | await Windows.System.Launcher.LaunchUriAsync(new Uri(((HyperlinkButton)sender).Tag.ToString()));
118 | }
119 |
120 | private void Button_Click(object sender, RoutedEventArgs e)
121 | {
122 | Splitter.IsPaneOpen = !Splitter.IsPaneOpen;
123 | }
124 | }
125 | public enum NotifyType
126 | {
127 | StatusMessage,
128 | ErrorMessage
129 | };
130 |
131 | public class ScenarioBindingConverter : IValueConverter
132 | {
133 | public object Convert(object value, Type targetType, object parameter, string language)
134 | {
135 | Scenario s = value as Scenario;
136 | return (MainPage.Current.Scenarios.IndexOf(s) + 1) + ") " + s.Title;
137 | }
138 |
139 | public object ConvertBack(object value, Type targetType, object parameter, string language)
140 | {
141 | return true;
142 | }
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/SharedContent/media/microsoft-sdk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/SharedContent/media/microsoft-sdk.png
--------------------------------------------------------------------------------
/SharedContent/media/placeholder-sdk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/SharedContent/media/placeholder-sdk.png
--------------------------------------------------------------------------------
/SharedContent/media/smalltile-sdk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/SharedContent/media/smalltile-sdk.png
--------------------------------------------------------------------------------
/SharedContent/media/splash-sdk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/SharedContent/media/splash-sdk.png
--------------------------------------------------------------------------------
/SharedContent/media/squaretile-sdk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/SharedContent/media/squaretile-sdk.png
--------------------------------------------------------------------------------
/SharedContent/media/storelogo-sdk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/SharedContent/media/storelogo-sdk.png
--------------------------------------------------------------------------------
/SharedContent/media/storelogo-sdk.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/SharedContent/media/storelogo-sdk.scale-100.png
--------------------------------------------------------------------------------
/SharedContent/media/tile-sdk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/SharedContent/media/tile-sdk.png
--------------------------------------------------------------------------------
/SharedContent/media/windows-sdk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kpathakota/Build2016BluetoothCodeSamples/350d6931c67e86ca2e1e4ebe7f1190dca36b100a/SharedContent/media/windows-sdk.png
--------------------------------------------------------------------------------
/SharedContent/xaml/App.xaml:
--------------------------------------------------------------------------------
1 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/SharedContent/xaml/Styles.xaml:
--------------------------------------------------------------------------------
1 |
13 |
17 |
18 |
119 |
120 |
124 |
125 |
130 |
131 |
136 |
137 |
145 |
146 |
149 |
150 |
155 |
156 |
161 |
162 |
168 |
169 |
174 |
175 |
179 |
180 |
181 |
343 |
344 |
345 |
404 |
405 |
406 |
--------------------------------------------------------------------------------