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/README.md +16 -0
- package/admin/i18n/de/translations.json +8 -4
- package/admin/i18n/en/translations.json +8 -4
- package/admin/i18n/es/translations.json +8 -4
- package/admin/i18n/fr/translations.json +8 -4
- package/admin/i18n/it/translations.json +8 -4
- package/admin/i18n/nl/translations.json +8 -4
- package/admin/i18n/pl/translations.json +8 -4
- package/admin/i18n/pt/translations.json +8 -4
- package/admin/i18n/ru/translations.json +8 -4
- package/admin/i18n/zh-cn/translations.json +8 -4
- package/admin/jsonConfig.json +58 -9
- package/io-package.json +27 -4
- package/lib/check.js +37 -0
- package/lib/deviceController.js +182 -0
- package/lib/exposes.js +34 -3
- package/lib/messages.js +18 -0
- package/lib/states.js +2 -0
- package/lib/statesController.js +127 -0
- package/lib/utils.js +20 -11
- package/lib/z2mController.js +80 -0
- package/main.js +80 -378
- package/package.json +9 -5
- package/lib/groups.js +0 -68
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
exports
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
+
};
|