├── OpenWindesheart
├── Properties
│ └── launchSettings.json
├── Exceptions
│ ├── ReadException.cs
│ ├── BatteryException.cs
│ └── ConnectionException.cs
├── Models
│ ├── HeartrateData.cs
│ ├── BLEScanResult.cs
│ ├── BatteryData.cs
│ ├── StepData.cs
│ └── ActivitySample.cs
├── OpenWindesheart.csproj
├── OpenWindesheart.sln
├── Devices
│ └── MiBand3
│ │ ├── Services
│ │ ├── MiBand3DateTimeService.cs
│ │ ├── MiBand3HeartrateService.cs
│ │ ├── MiBand3StepsService.cs
│ │ ├── MiBand3BatteryService.cs
│ │ ├── MiBand3AuthenticationService.cs
│ │ ├── MiBand3ConfigurationService.cs
│ │ └── MiBand3SampleService.cs
│ │ ├── Helpers
│ │ └── MiBand3ConversionHelper.cs
│ │ ├── Resources
│ │ └── MiBand3Resource.cs
│ │ └── Models
│ │ └── MiBand3.cs
├── Windesheart.cs
├── Helpers
│ └── ConversionHelper.cs
├── BLEDevice.cs
└── Services
│ └── BluetoothService.cs
├── README-Scanning.md
├── README-Readingdata.md
├── README-Connecting.md
├── README-SupportNewDevice.md
├── README-Settings.md
├── README-Samples.md
├── README.md
├── .gitignore
└── LICENSE.md
/OpenWindesheart/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "OpenWindesheart": {
4 | "commandName": "Project",
5 | "nativeDebugging": true
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/OpenWindesheart/Exceptions/ReadException.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using System;
16 |
17 | namespace OpenWindesheart.Exceptions
18 | {
19 | class ReadException : Exception
20 | {
21 | public ReadException() { }
22 |
23 | public ReadException(string message) : base(message) { }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/OpenWindesheart/Exceptions/BatteryException.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using System;
16 |
17 | namespace OpenWindesheart.Exceptions
18 | {
19 | public class BatteryException : Exception
20 | {
21 | public BatteryException() { }
22 |
23 | public BatteryException(string message) : base(message) { }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/OpenWindesheart/Exceptions/ConnectionException.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using System;
16 |
17 | namespace OpenWindesheart.Exceptions
18 | {
19 | public class ConnectionException : Exception
20 | {
21 | public ConnectionException() { }
22 |
23 | public ConnectionException(string message) : base(message) { }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/OpenWindesheart/Models/HeartrateData.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using OpenWindesheart.Exceptions;
16 |
17 | namespace OpenWindesheart.Models
18 | {
19 | public class HeartrateData
20 | {
21 | public byte[] Rawdata { get; }
22 |
23 | public int Heartrate { get; }
24 |
25 | public HeartrateData(byte[] rawdata)
26 | {
27 | Rawdata = rawdata;
28 | Heartrate = rawdata[1];
29 | }
30 | }
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/OpenWindesheart/OpenWindesheart.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.1
5 | true
6 | 2.0.3
7 | K. van Sloten, R. Abächerli, H. van der Gugten, T.C. Marschalk
8 | Research group ICT innovations in Health Care - Windesheim University of Applied Sciences
9 | The open-source OpenWindesheart is an SDK used for scanning, connecting and getting data from activity-trackers using bluetooth.
10 | Current support: - Mi Band 3 -
11 | Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
12 | https://github.com/ictinnovaties-zorg/openwindesheart
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/OpenWindesheart/OpenWindesheart.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29424.173
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenWindesheart", "OpenWindesheart.csproj", "{804BBA3E-3027-45D6-8384-E806A51E504A}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {804BBA3E-3027-45D6-8384-E806A51E504A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {804BBA3E-3027-45D6-8384-E806A51E504A}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {804BBA3E-3027-45D6-8384-E806A51E504A}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {804BBA3E-3027-45D6-8384-E806A51E504A}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {5A250640-D341-4F92-B01F-666E9FB58489}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/OpenWindesheart/Models/BLEScanResult.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using Plugin.BluetoothLE;
16 |
17 | namespace OpenWindesheart.Models
18 | {
19 | public class BLEScanResult
20 | {
21 | public BLEDevice Device { get; }
22 | public int Rssi { get; }
23 | public IAdvertisementData AdvertisementData { get; }
24 |
25 | public BLEScanResult(BLEDevice device, int rssi, IAdvertisementData advertisementData)
26 | {
27 | Device = device;
28 | Rssi = rssi;
29 | AdvertisementData = advertisementData;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/OpenWindesheart/Models/BatteryData.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | namespace OpenWindesheart.Models
16 | {
17 | public enum BatteryStatus
18 | {
19 | Charging,
20 | NotCharging
21 | }
22 |
23 | public class BatteryData
24 | {
25 | public BatteryStatus Status
26 | {
27 | get;
28 | set;
29 | }
30 |
31 | public int Percentage
32 | {
33 | get;
34 | set;
35 | }
36 |
37 | public byte[] RawData
38 | {
39 | get;
40 | set;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/OpenWindesheart/Models/StepData.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using OpenWindesheart.Helpers;
16 |
17 | namespace OpenWindesheart.Models
18 | {
19 | public class StepData
20 | {
21 | public StepData()
22 | {
23 |
24 | }
25 |
26 | public StepData(byte[] rawData)
27 | {
28 | RawData = rawData;
29 | byte[] stepsValue = new byte[] { RawData[1], RawData[2] };
30 | StepCount = ConversionHelper.ToUint16(stepsValue);
31 | }
32 |
33 | public byte[] RawData { get; }
34 | public int StepCount { get; }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/README-Scanning.md:
--------------------------------------------------------------------------------
1 |
2 | # Scanning
3 |
4 | Scanning allows the user to scan for BLEDevices.
5 |
6 | ### Windesheart.StartScanning(Callback)
7 | This method starts the scanning progress and calls the provided callback method when a BLEDevice is found. It returns a boolean to indicate whether scanning has started. An example:
8 |
9 |
10 |
11 | ```csharp
12 | public void Main(){
13 | if(Windesheart.StartScanning(WhenDeviceFound)){
14 | Console.WriteLine("Scanning started!");
15 | }
16 | else
17 | {
18 | Console.WriteLine("Couldn't start scanning. Is Bluetooth turned on?");
19 | }
20 | }
21 |
22 | public void WhenDeviceFound(BLEScanResult result){
23 | Console.WriteLine("Device found!");
24 | BLEDevice device = result.device;
25 | int Rssi = result.Rssi;
26 | AdvertisementData data = result.AdvertismentData;
27 | }
28 | ```
29 | As you can see in `WhenDeviceFound`, a BLEScanResult parameter is given. This parameter contains the device itself, the initial Rssi of the device, and the AdvertisementData for that device.
30 |
31 | When using this method, be sure to call the `Windesheart.StopScanning()` method at some point as well, otherwise your device will continue scanning indefinitely.
32 |
33 | ### Windesheart.StopScanning()
34 | This method stops the scanning process. This is a void method. You can assume that this method always succeeds.
35 | ```csharp
36 | Windesheart.StartScanning(WhenDeviceFound); //Start scanning
37 | await Task.Delay(2000); //Wait 2 seconds
38 | Windesheart.StopScanning(); //Stop scanning
39 | ```
40 |
41 | [<---- Back to mainpage](https://github.com/ictinnovaties-zorg/openwindesheart/blob/master/)
--------------------------------------------------------------------------------
/OpenWindesheart/Models/ActivitySample.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using System;
16 |
17 | namespace OpenWindesheart.Models
18 | {
19 | public class ActivitySample
20 | {
21 | public byte[] RawData { get; }
22 | public DateTime Timestamp { get; }
23 | public int UnixEpochTimestamp { get; }
24 | public int Category { get; }
25 | public int RawIntensity { get; }
26 | public int Steps { get; }
27 | public int HeartRate { get; }
28 |
29 | public ActivitySample(DateTime timestamp, int category, int intensity, int steps, int heartrate, byte[] rawdata = null)
30 | {
31 | this.RawData = rawdata;
32 | this.Timestamp = timestamp;
33 | this.UnixEpochTimestamp = (Int32)(timestamp.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
34 | this.Category = category;
35 | this.RawIntensity = intensity;
36 | this.Steps = steps;
37 | this.HeartRate = heartrate;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/OpenWindesheart/Devices/MiBand3/Services/MiBand3DateTimeService.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using System;
16 | using System.Reactive.Linq;
17 | using OpenWindesheart.Devices.MiBand3Device.Models;
18 | using OpenWindesheart.Devices.MiBand3Device.Resources;
19 | using OpenWindesheart.Helpers;
20 |
21 | namespace OpenWindesheart.Devices.MiBand3Device.Services
22 | {
23 | public class MiBand3DateTimeService
24 | {
25 | private readonly MiBand3 _miBand3;
26 |
27 | public MiBand3DateTimeService(MiBand3 device)
28 | {
29 | _miBand3 = device;
30 | }
31 |
32 | public void SetTime(DateTime time)
33 | {
34 | //Convert time to bytes
35 | byte[] timeToSet = ConversionHelper.GetTimeBytes(time, ConversionHelper.TimeUnit.Seconds);
36 |
37 | //Send to MiBand
38 | _miBand3.GetCharacteristic(MiBand3Resource.GuidCurrentTime).Write(timeToSet).Subscribe(result =>
39 | {
40 | Console.WriteLine("Time set to " + time.ToString());
41 | });
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/README-Readingdata.md:
--------------------------------------------------------------------------------
1 | # Reading data
2 | The Windesheart SDK allows reading data from BLE Devices.
3 |
4 |
5 | ## Reading current data
6 | The data that can be read at the moment is:
7 |
8 | * Battery data by using `BLEDevice.GetBattery()`
9 | * Steps by using `BLEDevice.GetSteps()`
10 |
11 | Please note that all of this is **current** data. If you want data of the past, you have to get the samples of your BLE Device.
12 |
13 | **Example**
14 |
15 | ```csharp
16 | BLEDevice device = // your device
17 | StepData steps = device.GetSteps();
18 | int stepCount = steps.StepCount;
19 |
20 | BatteryData battery= device.GetBattery();
21 | BatteryStatus status = battery.Status; //Either Charging or NotCharging
22 | int percentage = battery.Percentage;
23 | ```
24 |
25 |
26 | ## Real time data
27 | There is also an option to continuously get data from your device. This works by providing a callback method that will be run when the data has been updated.
28 |
29 | This works with:
30 |
31 | - Steps by using `BLEDevice.EnableRealTimeSteps(StepData)`
32 | - Battery by using `BLEDevice.EnableRealTimeBattery(BatteryData)`
33 | - Heart rate by using `BLEDevice.EnableRealTimeHeartrate(HeartrateData)`
34 |
35 | **Example**
36 | Let's say we want to continuously get the steps of the device for a period of 1 minute, then we could do this:
37 |
38 | ```csharp
39 |
40 | async void Main(){
41 | device.EnableRealTimeSteps(onStepsUpdated);
42 | await Task.Delay(60000);
43 | device.DisableRealTimeSteps(); //Don't forget to disable when not needed anymore!
44 | }
45 |
46 | void OnStepsUpdated(StepData data){
47 | int steps = data.StepCount;
48 | Console.WriteLine("Steps updated: " + steps);
49 | }
50 | ```
51 | [<---- Back to mainpage](https://github.com/ictinnovaties-zorg/openwindesheart/blob/master/)
52 |
--------------------------------------------------------------------------------
/README-Connecting.md:
--------------------------------------------------------------------------------
1 | # Connecting
2 | This documentation explains and demonstrates how to connect with a Bluetooth device. You should have access to the device itself by scanning for it. If you haven't, please take a look at the scanning docs.
3 |
4 | **Please note:** The SDK only supports one device to be connected at a time.
5 |
6 | ## BLEDevice.Connect(callback, secretkey)
7 | This method attempts to connect with your device. The callback parameter will be called when the connection process has finished. **This doesn't mean that it's always successful!**
8 | The callback returns a `ConnectionResult` enum. This enum can be either `Succeeded`, or `Failed`.
9 |
10 | You can also give this method the secretkey of the device you're trying to connect with. If you don't give a key to the connect method, It will generate a new key. This key will be returned in the connection callback. It is important you save this key. The next time you want to connect to this device you'll need use this key with the connect method. This is needed to reconnect without losing data!
11 |
12 | Example:
13 | ```
14 | BLEDevice device = //Retrieved from scanning
15 | device.Connect(OnConnectionFinished);
16 | ```
17 | ```csharp
18 | //Our scanning callback method
19 | void OnDeviceFound(BLEScanResult result){
20 | BLEDevice device = result.Device;
21 | //let's first stop scanning
22 | Windesheart.StopScanning();
23 | //Then, connect to device
24 | device.Connect(OnConnectionFinished);
25 | }
26 |
27 | void OnConnectionFinished(ConnectionResult result, byte[] secretKey){
28 | if (result == ConnectionResult.Succeeded)
29 | {
30 | Console.WriteLine("Successful Connection!");
31 | SaveKeyToProperties(secretKey)
32 | }
33 | else
34 | {
35 | Console.WriteLine("Connection failed... :(");
36 | }
37 | }
38 | ```
39 |
40 | ## BLEDevice.Disconnect(rememberDevice = true)
41 | This method disconnects the BLEDevice. There is an optional parameter called rememberDevice that defaults to true.
42 |
43 | WindesHeart always saves your currently connected device to the `Windesheart.ConnectedDevice` field. if rememberDevice is true, it won't clear this field after disconnecting. If false is passed, `Windesheart.ConnectedDevice` will be set to null.
44 |
45 | The disconnect method is a void. You can assume that it always works.
46 |
47 | [<---- Back to mainpage](https://github.com/ictinnovaties-zorg/openwindesheart/blob/master/)
--------------------------------------------------------------------------------
/OpenWindesheart/Devices/MiBand3/Services/MiBand3HeartrateService.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using Plugin.BluetoothLE;
16 | using System;
17 | using System.Reactive.Linq;
18 | using OpenWindesheart.Devices.MiBand3Device.Models;
19 | using OpenWindesheart.Devices.MiBand3Device.Resources;
20 | using OpenWindesheart.Models;
21 |
22 | namespace OpenWindesheart.Devices.MiBand3Device.Services
23 | {
24 | public class MiBand3HeartrateService
25 | {
26 | private readonly MiBand3 _miBand3;
27 | public IDisposable RealtimeDisposible;
28 |
29 | public MiBand3HeartrateService(MiBand3 device)
30 | {
31 | _miBand3 = device;
32 | }
33 |
34 | ///
35 | /// Add a callback to run everytime the user manually measures their heartrate
36 | ///
37 | ///
38 | public void EnableRealTimeHeartrate(Action callback)
39 | {
40 | RealtimeDisposible?.Dispose();
41 | RealtimeDisposible = _miBand3.GetCharacteristic(MiBand3Resource.GuidHeartrate).RegisterAndNotify().Subscribe(
42 | x => callback(new HeartrateData(x.Characteristic.Value))
43 | );
44 | }
45 |
46 | public void DisableRealTimeHeartrate()
47 | {
48 | RealtimeDisposible?.Dispose();
49 | }
50 |
51 | ///
52 | /// Set the interval for automatic heartrate measurements
53 | ///
54 | ///
55 | public async void SetMeasurementInterval(int minutes)
56 | {
57 | var Char = _miBand3.GetCharacteristic(MiBand3Resource.GuidHeartRateControl);
58 | await Char.Write(new byte[] { 0x14, (byte)minutes });
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/OpenWindesheart/Devices/MiBand3/Helpers/MiBand3ConversionHelper.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using System;
16 | using System.Security.Cryptography;
17 | using OpenWindesheart.Helpers;
18 |
19 | namespace OpenWindesheart.Devices.MiBand3Device.Helpers
20 | {
21 | public static class MiBand3ConversionHelper
22 | {
23 | ///
24 | /// This generates a new secret key for authenticating a new device
25 | ///
26 | ///
27 | public static byte[] GenerateAuthKey()
28 | {
29 | Random random = new Random();
30 | byte[] SecretKey = new byte[16];
31 | for (var i = 0; i < 16; i++)
32 | {
33 | int keyNumber = random.Next(1, 255);
34 | SecretKey[i] = Convert.ToByte(keyNumber);
35 | }
36 | return SecretKey;
37 | }
38 |
39 | public static byte[] CreateKey(byte[] value, byte[] key)
40 | {
41 | byte[] bytes = { 0x03, 0x00 };
42 | byte[] secretKey = key;
43 |
44 | value = ConversionHelper.CopyOfRange(value, 3, 19);
45 | byte[] buffer = EncryptBuff(secretKey, value);
46 | byte[] endBytes = new byte[18];
47 | Buffer.BlockCopy(bytes, 0, endBytes, 0, 2);
48 | Buffer.BlockCopy(buffer, 0, endBytes, 2, 16);
49 | return endBytes;
50 | }
51 |
52 | public static byte[] EncryptBuff(byte[] sessionKey, byte[] buffer)
53 | {
54 | AesManaged myAes = new AesManaged();
55 |
56 | myAes.Mode = CipherMode.ECB;
57 | myAes.Key = sessionKey;
58 | myAes.Padding = PaddingMode.None;
59 |
60 | ICryptoTransform encryptor = myAes.CreateEncryptor();
61 | return encryptor.TransformFinalBlock(buffer, 0, buffer.Length);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/OpenWindesheart/Devices/MiBand3/Services/MiBand3StepsService.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using Plugin.BluetoothLE;
16 | using System;
17 | using System.Reactive.Linq;
18 | using System.Threading.Tasks;
19 | using OpenWindesheart.Devices.MiBand3Device.Models;
20 | using OpenWindesheart.Devices.MiBand3Device.Resources;
21 | using OpenWindesheart.Models;
22 |
23 | namespace OpenWindesheart.Devices.MiBand3Device.Services
24 | {
25 | public class MiBand3StepsService
26 | {
27 | private readonly MiBand3 _miBand3;
28 | public IDisposable realtimeDisposable;
29 |
30 | public MiBand3StepsService(MiBand3 device)
31 | {
32 | _miBand3 = device;
33 | }
34 |
35 | ///
36 | /// Add a callback to run everytime the Mi Band updates its step count
37 | ///
38 | ///
39 | public void EnableRealTimeSteps(Action callback)
40 | {
41 | realtimeDisposable?.Dispose();
42 | realtimeDisposable = _miBand3.GetCharacteristic(MiBand3Resource.GuidStepsInfo).RegisterAndNotify().Subscribe(
43 | x => callback(new StepData(x.Characteristic.Value)));
44 | }
45 |
46 | ///
47 | /// Disables real time step count updates
48 | ///
49 | public void DisableRealTimeSteps()
50 | {
51 | realtimeDisposable?.Dispose();
52 | }
53 |
54 | public async Task GetSteps()
55 | {
56 | if (_miBand3.IsAuthenticated())
57 | {
58 | var steps = await _miBand3.GetCharacteristic(MiBand3Resource.GuidStepsInfo).Read();
59 | return new StepData(steps.Characteristic.Value);
60 | }
61 | else
62 | {
63 | return new StepData(new byte[] { 0, 0, 0 });
64 | }
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/README-SupportNewDevice.md:
--------------------------------------------------------------------------------
1 |
2 | # How to add support for a new device
3 |
4 | This documentation offers a step by step guide on how to add support for a new device. We assume you have the WindesheartSDK project cloned and open in Visual Studio.
5 |
6 | ### 1. Add new device folder
7 | 
8 | To start, you need a folder to put all your code in. In the Devices folder, create a new folder named after your device. Please follow the format as shown in the MiBand3 folder. Put your models inside a Models folder, Helpers in a Helpers folder, and so on.
9 |
10 | ### 2. Add your own Device class extending BLEDevice
11 | Inside your newly created folder, add a "Models" folder, then create a new class in there.
12 | This class should have the exact same name as your folder:
13 | 
14 |
15 |
16 | The class also has to extend from BLEDevice. Because of this, you're forced to implement all abstract methods that class contains.
17 |
18 | 
19 | In theory this class can do all the logic for your device, however it is **STRONGLY** recommended that you have different services that handle the implementation, as seen in MiBand3.cs:
20 |
21 | 
22 |
23 | A few things you need to have in this class:
24 | * Set BLEDevice's ConnectionCallback of BleDevice in your Connect method.
25 | * Set BLEDevice's DisconnectionCallback of BleDevice in your SubscribeToDisconnect method.
26 |
27 | As seen in the example below:
28 |
29 | 
30 |
31 |
32 |
33 | ## 3. Add your code
34 | Now its time to implement everything! To keep things organized and clean, please use different services for different tasks. Mi Band 3 is a good example for this.
35 |
36 | If your device doesn't support an action provided by the BLEDevice class, just throw a NotImplementedException.
37 | For example, if your device doesn't support sleep tracking, you do this:
38 | 
39 |
40 | ## 4. Edit the GetDevice method
41 | The last step is to edit the GetDevice method inside of `BluetoothService.cs`
42 | This method returns the correct BLEDevice dependent of it's name. Please note that `var name` is the Bluetooth device name. There might be two or more names for one device (in case of the Mi Band 3).
43 | 
44 | And that should be it! Now, when scanning for devices it should detect and return your device! Please make sure everything works as expected before submitting a pull request.
45 |
46 | [<---- Back to mainpage](https://github.com/ictinnovaties-zorg/openwindesheart/blob/master/)
--------------------------------------------------------------------------------
/README-Settings.md:
--------------------------------------------------------------------------------
1 | # Settings
2 |
3 | Most devices have some settings that can be changed. The Mi Band 3 is not an exception and that is why we created a way of changing some basic settings for this device.
4 |
5 | ## How to use
6 |
7 | The following settings can be configurated to your liking for the Mi band 3, by using *Windesheart.PairedDevice* when already connected to the device:
8 |
9 | * **Display Language**: You can change your display language to any locale you wish, by calling the SetLanguage(string localeString) method with the preferred locale.
10 | **NOTE: We have not tested all locales that exist, but german(de-DE), dutch(nl-NL) and english(en-EN) definitely work.
11 | [A list of locales that could work can be found here.](https://stackoverflow.com/questions/3191664/list-of-all-locales-and-their-short-codes)
12 |
13 | * **Set the time-displayformat**: You can change the displayformat for time to 12-hour or 24-hour format. Call the SetTimeDisplayFormat(bool is24hours) to change this.
14 |
15 | * **Set the date-displayformat**: You can change the displayformat for dates to either dd-MM-YYYY or MM-dd-YYYY. Use the method SetDateDisplayFormat(bool isddMMYYYY) for this.
16 |
17 | * **Set Stepgoal**: You can set a goal for the amount of steps needed per day. By using the SetStepGoal(int steps) you can set the goal to your liking. You should also call EnableFitnessGoalNotification(bool enable) to actually receive the notification on the device when the goal has been reached. **NOTE: If the goal will be set to 1000 steps (with the notification on) and you already have more than 1000 steps displayed on your device, then this will trigger the next time you take a step.**
18 |
19 | * **Set Time**: You can change the time that will be displayed on your device. This can be done by calling SetTime(DateTime dateTime) with the datetime you want the time to be set to. **NOTE: Changing this could result in loss of samples and can unreliably change data that can be received from the device.**
20 |
21 | * **Activate display on wristlift**: If you want to turn on your display of your device, when lifting your wrist, then use the method SetActivateOnLiftWrist(bool activate). You can also use SetActivateOnLiftWrist(DateTime from, DateTime to) to activate this feature between the two dates.
22 |
23 | * **Enable sleep-tracking**: If you would like to create samples of your sleeping pattern, then this configuration has to be turned on! Use EnableSleepTracking(bool enable) to toggle the functionality.
24 |
25 | * **Set Heartrate-measurementinterval**: If you would like more accurate samples with heartrates, then you should turn on this function for the interval you want. Use SetHeartrateMeasurementInterval(int minutes) to set this interval. **NOTE: It is recommended to use SetHeartrateMeasurementInterval(1) to measure your heartrate automatically every minute. More samples will have accurate heartrate-data this way if the device is worn correctly. This does consume more battery, so be aware of this!**
26 |
27 | *It is recommended to set these features once when connecting to the device. This way you will not forget them.*
28 |
29 |
30 | [<---- Back to mainpage](https://github.com/ictinnovaties-zorg/openwindesheart/blob/master/)
--------------------------------------------------------------------------------
/OpenWindesheart/Windesheart.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using OpenWindesheart.Models;
16 | using Plugin.BluetoothLE;
17 | using System;
18 | using System.Threading.Tasks;
19 |
20 | namespace OpenWindesheart
21 | {
22 | public static class Windesheart
23 | {
24 | public static BLEDevice PairedDevice;
25 |
26 | ///
27 | /// Scan for BLEDevices that are not yet connected.
28 | ///
29 | /// Throws exception when trying to start scan when a scan is already running.
30 | /// Called when a device is found
31 | /// List of IScanResult
32 | public static bool StartScanning(Action callback)
33 | {
34 | return BluetoothService.StartScanning(callback);
35 | }
36 |
37 | ///
38 | /// Stops scanning for devices
39 | ///
40 | public static void StopScanning()
41 | {
42 | BluetoothService.StopScanning();
43 | }
44 |
45 | ///
46 | /// Get a BLEDevice based on the UUID
47 | ///
48 | /// Uuid of the BLEDevice
49 | ///
50 | public static async Task GetKnownDevice(Guid uuid)
51 | {
52 | return await BluetoothService.GetKnownDevice(uuid);
53 | }
54 |
55 |
56 | ///
57 | /// Calls the callback method when Bluetooth adapter state changes to ready
58 | ///
59 | /// Called when adapter is ready
60 | public static void WhenAdapterReady(Action callback)
61 | {
62 | BluetoothService.WhenAdapterReady(callback);
63 | }
64 |
65 | ///
66 | /// Calls the callback method when Bluetooth adapter status changes
67 | ///
68 | /// Called when status changed
69 | public static void OnAdapterChanged(Action callback)
70 | {
71 | BluetoothService.OnAdapterChanged(callback);
72 | }
73 |
74 | ///
75 | /// Return whether device is currently scanning for devices.
76 | ///
77 | public static bool IsScanning()
78 | {
79 | return BluetoothService.IsScanning();
80 | }
81 |
82 | public static AdapterStatus AdapterStatus { get => CrossBleAdapter.Current.Status; }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/README-Samples.md:
--------------------------------------------------------------------------------
1 | # Reading Samples
2 | The Windesheart SDK allows reading samples from the past from BLE Devices.
3 |
4 | ## *Fetching Samples*
5 |
6 | By using our *MiBand3SamplesService* it is possible to fetch samples from the past days, weeks, months or even years.
7 |
8 | Samples are generated once *every minute* in your device. This means that fetching data for 1 day, 1440 samples will be fetched (24 hours * 60 minutes = 1440 samples).
9 |
10 | The data that is generated will be stored in a class called *ActivitySample*. This class contains the following data:
11 |
12 | * **RawData**: This is the byte-array containing the raw-data of the sample (for debugging purposes).
13 | * **TimeStamp**: The exact DateTime that this sample contains data for.
14 | * **UnixEpochTimeStamp**: The amount of seconds since UnixEpoch. This way time-zones can be countered.
15 | * **Category**: This is a number that tells you the sort of activity that has been measured in that minute. Walking, running, sleeping and other activities all have their separate number. We are unsure in what all the categories are, but some are obvious in our opinion. **NOTE: The accuracy of this number can vary. Sometimes the Mi band 3 thinks you are sleeping, when in reality you are sitting without moving.**
16 | * **RawIntensity**: This number can tell you whether your activity was intense or not. If you walk faster, the measured intensity will most likely be higher.
17 | * **Steps**: This is the number of steps that have been measured in that minute. If you use addition on all the step-numbers of the current day, then this should be exactly or close to your displayed step-number on your device.
18 | * **HeartRate**: The measured heartrate in that minute. **NOTE: This only gets measured if you wear your device properly and have set the heartratemeasurement-interval to 1 minute by using *MiBand3.SetHeartrateMeasurementInterval(1)***
19 |
20 | A list of AcitivitySample can be acquired by calling *MiBand3SampleService.StartFetching(). You will have to provide the datetime of the starting date (Example: For a week of data you will call this method with DateTime.Now.AddDays(-7)).
21 |
22 | The callbacks are useful if you want to know when fetching has been finished and if you want to get a callback on every 250 samples for creating a progressbar in the mobile-app.
23 |
24 | Fetching can take a while, because of the speed of Bluetooth Low Energy. Storing data in a database and only fetching the data of the last synchronization will speed up the process alot.
25 |
26 | ## *Example*
27 |
28 | To get the list of samples of your device correctly, you will have to connect to the device first and then use this example:
29 |
30 | ```csharp
31 | //Fetching from a week ago until now
32 | DateTime startDate = DateTime.Now.AddDays(-7);
33 | Windesheart.PairedDevice.GetSamples(startDate, FetchingFinished, UpdateProgression);
34 |
35 | private void UpdateProgression(int remainingSamples) {
36 | /*Do something with the calculated remaining samples.
37 | For example: remainingSamples = 1440,
38 | means that this amount of samples is remaining
39 | until all samples have been fetched.*/
40 | }
41 |
42 | private void FetchingFinished(List samples) {
43 | /*Do something with the samples that have been found*/
44 | }
45 | ```
46 |
47 | *The demo-application contains a working example of this in the directory 'Services' -> 'SamplesService.cs'*
48 |
49 | [<---- Back to mainpage](https://github.com/ictinnovaties-zorg/openwindesheart/blob/master/)
--------------------------------------------------------------------------------
/OpenWindesheart/Devices/MiBand3/Resources/MiBand3Resource.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using System;
16 | namespace OpenWindesheart.Devices.MiBand3Device.Resources
17 | {
18 | public static class MiBand3Resource
19 | {
20 | //Authentication
21 | public static Guid GuidCharacteristicAuth = new Guid("00000009-0000-3512-2118-0009af100700");
22 |
23 | public static byte AuthResponse = 0x10;
24 | public static byte AuthSendKey = 0x01;
25 | public static byte AuthRequestRandomAuthNumber = 0x02;
26 | public static byte AuthSendEncryptedAuthNumber = 0x03;
27 | public static byte AuthSuccess = 0x01;
28 | public static readonly byte[] RequestNumber = { 0x02, 0x00 };
29 |
30 | //General Guid for device settings
31 | public static Guid GuidDeviceConfiguration = new Guid("00000003-0000-3512-2118-0009af100700");
32 |
33 | public static byte[] Byte_EnableActivateOnLiftWrist = new byte[] { 0x06, 0x05, 0x00, 0x01 };
34 | public static byte[] Byte_DisableActivateOnLiftWrist = new byte[] { 0x06, 0x05, 0x00, 0x00 };
35 | public static byte[] Byte_ScheduleActivateOnLiftWrist_Template = new byte[] { 0x06, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 };
36 |
37 | public static byte[] Byte_SetLanguage_Template = new byte[] { 0x06, 0x17, 0x00, 0, 0, 0, 0, 0 };
38 |
39 | public static byte[] Byte_TimeFomat_24hours = new byte[] { 0x06, 0x02, 0x0, 0x1 };
40 | public static byte[] Byte_TimeFomat_12hours = new byte[] { 0x06, 0x02, 0x0, 0x0 };
41 |
42 | public static byte[] Byte_EnableGoalNotification = new byte[] { 0x06, 0x06, 0x00, 0x01};
43 | public static byte[] Byte_DisableGoalNotification = new byte[] { 0x06, 0x06, 0x00, 0x00};
44 |
45 | public static byte[] Byte_EnableSleepMeasurement = new byte[] { 0x15, 0x00, 0x01 };
46 | public static byte[] Byte_DisableSleepMeasurement = new byte[] { 0x15, 0x00, 0x00 };
47 |
48 | public static byte[] Byte_DateFormat_dd_MM_YYYY = new byte[] { 0x06, 30, 0x00, Convert.ToByte('d'), Convert.ToByte('d'), Convert.ToByte('/'), Convert.ToByte('M'), Convert.ToByte('M'), Convert.ToByte('/'), Convert.ToByte('y'), Convert.ToByte('y'), Convert.ToByte('y'), Convert.ToByte('y') };
49 | public static byte[] Byte_DateFormat_MM_dd_YYYY = new byte[] { 0x06, 30, 0x00, Convert.ToByte('M'), Convert.ToByte('M'), Convert.ToByte('/'), Convert.ToByte('d'), Convert.ToByte('d'), Convert.ToByte('/'), Convert.ToByte('y'), Convert.ToByte('y'), Convert.ToByte('y'), Convert.ToByte('y') };
50 |
51 | //User settings
52 | public static Guid GuidUserInfo = new Guid("00000008-0000-3512-2118-0009af100700");
53 |
54 | //Battery Guid
55 | public static Guid GuidBatteryInfo = new Guid("00000006-0000-3512-2118-0009af100700");
56 |
57 | //Current Time Guid
58 | public static Guid GuidCurrentTime = new Guid("00002A2B-0000-1000-8000-00805f9b34fb");
59 |
60 | //Heartrate Control Point Guid
61 | public static Guid GuidHeartRateControl = new Guid("00002A39-0000-1000-8000-00805f9b34fb");
62 |
63 | //Heartrate Realtime Guid
64 | public static Guid GuidHeartrate = new Guid("00002A37-0000-1000-8000-00805f9b34fb");
65 |
66 | //Request & get samples
67 | public static Guid GuidSamplesRequest = new Guid("00000004-0000-3512-2118-0009af100700");
68 | public static Guid GuidActivityData = new Guid("00000005-0000-3512-2118-0009af100700");
69 |
70 | public static byte Response = 0x10;
71 | public static byte CommandActivityDataStartDate = 0x01;
72 | public static byte Success = 0x01;
73 |
74 | public static byte[] ResponseActivityDataStartDateSuccess = { Response, CommandActivityDataStartDate, Success };
75 |
76 | //Steps Realtime Guid
77 | public static Guid GuidStepsInfo = new Guid("00000007-0000-3512-2118-0009af100700");
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/OpenWindesheart/Helpers/ConversionHelper.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using System;
16 |
17 | namespace OpenWindesheart.Helpers
18 | {
19 | public static class ConversionHelper
20 | {
21 | public enum TimeUnit { Seconds, Days, Hours, Minutes, Unknown = -1 }
22 |
23 | public static byte[] ShortDateTimeToRawBytes(DateTime dateTime)
24 | {
25 | byte[] year = FromUint16(dateTime.Year);
26 | return new[] {
27 | year[0],
28 | year[1],
29 | FromUint8(dateTime.Month),
30 | FromUint8(dateTime.Day),
31 | FromUint8(dateTime.Hour),
32 | FromUint8(dateTime.Minute)
33 | };
34 | }
35 |
36 | public static byte[] DateTimeToRawBytes(DateTime dateTime)
37 | {
38 | byte[] year = FromUint16(dateTime.Year);
39 | return new[] {
40 | year[0],
41 | year[1],
42 | FromUint8(dateTime.Month),
43 | FromUint8(dateTime.Day),
44 | FromUint8(dateTime.Hour),
45 | FromUint8(dateTime.Minute),
46 | FromUint8(dateTime.Second),
47 | DayOfWeekToRawBytes(dateTime),
48 | (byte) 0
49 | };
50 | }
51 |
52 | public static byte[] GetTimeBytes(DateTime dateTime, TimeUnit precision)
53 | {
54 | byte[] bytes;
55 | if (precision == TimeUnit.Minutes)
56 | {
57 | bytes = ShortDateTimeToRawBytes(dateTime);
58 | }
59 | else if (precision == TimeUnit.Seconds)
60 | {
61 | bytes = DateTimeToRawBytes(dateTime);
62 | }
63 | else
64 | {
65 | throw new ArgumentException();
66 | }
67 |
68 | byte[] all = new byte[bytes.Length + 2];
69 | Buffer.BlockCopy(bytes, 0, all, 0, bytes.Length);
70 | Buffer.BlockCopy(new byte[] { 0, 4 }, 0, all, bytes.Length, 2);
71 |
72 | return all;
73 | }
74 |
75 | private static byte DayOfWeekToRawBytes(DateTime dateTime)
76 | {
77 | int dayValue = (int)dateTime.DayOfWeek;
78 | if (dateTime.DayOfWeek == DayOfWeek.Saturday)
79 | {
80 | return 7;
81 | }
82 | return (byte)dayValue;
83 | }
84 |
85 | public static byte FromUint8(int value)
86 | {
87 | byte[] bytes = BitConverter.GetBytes(value);
88 | return bytes[0];
89 | }
90 |
91 | public static byte[] FromUint16(int value)
92 | {
93 | return BitConverter.GetBytes((short)value);
94 | }
95 |
96 | public static int ToUint16(byte[] bytes)
97 | {
98 | return (bytes[1] << 8 | bytes[0]);
99 | }
100 |
101 | public static DateTime RawBytesToCalendar(byte[] value)
102 | {
103 | if (value.Length >= 7)
104 | {
105 | int year = ToUint16(new byte[] { value[0], value[1], 0, 0 });
106 | DateTime timestamp = new DateTime(
107 | year,
108 | (value[2] & 0xff),
109 | value[3] & 0xff,
110 | value[4] & 0xff,
111 | value[5] & 0xff,
112 | value[6] & 0xff
113 | );
114 | return timestamp;
115 | }
116 | return new DateTime();
117 | }
118 |
119 | public static byte[] CopyOfRange(byte[] src, int start, int end)
120 | {
121 | int len = end - start;
122 | byte[] dest = new byte[len];
123 | // note i is always from 0
124 | for (int i = 0; i < len; i++)
125 | {
126 | dest[i] = src[start + i]; // so 0..n = 0+x..n+x
127 | }
128 | return dest;
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # OpenWindesheart
3 |
4 | The open-source OpenWindesheart is a library used for scanning, connecting and getting data from activity-trackers using bluetooth.
5 |
6 | ## Support
7 |
8 | This project has been created by students of Windesheim University of Applied Sciences and does not guarantee any support in the future.
9 |
10 | This library uses the [ACR Reactive BluetoothLE Plugin](https://github.com/aritchie/bluetoothle) to do anything BluetoothLE related. Our project only supports versions that are supported by this library, because our project depends heavily upon it.
11 |
12 | The features have been tested with Android/iOS phones in combination with the Mi Band 3/Xiaomi Band 3.
13 |
14 | ## Features
15 |
16 | * Scanning for BLE devices
17 | * Pairing with a BLE device
18 | * Connecting to BLE device
19 | * Reading current battery-data and status
20 | * Reading current step-data
21 | * Reading step-data from the past days
22 | * Reading heartrate after measurement.
23 | * Reading heartrate from the past days with measurement-intervals
24 | * Reading sleep-data from the past days
25 | * Setting step-goal on BLE device
26 | * Setting language on BLE device
27 | * Setting Date and time on BLE device
28 | * Setting Date-format and Hour-notation on BLE device
29 | * Toggle screen of BLE device on wrist-lift
30 | * Auto-reconnect after Bluetooth-adapter toggle
31 | * Auto-reconnect when within range of BLE device
32 | * Disconnect with BLE device
33 |
34 | ## Supported Devices
35 |
36 | At this moment the OpenWindesheart library only fully supports the Mi Band 3.
37 |
38 | The library is designed in a way that other devices can be added easily. If you want to add support for a device, please check out our documentation: [How to add support for a new device](https://github.com/ictinnovaties-zorg/openwindesheart/blob/master/README-SupportNewDevice.md)
39 |
40 |
41 | ### Mi Band 4
42 | If you want these features with a Mi Band 4, then you will have to get the authentication-key for your Mi Band here:
43 | https://www.freemyband.com/2019/08/mi-band-4-auth-key.html
44 |
45 | We have a branch for the Mi Band 4, called MiBand4, which allows these devices to show up in the list of scanned devices.
46 |
47 | To make your app work with our logic, please update line 13 of this file: https://github.com/ictinnovaties-zorg/openwindesheart/blob/MiBand4/WindesHeartSDK/Devices/MiBand4/Helpers/MiBand4ConversionHelper.cs
48 |
49 | This is where you fill in your own secret key. For example; the key '0a1bc2' should be altered to {0x0a, 0x1b, 0xc2} in the byte-array on line 13 of the code.
50 |
51 | After that, you will only have to build the SDK and the mobile-project.
52 | Once all is built, it should be ready for use with the Mi Band 4.
53 |
54 | DISCLAIMER: The source of www.freemyband.com is unofficial. Use this website at your own risk, we do not take responsibility for anything related to this source.
55 |
56 | ## Documentation
57 |
58 | #### User docs:
59 | * [Scanning](https://github.com/ictinnovaties-zorg/openwindesheart/blob/master/README-Scanning.md)
60 | * [Connecting & Disconnecting](https://github.com/ictinnovaties-zorg/openwindesheart/blob/master/README-Connecting.md)
61 | * [Reading data](https://github.com/ictinnovaties-zorg/openwindesheart/blob/master/README-Readingdata.md)
62 | * [Reading samples](https://github.com/ictinnovaties-zorg/openwindesheart/blob/master/README-Samples.md)
63 | * [Supported settings](https://github.com/ictinnovaties-zorg/openwindesheart/blob/master/README-Settings.md)
64 |
65 | #### Contributor docs:
66 | * [How to add support for a new device](https://github.com/ictinnovaties-zorg/openwindesheart/blob/master/README-SupportNewDevice.md)
67 |
68 | ## SETUP
69 | 1. Clone this repository into your solution and manage a dependency from your mobile-project to this one.
70 | 2. Carefully read the docs for implementation of different features. For a working example, have a look at the Xamarin Forms project on this page.
71 | 3. Implement the features in your mobile-application the way you want them!
72 |
73 | ## Credits
74 |
75 | We would like to thank Allan Ritchie for creating the [ACR Reactive BluetoothLE Plugin](https://github.com/aritchie/bluetoothle). Without this open-source library our project would not have been finished within the specified amount of time.
76 |
77 | ## Contributions
78 |
79 | To make contributions to this project, please open up a [pull request](https://github.com/ictinnovaties-zorg/openwindesheart/pull/new/master).
80 |
81 | ## Creators
82 |
83 | * R. Abächerli [@ramonb1996](https://github.com/ramonB1996)
84 | * H. van der Gugten [@hielkeg](https://github.com/hielkeg)
85 | * T.C. Marschalk [@marstc](https://github.com/marstc)
86 | * K. van Sloten [@kevinvansloten](https://github.com/kevinvansloten)
87 |
88 | ## Copyright
89 |
90 | Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences.
91 |
--------------------------------------------------------------------------------
/OpenWindesheart/BLEDevice.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 Research group ICT innovations in Health Care, Windesheim University of Applied Sciences
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | using OpenWindesheart.Models;
16 | using Plugin.BluetoothLE;
17 | using System;
18 | using System.Collections.Generic;
19 | using System.Threading.Tasks;
20 |
21 | namespace OpenWindesheart
22 | {
23 | public abstract class BLEDevice
24 | {
25 | public string Name { get => IDevice.Name; }
26 | public ConnectionStatus Status { get => IDevice.Status; }
27 | public Guid Uuid { get => IDevice.Uuid; }
28 | public List Characteristics = new List();
29 | public readonly IDevice IDevice;
30 | protected readonly BluetoothService BluetoothService;
31 | public bool Authenticated = false;
32 | public bool NeedsAuthentication = false;
33 | public byte[] SecretKey;
34 |
35 | //Callbacks & Disposables
36 | public Action ConnectionCallback;
37 | internal Action