iobroker.zigbee 2.0.0 → 2.0.2
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 +40 -10
- package/admin/admin.js +312 -125
- package/admin/img/PTM 215Z.png +0 -0
- package/admin/img/group_0.png +0 -0
- package/admin/img/group_x.png +0 -0
- package/admin/img/philips_hue_lom001.png +0 -0
- package/admin/index_m.html +95 -45
- package/admin/tab_m.html +116 -48
- package/docs/de/img/Zigbee_config_de.png +0 -0
- package/docs/de/img/Zigbee_tab_de.png +0 -0
- package/docs/de/readme.md +21 -28
- package/docs/en/img/Zigbee_config_en.png +0 -0
- package/docs/en/img/Zigbee_tab_en.png +0 -0
- package/docs/tutorial/groups-1.png +0 -0
- package/docs/tutorial/groups-2.png +0 -0
- package/docs/tutorial/tab-dev-1.png +0 -0
- package/io-package.json +55 -41
- package/lib/binding.js +1 -1
- package/lib/colors.js +7 -0
- package/lib/commands.js +136 -20
- package/lib/developer.js +0 -0
- package/lib/devices.js +88 -74
- package/lib/exclude.js +30 -54
- package/lib/exposes.js +247 -290
- package/lib/groups.js +84 -29
- package/lib/localConfig.js +301 -0
- package/lib/ota.js +5 -4
- package/lib/statescontroller.js +452 -185
- package/lib/utils.js +5 -3
- package/lib/zbDeviceAvailability.js +16 -30
- package/lib/zbDeviceConfigure.js +55 -28
- package/lib/zbDeviceEvent.js +2 -13
- package/lib/zigbeecontroller.js +335 -214
- package/main.js +181 -65
- package/package.json +8 -7
package/lib/devices.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const states = require('./states.js').states;
|
|
4
4
|
const utils = require('./utils.js');
|
|
5
5
|
const rgb = require('./rgb.js');
|
|
6
|
-
const applyExposes = require('./exposes.js')
|
|
6
|
+
const {applyExposes, applyExposeForDevice} = require('./exposes.js');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
// return list of changing states when incoming state is changed
|
|
@@ -599,17 +599,7 @@ function states_with_epname(entity, states) {
|
|
|
599
599
|
return devstates;
|
|
600
600
|
}
|
|
601
601
|
|
|
602
|
-
const
|
|
603
|
-
/* {
|
|
604
|
-
models: ['WXKG01LM'],
|
|
605
|
-
icon: 'img/xiaomi_wireless_switch.png',
|
|
606
|
-
states: [
|
|
607
|
-
states.click, states.double_click, states.triple_click, states.quad_click,
|
|
608
|
-
states.many_click, states.long_click, states.voltage, states.battery,
|
|
609
|
-
states.long_press,
|
|
610
|
-
],
|
|
611
|
-
},
|
|
612
|
-
*/
|
|
602
|
+
const legacy_devices = [
|
|
613
603
|
{
|
|
614
604
|
models: ['WXKG11LM'],
|
|
615
605
|
icon: 'img/aqara_switch.png',
|
|
@@ -655,9 +645,9 @@ const devices = [
|
|
|
655
645
|
models: ['WXKG02LM', 'WXKG02LM_rev2'],
|
|
656
646
|
icon: 'img/86sw2.png',
|
|
657
647
|
states: [
|
|
658
|
-
states.
|
|
659
|
-
states.
|
|
660
|
-
states.
|
|
648
|
+
states.lumi_left_click, states.lumi_right_click, states.lumi_both_click,
|
|
649
|
+
states.lumi_left_click_long, states.lumi_right_click_long, states.lumi_left_click_double, states.lumi_right_click_double,
|
|
650
|
+
states.lumi_both_click_long, states.lumi_both_click_double, states.voltage, states.battery
|
|
661
651
|
],
|
|
662
652
|
},
|
|
663
653
|
{
|
|
@@ -3061,56 +3051,14 @@ const devices = [
|
|
|
3061
3051
|
icon: 'img/ICZB-RM11S.png',
|
|
3062
3052
|
states: generator.icasa_remote,
|
|
3063
3053
|
},
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
{
|
|
3067
|
-
models: ['LED1923R5/LED1925G6'],
|
|
3068
|
-
icon: 'img/LED1923R5.png',
|
|
3069
|
-
},
|
|
3070
|
-
{
|
|
3071
|
-
models: ['E1812'],
|
|
3072
|
-
icon: 'img/ikea_E1812.png',
|
|
3073
|
-
},
|
|
3074
|
-
{
|
|
3075
|
-
models: ['WHD02'],
|
|
3076
|
-
icon: 'img/WHD02.png',
|
|
3077
|
-
},
|
|
3078
|
-
{
|
|
3079
|
-
models: ['R7060'],
|
|
3080
|
-
icon: 'img/R7060.png',
|
|
3081
|
-
},
|
|
3082
|
-
{
|
|
3083
|
-
models: ['929001821618'],
|
|
3084
|
-
icon: 'img/philips_hue_ambiance.png',
|
|
3085
|
-
},
|
|
3086
|
-
{
|
|
3087
|
-
models: ['14153905L'],
|
|
3088
|
-
icon: 'img/14153905L.png',
|
|
3089
|
-
},
|
|
3090
|
-
{
|
|
3091
|
-
models: ['HG06338'],
|
|
3092
|
-
icon: 'img/HG06338.png',
|
|
3093
|
-
},
|
|
3094
|
-
{
|
|
3095
|
-
models: ['81855'],
|
|
3096
|
-
icon: 'img/81855.png',
|
|
3097
|
-
},
|
|
3098
|
-
{
|
|
3099
|
-
models: ['TI0001-cover'],
|
|
3100
|
-
icon: 'img/TI0001-cover.png',
|
|
3101
|
-
},
|
|
3102
|
-
{
|
|
3103
|
-
models: ['E1603/E1702/E1708'],
|
|
3104
|
-
icon: 'img/ikea_control_outlet.png',
|
|
3105
|
-
},
|
|
3106
|
-
{
|
|
3107
|
-
models: ['E2204'],
|
|
3108
|
-
icon: 'img/E2204.png',
|
|
3109
|
-
},
|
|
3054
|
+
];
|
|
3055
|
+
const devices = [
|
|
3110
3056
|
{
|
|
3111
|
-
models: ['
|
|
3112
|
-
icon: 'img/
|
|
3113
|
-
|
|
3057
|
+
models: ['group'],
|
|
3058
|
+
icon: 'img/group_0.png',
|
|
3059
|
+
states: states.groupStates,
|
|
3060
|
+
linkedStates: [comb.brightnessAndState],
|
|
3061
|
+
}
|
|
3114
3062
|
];
|
|
3115
3063
|
|
|
3116
3064
|
const commonStates = [
|
|
@@ -3121,27 +3069,44 @@ const commonStates = [
|
|
|
3121
3069
|
states.send_payload,
|
|
3122
3070
|
];
|
|
3123
3071
|
|
|
3072
|
+
const DevicesByModel = new Map();
|
|
3073
|
+
const LegacyDevicesByModel = new Map();
|
|
3074
|
+
|
|
3124
3075
|
const groupStates = [states.brightness_step].concat(lightStatesWithColor);
|
|
3125
3076
|
|
|
3126
3077
|
function getByModel() {
|
|
3127
|
-
|
|
3078
|
+
DevicesByModel.clear();
|
|
3128
3079
|
for (const device of devices) {
|
|
3129
3080
|
for (const model of device.models) {
|
|
3130
3081
|
const stripModel = model.replace(/\0.*$/g, '').trim();
|
|
3131
|
-
|
|
3082
|
+
DevicesByModel.set(stripModel, device);
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
LegacyDevicesByModel.clear();
|
|
3086
|
+
for (const device of legacy_devices) {
|
|
3087
|
+
for (const model of device.models) {
|
|
3088
|
+
const stripModel = model.replace(/\0.*$/g, '').trim();
|
|
3089
|
+
LegacyDevicesByModel.set(stripModel, device);
|
|
3132
3090
|
}
|
|
3133
3091
|
}
|
|
3134
|
-
return
|
|
3092
|
+
return DevicesByModel;
|
|
3135
3093
|
}
|
|
3136
3094
|
|
|
3137
3095
|
removeEmptyStates(devices);
|
|
3138
3096
|
|
|
3139
|
-
function fillStatesWithExposes(
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
applyExposes(devices,
|
|
3097
|
+
function fillStatesWithExposes(logger) {
|
|
3098
|
+
if (DevicesByModel.size <1) getByModel();
|
|
3099
|
+
return;
|
|
3100
|
+
// applyExposes(devices, DevicesByModel, logger);
|
|
3101
|
+
//removeEmptyStates(devices);
|
|
3102
|
+
}
|
|
3143
3103
|
|
|
3104
|
+
async function addExposeToDevices(device, logger, model) {
|
|
3105
|
+
const s = DevicesByModel.size;
|
|
3106
|
+
if (s < 1) getByModel();
|
|
3107
|
+
await applyExposeForDevice(devices, DevicesByModel, device, logger, model);
|
|
3144
3108
|
removeEmptyStates(devices);
|
|
3109
|
+
return (DevicesByModel.size != s);
|
|
3145
3110
|
}
|
|
3146
3111
|
|
|
3147
3112
|
// remove empty states
|
|
@@ -3153,17 +3118,66 @@ function removeEmptyStates(devices) {
|
|
|
3153
3118
|
}
|
|
3154
3119
|
}
|
|
3155
3120
|
|
|
3156
|
-
function findModel(model) {
|
|
3157
|
-
const
|
|
3121
|
+
function findModel(model, legacy) {
|
|
3122
|
+
const src = (legacy ? LegacyDevicesByModel : DevicesByModel)
|
|
3123
|
+
if (src.size <1) getByModel();
|
|
3158
3124
|
const stripModel = (model) ? model.replace(/\0.*$/g, '').trim() : '';
|
|
3159
|
-
return
|
|
3125
|
+
return src.get(stripModel);
|
|
3126
|
+
}
|
|
3127
|
+
|
|
3128
|
+
|
|
3129
|
+
|
|
3130
|
+
function fillDevicesForLegacy(paired) {
|
|
3131
|
+
devices.clear();
|
|
3132
|
+
for (const candidate in legacy_devices) {
|
|
3133
|
+
for (const model in candidate.models) {
|
|
3134
|
+
if (paired.indexOf(model) >= 0) devices.push(candidate);
|
|
3135
|
+
break;
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3139
|
+
|
|
3140
|
+
function pairedLegacyDevices(candidates) {
|
|
3141
|
+
const rv = [];
|
|
3142
|
+
for (const candidate in legacy_devices) {
|
|
3143
|
+
for (const model in candidates.models) {
|
|
3144
|
+
if (candidate.models.contains(model)) rv.push(model);
|
|
3145
|
+
break;
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
3148
|
+
return rv;
|
|
3149
|
+
}
|
|
3150
|
+
|
|
3151
|
+
function setLegacyDevices(legacyModels) {
|
|
3152
|
+
const legacyByModel = new Map();
|
|
3153
|
+
for (const device of legacy_devices) {
|
|
3154
|
+
for (const model of device.models) {
|
|
3155
|
+
const stripModel = model.replace(/\0.*$/g, '').trim();
|
|
3156
|
+
legacyByModel.set(stripModel, device);
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
legacyModels.forEach((model) => {
|
|
3160
|
+
const stripModel = model.replace(/\0.*$/g, '').trim();
|
|
3161
|
+
const dev = legacyByModel.get(stripModel);
|
|
3162
|
+
if (dev) devices.push(dev);
|
|
3163
|
+
})
|
|
3164
|
+
}
|
|
3165
|
+
|
|
3166
|
+
function getIconforLegacyModel(model) {
|
|
3167
|
+
|
|
3160
3168
|
}
|
|
3161
3169
|
|
|
3162
3170
|
module.exports = {
|
|
3163
3171
|
devices,
|
|
3172
|
+
legacy_devices,
|
|
3164
3173
|
commonStates,
|
|
3165
3174
|
groupStates,
|
|
3166
3175
|
groupsState: states.groups,
|
|
3167
3176
|
fillStatesWithExposes,
|
|
3177
|
+
addExposeToDevices,
|
|
3178
|
+
getByModel,
|
|
3168
3179
|
findModel,
|
|
3180
|
+
fillDevicesForLegacy,
|
|
3181
|
+
pairedLegacyDevices,
|
|
3182
|
+
setLegacyDevices
|
|
3169
3183
|
};
|
package/lib/exclude.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
const devicedefinitions = require('./devices');
|
|
2
3
|
|
|
3
4
|
class Exclude {
|
|
4
5
|
constructor(adapter) {
|
|
@@ -9,6 +10,7 @@ class Exclude {
|
|
|
9
10
|
start(zbController, stController) {
|
|
10
11
|
this.zbController = zbController;
|
|
11
12
|
this.stController = stController;
|
|
13
|
+
this.localConfig = stController.localConfig;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
stop() {
|
|
@@ -52,6 +54,12 @@ class Exclude {
|
|
|
52
54
|
this.adapter.sendTo(obj.from, obj.command, exclude, obj.callback));
|
|
53
55
|
}
|
|
54
56
|
break;
|
|
57
|
+
case 'getExcludable':
|
|
58
|
+
if (obj && obj.message && typeof obj.message === 'object') {
|
|
59
|
+
this.getExcludable(exclude =>
|
|
60
|
+
this.adapter.sendTo(obj.from, obj.command, exclude, obj.callback));
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
55
63
|
case 'delExclude':
|
|
56
64
|
if (obj && obj.message) {
|
|
57
65
|
this.delExclude(obj.from, obj.command, obj.message, err =>
|
|
@@ -74,7 +82,7 @@ class Exclude {
|
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
extractExcludeId(stateId) {
|
|
77
|
-
return stateId.replace(`${this.adapter.namespace}.
|
|
85
|
+
return stateId.replace(`${this.adapter.namespace}.info.legacy.`, '');
|
|
78
86
|
}
|
|
79
87
|
|
|
80
88
|
getExcludeName(devName, stateId) {
|
|
@@ -83,18 +91,10 @@ class Exclude {
|
|
|
83
91
|
|
|
84
92
|
async addExclude(from, command, params, callback) {
|
|
85
93
|
try {
|
|
86
|
-
this.
|
|
94
|
+
//this.warn('addExclude message: ' + JSON.stringify(params));
|
|
87
95
|
const exclude_mod = params.exclude_model.common.type;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
this.adapter.setObjectNotExists(stateId,
|
|
91
|
-
{
|
|
92
|
-
type: 'state',
|
|
93
|
-
common: {name: exclude_mod},
|
|
94
|
-
},
|
|
95
|
-
() => this.adapter.setState(stateId, exclude_mod, true, () =>
|
|
96
|
-
callback()),
|
|
97
|
-
);
|
|
96
|
+
this.localConfig.updateLocalOverride(exclude_mod, exclude_mod, 'legacy', exclude_mod, true);
|
|
97
|
+
callback({});
|
|
98
98
|
} catch (error) {
|
|
99
99
|
this.error(`Failed to addExclude ${error.stack}`);
|
|
100
100
|
throw new Error(`Failed to addExclude ${error.stack}`);
|
|
@@ -104,58 +104,34 @@ class Exclude {
|
|
|
104
104
|
async delExclude(from, command, exclude_id, callback) {
|
|
105
105
|
try {
|
|
106
106
|
this.debug(`delExclude message: ${JSON.stringify(exclude_id)}`);
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
.then(async (stateV) => {
|
|
110
|
-
this.debug(`found state: ${JSON.stringify(stateV)}`);
|
|
111
|
-
this.adapter.deleteState(null, 'exclude', exclude_id, async () =>
|
|
112
|
-
callback());
|
|
113
|
-
});
|
|
107
|
+
this.localConfig.updateLocalOverride(exclude_id, exclude_id, 'legacy', '', true);
|
|
108
|
+
callback({});
|
|
114
109
|
} catch (error) {
|
|
115
110
|
this.error(`Failed to delExclude ${error.stack}`);
|
|
116
111
|
throw new Error(`Failed to delExclude ${error.stack}`);
|
|
117
112
|
}
|
|
118
113
|
}
|
|
119
114
|
|
|
120
|
-
getExclude(callback) {
|
|
115
|
+
async getExclude(callback) {
|
|
121
116
|
try {
|
|
122
|
-
const exclude =
|
|
123
|
-
|
|
124
|
-
if (!err && states) {
|
|
125
|
-
const exc = [];
|
|
126
|
-
states.forEach(state => {
|
|
127
|
-
if (state._id.startsWith(`${this.adapter.namespace}.exclude`)) {
|
|
128
|
-
exc.push(new Promise(resolve =>
|
|
129
|
-
this.adapter.getStateAsync(state._id)
|
|
130
|
-
.then(stateVa => {
|
|
131
|
-
if (stateVa !== null) {
|
|
132
|
-
const val = {
|
|
133
|
-
id: this.extractExcludeId(state._id),
|
|
134
|
-
name: stateVa.val
|
|
135
|
-
};
|
|
136
|
-
if (this.extractExcludeId(state._id) !== 'all') {
|
|
137
|
-
exclude.push(val);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
resolve();
|
|
141
|
-
})));
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
return Promise.all(exc)
|
|
145
|
-
.then(() => {
|
|
146
|
-
const arrExclude = JSON.stringify(exclude);
|
|
147
|
-
this.debug(`getExclude result: ${arrExclude}`);
|
|
148
|
-
this.adapter.setState('exclude.all', arrExclude, true, () =>
|
|
149
|
-
callback(exclude));
|
|
150
|
-
});
|
|
151
|
-
} else {
|
|
152
|
-
this.debug(`getExclude result: ${JSON.stringify(exclude)}`);
|
|
153
|
-
callback(exclude);
|
|
154
|
-
}
|
|
155
|
-
});
|
|
117
|
+
const exclude = this.localConfig.getOverridesWithKey('legacy', true)
|
|
118
|
+
callback({legacy: exclude});
|
|
156
119
|
} catch (error) {
|
|
157
120
|
this.error(`Failed to getExclude ${error.stack}`);
|
|
121
|
+
callback({error: 'unable to get excludes' });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async getExcludable(callback) {
|
|
126
|
+
const devices = this.zbController.getClients();
|
|
127
|
+
const excludables = [];
|
|
128
|
+
for (const device of devices) {
|
|
129
|
+
const obj = await this.adapter.getObjectAsync(device.ieeeAddr.substr(2));
|
|
130
|
+
if (obj && obj.common && obj.common.type) {
|
|
131
|
+
excludables.push(obj.common.tyoe);
|
|
132
|
+
}
|
|
158
133
|
}
|
|
134
|
+
callback(devices.pairedLegacyDevices(excludables));
|
|
159
135
|
}
|
|
160
136
|
}
|
|
161
137
|
|