iobroker.zigbee2mqtt 0.2.0 → 1.0.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/lib/states.js CHANGED
@@ -5447,6 +5447,7 @@ const states = {
5447
5447
  write: false,
5448
5448
  read: true,
5449
5449
  type: 'boolean',
5450
+ def: false,
5450
5451
  isEvent: true,
5451
5452
  getter: payload => (payload.action === 'brightness_move_up') ? true : undefined,
5452
5453
  },
@@ -5471,6 +5472,7 @@ const states = {
5471
5472
  write: false,
5472
5473
  read: true,
5473
5474
  type: 'boolean',
5475
+ def: false,
5474
5476
  isEvent: true,
5475
5477
  getter: payload => (payload.action === 'brightness_move_down') ? true : undefined,
5476
5478
  },
@@ -0,0 +1,127 @@
1
+ const utils = require('./utils');
2
+ const incStatsQueue = [];
3
+
4
+ class StatesController {
5
+ constructor(adapter, deviceCache, groupCache, debugDevices) {
6
+ this.adapter = adapter;
7
+ this.groupCache = groupCache;
8
+ this.deviceCache = deviceCache;
9
+ this.debugDevices = debugDevices;
10
+ }
11
+
12
+ async processDeviceMessage(messageObj) {
13
+ // Is payload present?
14
+ if (messageObj.payload == '') {
15
+ return;
16
+ }
17
+
18
+ const device = this.groupCache.concat(this.deviceCache).find(x => x.id == messageObj.topic);
19
+ if (device) {
20
+ try {
21
+ this.setDeviceState(messageObj, device);
22
+ } catch (error) {
23
+ this.adapter.log.error(error);
24
+ }
25
+ }
26
+ else {
27
+ incStatsQueue[incStatsQueue.length] = messageObj;
28
+ this.adapter.log.debug(`Device: ${messageObj.topic} not found, queue state in incStatsQueue!`);
29
+ }
30
+ }
31
+
32
+ async setDeviceState(messageObj, device) {
33
+ if (this.debugDevices.includes(device.ieee_address)) {
34
+ this.adapter.log.warn(`--->>> fromZ2M -> ${device.ieee_address} states: ${JSON.stringify(messageObj)}`);
35
+ }
36
+
37
+ for (const [key, value] of Object.entries(messageObj.payload)) {
38
+ let states;
39
+ if (key == 'action') {
40
+ states = device.states.filter(x => (x.prop && x.prop == key));
41
+ } else {
42
+ states = device.states.filter(x => (x.prop && x.prop == key) || x.id == key);
43
+ }
44
+
45
+ for (const state of states) {
46
+ if (!state) {
47
+ continue;
48
+ }
49
+
50
+ const stateName = `${device.ieee_address}.${state.id}`;
51
+
52
+ try {
53
+ if (state.isEvent) {
54
+ if (state.getter) {
55
+ await this.setStateWithTimeoutAsync(stateName, state.getter(messageObj.payload), 300);
56
+ }
57
+ else {
58
+ await this.setStateWithTimeoutAsync(stateName, value, 300);
59
+ }
60
+ }
61
+ else {
62
+ if (state.getter) {
63
+ await this.setStateAsync(stateName, state.getter(messageObj.payload));
64
+ }
65
+ else {
66
+ await this.setStateAsync(stateName, value);
67
+ }
68
+ }
69
+ } catch (err) {
70
+ //this.adapter.log.warn(`Can not set ${stateName}`);
71
+ incStatsQueue[incStatsQueue.length] = messageObj;
72
+ this.adapter.log.debug(`Can not set ${stateName} for ${messageObj.topic}, queue state in incStatsQueue!`);
73
+ }
74
+ }
75
+ }
76
+ }
77
+
78
+ async setStateAsync(stateName, value) {
79
+ if (value !== undefined) {
80
+ await this.adapter.setStateAsync(stateName, value, true);
81
+ }
82
+ }
83
+
84
+ async setStateWithTimeoutAsync(stateName, value, timeout) {
85
+ if (value !== undefined) {
86
+ await this.adapter.setStateAsync(stateName, value, true);
87
+ setTimeout(() => {
88
+ this.adapter.setStateAsync(stateName, !value, true);
89
+ }, timeout);
90
+ }
91
+ }
92
+
93
+ async processQueue() {
94
+ const oldIncStatsQueue = [];
95
+ utils.moveArray(incStatsQueue, oldIncStatsQueue);
96
+ while (oldIncStatsQueue.length > 0) {
97
+ this.processDeviceMessage(oldIncStatsQueue.shift());
98
+ }
99
+ }
100
+
101
+ async subscribeWritableStates() {
102
+ await this.adapter.unsubscribeObjectsAsync('*');
103
+ for (const device of this.groupCache.concat(this.deviceCache)) {
104
+ for (const state of device.states) {
105
+ if (state.write == true) {
106
+ this.adapter.subscribeStatesAsync(`${device.ieee_address}.${state.id}`);
107
+ }
108
+ }
109
+ }
110
+ this.adapter.subscribeStatesAsync('info.debugmessages');
111
+ this.adapter.subscribeStatesAsync('info.logfilter');
112
+ }
113
+
114
+ async setAllAvailableToFalse() {
115
+ for (const device of this.deviceCache) {
116
+ for (const state of device.states) {
117
+ if (state.id == 'available') {
118
+ await this.adapter.setStateAsync(`${device.ieee_address}.${state.id}`, false, true);
119
+ }
120
+ }
121
+ }
122
+ }
123
+ }
124
+
125
+ module.exports = {
126
+ StatesController
127
+ };
package/lib/utils.js CHANGED
@@ -118,14 +118,23 @@ function clearArray(array) {
118
118
  }
