@mschaeffler/node-red-bthome 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/btevent.js +31 -30
- package/bthome.js +48 -16
- package/package.json +1 -1
package/btevent.js
CHANGED
|
@@ -1,52 +1,49 @@
|
|
|
1
1
|
class BtEvent {
|
|
2
|
-
|
|
2
|
+
static eventLut = {
|
|
3
|
+
9: {
|
|
4
|
+
button: ["left","right"]
|
|
5
|
+
}
|
|
6
|
+
};
|
|
7
|
+
constructor(prefix,item)
|
|
3
8
|
{
|
|
4
9
|
this._events = {};
|
|
5
10
|
this._prefix = prefix;
|
|
11
|
+
this._item = item;
|
|
6
12
|
}
|
|
7
13
|
pushEvent(type,event,data=null)
|
|
8
14
|
{
|
|
9
|
-
if(
|
|
10
|
-
{
|
|
11
|
-
event = `${event}|${data}`;
|
|
12
|
-
}
|
|
13
|
-
switch( typeof this._events[type] )
|
|
15
|
+
if( this._events[type] === undefined )
|
|
14
16
|
{
|
|
15
|
-
|
|
16
|
-
this._events[type] = event;
|
|
17
|
-
break;
|
|
18
|
-
case "string":
|
|
19
|
-
this._events[type] = [ this._events[type] ];
|
|
20
|
-
// fall through
|
|
21
|
-
case "object":
|
|
22
|
-
this._events[type].push( event );
|
|
23
|
-
break;
|
|
17
|
+
this._events[type] = [];
|
|
24
18
|
}
|
|
19
|
+
this._events[type].push( { event:event, data:data } );
|
|
25
20
|
}
|
|
26
|
-
eventMessages(name)
|
|
21
|
+
eventMessages(name,channel)
|
|
27
22
|
{
|
|
28
23
|
function pushResult(type,event,index=null)
|
|
29
24
|
{
|
|
30
|
-
if( event )
|
|
25
|
+
if( event.event && event.data !== 0 )
|
|
31
26
|
{
|
|
32
|
-
|
|
33
|
-
let
|
|
34
|
-
|
|
35
|
-
if( index === null )
|
|
27
|
+
let payload = { type: type, event: event.event };
|
|
28
|
+
let indexStr = "";;
|
|
29
|
+
if( channel !== null )
|
|
36
30
|
{
|
|
37
|
-
|
|
31
|
+
indexStr += "/"
|
|
32
|
+
indexStr += channel;
|
|
33
|
+
payload.channel = channel;
|
|
38
34
|
}
|
|
39
|
-
|
|
35
|
+
if( index !== null )
|
|
40
36
|
{
|
|
41
|
-
|
|
37
|
+
indexStr += "/";
|
|
38
|
+
indexStr += index;
|
|
42
39
|
payload.id = index;
|
|
43
40
|
}
|
|
44
|
-
if(
|
|
41
|
+
if( event.data !== null )
|
|
45
42
|
{
|
|
46
|
-
payload.data =
|
|
43
|
+
payload.data = event.data;
|
|
47
44
|
}
|
|
48
45
|
result.push( {
|
|
49
|
-
topic:
|
|
46
|
+
topic: `${prefix}${name}${indexStr}/${event.event}`,
|
|
50
47
|
payload: payload
|
|
51
48
|
} );
|
|
52
49
|
}
|
|
@@ -57,15 +54,19 @@ class BtEvent {
|
|
|
57
54
|
for( const t in this._events )
|
|
58
55
|
{
|
|
59
56
|
const event = this._events[t];
|
|
60
|
-
if(
|
|
57
|
+
if( event.length == 1 )
|
|
61
58
|
{
|
|
62
|
-
pushResult( t, event );
|
|
59
|
+
pushResult( t, event[0] );
|
|
63
60
|
}
|
|
64
61
|
else
|
|
65
62
|
{
|
|
66
63
|
for( const i in event )
|
|
67
64
|
{
|
|
68
|
-
pushResult(
|
|
65
|
+
pushResult(
|
|
66
|
+
t,
|
|
67
|
+
event[i],
|
|
68
|
+
BtEvent.eventLut[this._item.typeId]?.[t]?.[i] ?? Number( i ) + 1
|
|
69
|
+
);
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
}
|
package/bthome.js
CHANGED
|
@@ -3,6 +3,12 @@ const Tools = require( './tools.js' );
|
|
|
3
3
|
const Rawdata = require( "./rawdata.js" );
|
|
4
4
|
const BtEvent = require( "./btevent.js" );
|
|
5
5
|
|
|
6
|
+
class TypeIds {
|
|
7
|
+
static bluDW = 0x0202;
|
|
8
|
+
static bluRemote = 9;
|
|
9
|
+
}
|
|
10
|
+
Object.freeze( TypeIds );
|
|
11
|
+
|
|
6
12
|
module.exports = function(RED) {
|
|
7
13
|
|
|
8
14
|
function BtHomeNode(config) {
|
|
@@ -10,7 +16,7 @@ module.exports = function(RED) {
|
|
|
10
16
|
var node = this;
|
|
11
17
|
this.flowcontext = this.context().flow;
|
|
12
18
|
this.devices = JSON.parse( config.devices ?? "{}" );
|
|
13
|
-
this.counterMode = config.counterMode
|
|
19
|
+
this.counterMode = config.counterMode ?? "none";
|
|
14
20
|
this.statusPrefix = config.statusPrefix ? config.statusPrefix+'/' : "";
|
|
15
21
|
this.eventPrefix = config.eventPrefix ? config.eventPrefix +'/' : "";
|
|
16
22
|
this.contextVar = config.contextVar ?? "bthome";
|
|
@@ -124,18 +130,18 @@ module.exports = function(RED) {
|
|
|
124
130
|
{
|
|
125
131
|
item.data = {};
|
|
126
132
|
}
|
|
127
|
-
switch(
|
|
133
|
+
switch( counter[name] )
|
|
128
134
|
{
|
|
129
|
-
case
|
|
135
|
+
case undefined:
|
|
130
136
|
counter[name] = 1;
|
|
131
137
|
item.data[name] = value;
|
|
132
138
|
break;
|
|
133
|
-
case
|
|
134
|
-
case "number":
|
|
135
|
-
case "string":
|
|
139
|
+
case 1:
|
|
136
140
|
item.data[name] = [ item.data[name] ];
|
|
137
141
|
// fall through
|
|
138
|
-
case
|
|
142
|
+
case 2:
|
|
143
|
+
case 3:
|
|
144
|
+
case 4:
|
|
139
145
|
counter[name]++;
|
|
140
146
|
item.data[name].push( value );
|
|
141
147
|
break;
|
|
@@ -173,10 +179,19 @@ module.exports = function(RED) {
|
|
|
173
179
|
setData( "dewpoint", rawdata.getInt16() * 0.01 );
|
|
174
180
|
break;
|
|
175
181
|
case 0x0C:
|
|
176
|
-
|
|
182
|
+
if( node.batteryState )
|
|
183
|
+
{
|
|
184
|
+
setData( "voltage", rawdata.getUInt16() * 0.001 );
|
|
185
|
+
delete item.voltage;
|
|
186
|
+
}
|
|
187
|
+
else
|
|
188
|
+
{
|
|
189
|
+
item.voltage = rawdata.getUInt16() * 0.001;
|
|
190
|
+
delete item.data?.voltage;
|
|
191
|
+
}
|
|
177
192
|
break;
|
|
178
193
|
case 0x20:
|
|
179
|
-
setData( "
|
|
194
|
+
setData( "moisture", Boolean( rawdata.getUInt8() ) );
|
|
180
195
|
break;
|
|
181
196
|
case 0x21:
|
|
182
197
|
events.pushEvent( "motion", rawdata.getEnum( ["","motion"] ) );
|
|
@@ -185,13 +200,15 @@ module.exports = function(RED) {
|
|
|
185
200
|
setData( "vibration", Boolean( rawdata.getUInt8() ) );
|
|
186
201
|
break;
|
|
187
202
|
case 0x2D:
|
|
203
|
+
{
|
|
188
204
|
let state = rawdata.getUInt8();
|
|
189
|
-
if( item.typeId ===
|
|
205
|
+
if( item.typeId === TypeIds.bluDW )
|
|
190
206
|
{
|
|
191
207
|
state = Boolean( state );
|
|
192
208
|
}
|
|
193
209
|
setData( "state", state );
|
|
194
210
|
break;
|
|
211
|
+
}
|
|
195
212
|
case 0x2E:
|
|
196
213
|
setData( "humidity", rawdata.getUInt8() );
|
|
197
214
|
break;
|
|
@@ -199,14 +216,21 @@ module.exports = function(RED) {
|
|
|
199
216
|
events.pushEvent( "button", rawdata.getEnum( ["","S","SS","SSS","L"] ) );
|
|
200
217
|
break;
|
|
201
218
|
case 0x3C:
|
|
202
|
-
|
|
219
|
+
{
|
|
220
|
+
const dimmer = rawdata.getUInt8();
|
|
221
|
+
const data = rawdata.getUInt8();
|
|
222
|
+
events.pushEvent( "dimmer", "dimmer", dimmer==1 ? data : -data );
|
|
203
223
|
break;
|
|
224
|
+
}
|
|
204
225
|
case 0x3F:
|
|
205
226
|
setData( "tilt", rawdata.getInt16() * 0.1 );
|
|
206
227
|
break;
|
|
207
228
|
case 0x40:
|
|
208
|
-
|
|
229
|
+
{
|
|
230
|
+
const distance = rawdata.getUInt16();
|
|
231
|
+
setData( "distance", distance != 0 ? distance : null );
|
|
209
232
|
break;
|
|
233
|
+
}
|
|
210
234
|
case 0x44:
|
|
211
235
|
setData( "wind", rawdata.getUInt16() * 0.01 );
|
|
212
236
|
break;
|
|
@@ -216,6 +240,9 @@ module.exports = function(RED) {
|
|
|
216
240
|
case 0x46:
|
|
217
241
|
setData( "uv", rawdata.getUInt8() * 0.1 );
|
|
218
242
|
break;
|
|
243
|
+
case 0x59:
|
|
244
|
+
setData( "count", rawdata.getInt8() );
|
|
245
|
+
break;
|
|
219
246
|
case 0x5E:
|
|
220
247
|
setData( "direction", rawdata.getUInt16() * 0.01 );
|
|
221
248
|
break;
|
|
@@ -223,7 +250,7 @@ module.exports = function(RED) {
|
|
|
223
250
|
setData( "precipitation", rawdata.getUInt16() * 0.1 );
|
|
224
251
|
break;
|
|
225
252
|
case 0x60:
|
|
226
|
-
setData( "channel", rawdata.getUInt8() );
|
|
253
|
+
setData( "channel", rawdata.getUInt8() + 1 );
|
|
227
254
|
break;
|
|
228
255
|
case 0xF0:
|
|
229
256
|
item.typeId = rawdata.getUInt16();
|
|
@@ -248,7 +275,11 @@ module.exports = function(RED) {
|
|
|
248
275
|
rawdata.reset();
|
|
249
276
|
}
|
|
250
277
|
}
|
|
251
|
-
|
|
278
|
+
if( item.typeId === TypeIds.bluRemote && item.data?.tilt )
|
|
279
|
+
{
|
|
280
|
+
events.pushEvent( "rotation", "rotation", item.data.tilt );
|
|
281
|
+
delete item.data.tilt;
|
|
282
|
+
}
|
|
252
283
|
}
|
|
253
284
|
|
|
254
285
|
function checkPid()
|
|
@@ -291,7 +322,7 @@ module.exports = function(RED) {
|
|
|
291
322
|
node.status( name );
|
|
292
323
|
send( [
|
|
293
324
|
item.data ? { topic:node.statusPrefix+name, payload:item.data } : null,
|
|
294
|
-
events.eventMessages( name )
|
|
325
|
+
events.eventMessages( name, item.data?.channel ?? null )
|
|
295
326
|
] );
|
|
296
327
|
}
|
|
297
328
|
|
|
@@ -302,8 +333,8 @@ module.exports = function(RED) {
|
|
|
302
333
|
const encrypted = Boolean( dib & 0x1 );
|
|
303
334
|
const version = dib >> 5;
|
|
304
335
|
let pid = null;
|
|
305
|
-
const events = new BtEvent( node.eventPrefix );
|
|
306
336
|
let item = node.data[name];
|
|
337
|
+
let events;
|
|
307
338
|
|
|
308
339
|
try
|
|
309
340
|
{
|
|
@@ -317,6 +348,7 @@ module.exports = function(RED) {
|
|
|
317
348
|
{
|
|
318
349
|
decryptMsg();
|
|
319
350
|
}
|
|
351
|
+
events = new BtEvent( node.eventPrefix, item );
|
|
320
352
|
decodeMsg();
|
|
321
353
|
if( checkPid() )
|
|
322
354
|
{
|