Skip to content

Commit 6ff5fb4

Browse files
committed
419 ble server - first time
1 parent 9c30806 commit 6ff5fb4

File tree

9 files changed

+2363
-0
lines changed

9 files changed

+2363
-0
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*
2+
* Copyright (c) 2025 Moddable Tech, Inc.
3+
*
4+
* This file is part of the Moddable SDK.
5+
*
6+
* This work is licensed under the
7+
* Creative Commons Attribution 4.0 International License.
8+
* To view a copy of this license, visit
9+
* <http://creativecommons.org/licenses/by/4.0>.
10+
* or send a letter to Creative Commons, PO Box 1866,
11+
* Mountain View, CA 94042, USA.
12+
*
13+
*/
14+
15+
import { GATTServer} from "embedded:io/bluetoothle/peripheral"
16+
import Timer from "timer";
17+
18+
const deviceName = "419 HRM";
19+
20+
let hrm = new GATTServer({
21+
mtu: 128,
22+
services: [
23+
// Generic Access Service
24+
{
25+
uuid: "1800",
26+
characteristics: [
27+
{
28+
uuid: "2a00", // device name
29+
properties: GATTServer.properties.read,
30+
value: ArrayBuffer.fromString(deviceName),
31+
},
32+
{
33+
uuid: "2a01", // appearance
34+
properties: GATTServer.properties.read,
35+
value: Uint8Array.of(0x40, 0x03),
36+
},
37+
]
38+
},
39+
// Battery Service
40+
{
41+
uuid: "180f",
42+
characteristics: [
43+
{
44+
uuid: "2a19", // // battery level
45+
properties: GATTServer.properties.read | GATTServer.properties.write,
46+
onRead(connection) {
47+
return Uint8Array.of(this.value ?? 50); // last value written or default of 50%
48+
},
49+
onWrite(buffer, connection) { // write support for demonstration purposes
50+
this.value = (new Uint8Array(buffer))[0];
51+
if (0 === this.value)
52+
connection.close(); // out of battery!
53+
},
54+
descriptors: [
55+
{
56+
uuid: "2901", // User description
57+
value: ArrayBuffer.fromString("Battery level")
58+
},
59+
{
60+
uuid: "2904", // Characteristic presentation format
61+
value: Uint8Array.of(4, 0, 0xad, 0x27, 1, 0, 0)
62+
},
63+
{
64+
uuid: "2999", // test
65+
onRead() {
66+
return Uint8Array.of(this.value ?? 128);
67+
},
68+
onWrite(buffer) {
69+
this.value = (new Uint8Array(buffer))[0];
70+
}
71+
}
72+
]
73+
}
74+
]
75+
},
76+
// Heart Rate Monitor Service
77+
{
78+
uuid: "180d",
79+
characteristics: [
80+
{
81+
uuid: "2a37", // heart rate
82+
properties: GATTServer.properties.read | GATTServer.properties.indicate,
83+
onRead() {
84+
return Uint8Array.of(0, 65); // 65 BPM
85+
},
86+
onSubscribe(connection) {
87+
connection.heartRateTimer ??= Timer.set(() => {
88+
connection.notify(this, Uint8Array.of(0, 55 + Math.random() * 10), error => trace(`notify complete ${error}\n`));
89+
}, 1, connection.heartRateNotificationInterval * 1000);
90+
},
91+
onUnsubscribe(connection) {
92+
Timer.clear(connection.heartRateTimer);
93+
delete connection.heartRateTimer;
94+
}
95+
}
96+
]
97+
},
98+
// Heart Rate notification frequency – custom service and characteristic
99+
{
100+
uuid: "cfe6f7f2-16d2-4b7e-9253-a1d1c1577a35",
101+
characteristics: [
102+
{
103+
uuid: "7d3a0f66-19a9-4fc4-b3e6-91a2d2c2e58a",
104+
properties: GATTServer.properties.read | GATTServer.properties.write,
105+
onRead(connection) {
106+
return Uint8Array.of(connection.heartRateNotificationInterval);
107+
},
108+
onWrite(buffer, connection) {
109+
const value = (new Uint8Array(buffer))[0];
110+
if (value > 0) {
111+
connection.heartRateNotificationInterval = value;
112+
if (connection.heartRateTimer)
113+
Timer.schedule(connection.heartRateTimer, value * 1000, value * 1000);
114+
}
115+
},
116+
descriptors: [
117+
{
118+
uuid: "2901", // User description
119+
value: ArrayBuffer.fromString("Update frequency in seconds")
120+
}
121+
]
122+
}
123+
]
124+
}
125+
],
126+
onConnect(connection) {
127+
trace("connect!\n");
128+
connection.heartRateNotificationInterval = 1;
129+
},
130+
onDisconnect(connection) {
131+
trace("disconnect!\n");
132+
Timer.clear(connection.heartRateTimer);
133+
},
134+
onReady(connection) {
135+
trace("hrm onReady\n");
136+
this.startAdvertising({
137+
flags: 6,
138+
name: deviceName,
139+
manufacturerData: {
140+
manufacturer: 1,
141+
data: Uint8Array.of(255, 0, 1)
142+
},
143+
services: ["180d", "180f"],
144+
[123]: Uint8Array.of(1,2,3)
145+
});
146+
},
147+
onWarning(msg) {
148+
trace(`BLE server warning: ${msg}\n`);
149+
}
150+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"include": [
3+
"$(MODDABLE)/examples/manifest_base.json",
4+
"$(MODDABLE)/modules/io/ble/server/manifest.json"
5+
],
6+
"modules": {
7+
"*": "./main"
8+
}
9+
}

0 commit comments

Comments
 (0)