119
119
  }
120
120
 
121
- exports.bulbLevelToAdapterLevel = bulbLevelToAdapterLevel;
122
- exports.adapterLevelToBulbLevel = adapterLevelToBulbLevel;
123
- exports.bytesArrayToWordArray = bytesArrayToWordArray;
124
- exports.toMired = toMired;
125
- exports.miredKelvinConversion = miredKelvinConversion;
126
- exports.decimalToHex = decimalToHex;
127
- exports.getZbId = getZbId;
128
- exports.getAdId = getAdId;
129
- exports.removeDeviceByIeee = removeDeviceByIeee;
130
- exports.getDeviceIcon = getDeviceIcon;
131
- exports.clearArray = clearArray;
121
+ function moveArray(source, target) {
122
+ while (source.length > 0) {
123
+ target.push(source.shift());
124
+ }
125
+ }
126
+
127
+ module.exports = {
128
+ bulbLevelToAdapterLevel: bulbLevelToAdapterLevel,
129
+ adapterLevelToBulbLevel: adapterLevelToBulbLevel,
130
+ bytesArrayToWordArray: bytesArrayToWordArray,
131
+ toMired: toMired,
132
+ miredKelvinConversion: miredKelvinConversion,
133
+ decimalToHex: decimalToHex,
134
+ getZbId: getZbId,
135
+ getAdId: getAdId,
136
+ removeDeviceByIeee: removeDeviceByIeee,
137
+ getDeviceIcon: getDeviceIcon,
138
+ clearArray: clearArray,
139
+ moveArray: moveArray,
140
+ };
@@ -0,0 +1,80 @@
1
+ class Z2mController {
2
+ constructor(adapter, deviceCache, groupCache, logfilter) {
3
+ this.adapter = adapter;
4
+ this.groupCache = groupCache;
5
+ this.deviceCache = deviceCache;
6
+ this.logfilter = logfilter;
7
+ }
8
+
9
+ async createZ2MMessage(id, state) {
10
+ const splitedID = id.split('.');
11
+ if (splitedID.length < 4) {
12
+ this.adapter.log.warn(`state ${id} not valid`);
13
+ return;
14
+ }
15
+
16
+ const ieee_address = splitedID[2];
17
+ const stateName = splitedID[3];
18
+
19
+ const device = this.groupCache.concat(this.deviceCache).find(d => d.ieee_address == ieee_address);
20
+ if (!device) {
21
+ return;
22
+ }
23
+
24
+ const deviceState = device.states.find(s => s.id == stateName);
25
+ if (!deviceState) {
26
+ return;
27
+ }
28
+
29
+ let stateVal = state.val;
30
+ if (deviceState.setter) {
31
+ stateVal = deviceState.setter(state.val);
32
+ }
33
+
34
+ let stateID = deviceState.id;
35
+ if (deviceState.prop) {
36
+ stateID = deviceState.prop;
37
+ }
38
+
39
+ let topic = `${device.ieee_address}/set`;
40
+ if (device.ieee_address.includes('group_')) {
41
+ topic = `${device.id}/set`;
42
+ }
43
+
44
+ const controlObj = {
45
+ payload: {
46
+ [stateID]: stateVal
47
+ },
48
+ topic: topic
49
+ };
50
+ // set stats with the mentioned role or ids always immediately to ack = true, because these are not reported back by Zigbee2MQTT
51
+ if (['button'].includes(deviceState.role) || ['brightness_move', 'color_temp_move'].includes(stateID)) {
52
+ this.adapter.setState(id, state, true);
53
+ }
54
+
55
+ return controlObj;
56
+ }
57
+
58
+ async proxyZ2MLogs(messageObj) {
59
+ const logMessage = messageObj.payload.message;
60
+ if (this.logfilter.some(x => logMessage.includes(x))) {
61
+ return;
62
+ }
63
+
64
+ const logLevel = messageObj.payload.level;
65
+ switch (logLevel) {
66
+ case 'debug':
67
+ case 'info':
68
+ case 'error':
69
+ this.adapter.log[logLevel](logMessage);
70
+ break;
71
+ case 'warning':
72
+ this.adapter.log.warn(logMessage);
73
+ break;
74
+ }
75
+ }
76
+ }
77
+
78
+ module.exports = {
79
+ Z2mController: Z2mController
80
+ };