Skip to content

Commit ed3fe02

Browse files
author
Daisuke Baba
committed
Add a poll-notify-events request support
1 parent 6b7b224 commit ed3fe02

File tree

3 files changed

+101
-14
lines changed

3 files changed

+101
-14
lines changed

examples/01-read-write.json

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"crontab": "",
3535
"once": false,
3636
"x": 200,
37-
"y": 260,
37+
"y": 220,
3838
"wires": [
3939
[
4040
"dfcf20d6.138ff"
@@ -101,13 +101,32 @@
101101
]
102102
]
103103
},
104+
{
105+
"id": "5525464e.999a4",
106+
"type": "inject",
107+
"z": "867e39b4.d517f",
108+
"name": "Poll Notify Events",
109+
"topic": "2a19",
110+
"payload": "{\"notify\":true,\"period\":5000}",
111+
"payloadType": "json",
112+
"repeat": "",
113+
"crontab": "",
114+
"once": false,
115+
"x": 200,
116+
"y": 300,
117+
"wires": [
118+
[
119+
"dfcf20d6.138ff"
120+
]
121+
]
122+
},
104123
{
105124
"id": "3b98076c.99a4c8",
106125
"type": "Generic BLE",
107126
"z": "",
108127
"localName": "CC2650 SensorTag",
109-
"address": "99:99:99:99:99:99",
110-
"uuid": "00000000000000000000000000000000",
128+
"address": "54:6c:0e:78:86:80",
129+
"uuid": "666e850ba45c4952b8bed27a8133ecb2",
111130
"muteNotifyEvents": true,
112131
"operationTimeout": "5000",
113132
"characteristics": [

src/generic-ble.js

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ function hasPendingOperations(bleDevice) {
123123
if (!bleDevice) {
124124
return false;
125125
}
126-
if ((bleDevice._writeRequests.length > 0) || (bleDevice._readRequests.length > 0)) {
126+
if ((bleDevice._writeRequests.length > 0) || (bleDevice._readRequests.length > 0) || (bleDevice._notifyRequests.length > 0)) {
127127
return true;
128128
}
129129
if (bleDevice.muteNotifyEvents) {
@@ -246,14 +246,26 @@ function characteristicsTask(services, bleDevice) {
246246
}
247247
process.nextTick(loop);
248248
}).then(() => {
249-
if (bleDevice.muteNotifyEvents) {
250-
return Promise.resolve();
251-
}
252-
let notifiables = bleDevice.characteristics.filter(c => c.notifiable);
253-
if (notifiables.length === 0) {
254-
return Promise.resolve();
249+
let notifiables = [];
250+
let notifyRequest = bleDevice._notifyRequests.shift() || [];
251+
let notifyUuidList = notifyRequest.map(c => {
252+
operationTimeoutMs += c.period;
253+
return c.uuid;
254+
});
255+
notifiables = notifyUuidList.length > 0 ?
256+
characteristics.filter(c => c && notifyUuidList.indexOf(c.uuid) >= 0) : [];
257+
258+
if (notifyRequest.length === 0) {
259+
if (bleDevice.muteNotifyEvents) {
260+
return Promise.resolve();
261+
}
262+
operationTimeoutMs += (bleDevice.operationTimeout || BLE_OPERATION_WAIT_MS) * notifiables.length;
263+
notifiables = bleDevice.characteristics.filter(c => c.notifiable);
264+
if (notifiables.length === 0) {
265+
return Promise.resolve();
266+
}
255267
}
256-
operationTimeoutMs += (bleDevice.operationTimeout || BLE_OPERATION_WAIT_MS) * notifiables.length;
268+
257269
return new Promise((taskResolve, taskReject) => {
258270
timeout = addTimeout(() => {
259271
if (TRACE) {
@@ -708,6 +720,7 @@ export default function(RED) {
708720
this.nodes = {};
709721
this._writeRequests = []; // {uuid:'characteristic-uuid-to-write', data:Buffer()}
710722
this._readRequests = []; // {uuid:'characteristic-uuid-to-read'}
723+
this._notifyRequests = []; // {uuid:'characteristic-uuid-to-subscribe', period:subscription period}
711724
this.operations = {
712725
register: (node) => {
713726
this.nodes[node.id] = node;
@@ -777,6 +790,31 @@ export default function(RED) {
777790
return { uuid: r.uuid };
778791
}));
779792
return true;
793+
},
794+
subscribe: (uuids='', period=3000) => {
795+
uuids = uuids.split(',').map((uuid) => uuid.trim()).filter((uuid) => uuid);
796+
let notifiables = this.characteristics.filter(c => {
797+
if (c.notifiable) {
798+
if (uuids.length === 0) {
799+
return true;
800+
}
801+
return uuids.indexOf(c.uuid) >= 0;
802+
}
803+
});
804+
if (TRACE) {
805+
this.log(`characteristics => ${JSON.stringify(this.characteristics)}`);
806+
this.log(`notifiables.length => ${notifiables.length}`);
807+
}
808+
if (notifiables.length === 0) {
809+
return false;
810+
}
811+
if (this._notifyRequests.length >= MAX_REQUESTS) {
812+
return false;
813+
}
814+
this._notifyRequests.push(notifiables.map((r) => {
815+
return { uuid: r.uuid, period: period };
816+
}));
817+
return true;
780818
}
781819
};
782820
['connected', 'disconnected', 'subscribed', 'unsubscribed', 'error', 'timeout'].forEach(ev => {
@@ -869,7 +907,18 @@ export default function(RED) {
869907
if (TRACE) {
870908
this.log(`input arrived!`);
871909
}
872-
this.genericBleNode.operations.read(msg.topic);
910+
let obj = msg.payload || {};
911+
try {
912+
if (typeof(obj) === 'string') {
913+
obj = JSON.parse(msg.payload);
914+
}
915+
} catch (_) {
916+
}
917+
if (obj.notify) {
918+
this.genericBleNode.operations.subscribe(msg.topic, obj.period);
919+
} else {
920+
this.genericBleNode.operations.read(msg.topic);
921+
}
873922
});
874923
this.on('close', () => {
875924
if (this.genericBleNode) {

src/locales/en-US/generic-ble.html

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,29 @@ <h3>Outputs</h3>
2020
</p>
2121
<h3>Inputs</h3>
2222
<p>
23-
Expects a message used for triggering <code>Read</code> operations.
23+
Expects a message used for triggering <code>Read</code> operation or subscribing <code>Notify</code> events.
24+
<dl>
25+
<dt>For <code>Read</code> operation:</dt>
26+
<dd>
2427
You can set one or more characteristic uuids separated by comma (CSV) to query to <code>msg.topic</code>.
2528
However, leave <code>msg.topic</code> empty if you want to query all readable characteristics.
26-
The content of the message paylaod is always <b>IGNORED</b>.
29+
</dd>
30+
<dt>For subscribing <code>Notify</code> events:</dt>
31+
<dd>
32+
In order to subscribe <code>Notify</code> events rather than reading characteristics,
33+
set one or more characteristic uuids separated by comma (CSV) to subscribe to <code>msg.topic</code>
34+
and set the following object to <code>msg.payload</code> as well.
35+
However, leave <code>msg.topic</code> empty if you want to subscribe all notifiable characteristics.
36+
<pre>
37+
{
38+
"notify": true,
39+
"period": 6000
40+
}
41+
</pre>
42+
When you set the above in <code>msg.payload</code>, <code>msg.topic</code> is ignored.
43+
The <code>period</code> property is the period for subscribing <code>Notify</code> events in milliseconds <b>per characteristic</b>.
44+
</dd>
45+
</dl>
2746
</p>
2847
</script>
2948

0 commit comments

Comments
 (0)