zigbee-herdsman-converters 14.0.377 → 14.0.381

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.
@@ -1380,8 +1380,8 @@ const converters = {
1380
1380
  const payload = {
1381
1381
  action: postfixWithEndpointName(`color_move`, msg, model),
1382
1382
  action_color: {
1383
- x: precisionRound(msg.data.colorx / 65535, 3),
1384
- y: precisionRound(msg.data.colory / 65535, 3),
1383
+ x: precisionRound(msg.data.colorx / 65536, 3),
1384
+ y: precisionRound(msg.data.colory / 65536, 3),
1385
1385
  },
1386
1386
  action_transition_time: msg.data.transtime,
1387
1387
  };
@@ -7928,6 +7928,34 @@ const converters = {
7928
7928
  return result;
7929
7929
  },
7930
7930
  },
7931
+ command_stop_move_raw: {
7932
+ cluster: 'lightingColorCtrl',
7933
+ type: 'raw',
7934
+ convert: (model, msg, publish, options, meta) => {
7935
+ // commandStopMove without params
7936
+ if (msg.data[2] !== 71) return;
7937
+ if (hasAlreadyProcessedMessage(msg)) return;
7938
+ const movestop = 'stop';
7939
+ const action = postfixWithEndpointName(`hue_${movestop}`, msg, model);
7940
+ const payload = {action};
7941
+ addActionGroup(payload, msg, model);
7942
+ return payload;
7943
+ },
7944
+ },
7945
+ tuya_multi_action: {
7946
+ cluster: 'genOnOff',
7947
+ type: 'raw',
7948
+ convert: (model, msg, publish, options, meta) => {
7949
+ if (hasAlreadyProcessedMessage(msg, msg.data[2])) return;
7950
+ let action;
7951
+ if (msg.data[2] == 253) {
7952
+ action = {0: 'single', 1: 'double', 2: 'hold'}[msg.data[3]];
7953
+ } else if (msg.data[2] == 252) {
7954
+ action = {0: 'rotate_right', 1: 'rotate_left'}[msg.data[3]];
7955
+ }
7956
+ return {action};
7957
+ },
7958
+ },
7931
7959
  // #endregion
7932
7960
 
7933
7961
  // #region Ignore converters (these message dont need parsing).
@@ -8086,6 +8114,15 @@ const converters = {
8086
8114
  type: ['raw'],
8087
8115
  convert: (model, msg, publish, options, meta) => null,
8088
8116
  },
8117
+ ignore_metering: {
8118
+ /**
8119
+ * When using this converter also add the following to the configure method of the device:
8120
+ * await readMeteringPowerConverterAttributes(endpoint);
8121
+ */
8122
+ cluster: 'seMetering',
8123
+ type: ['attributeReport', 'readResponse'],
8124
+ convert: (model, msg, publish, options, meta) => null,
8125
+ },
8089
8126
  // #endregion
8090
8127
  };
8091
8128
 
@@ -6471,10 +6471,12 @@ const converters = {
6471
6471
  } else {
6472
6472
  throw new Error('Dimmer brightness is out of range 0..255');
6473
6473
  }
6474
- await tuya.sendDataPointEnum(entity, tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.white);
6475
- await tuya.sendDataPointValue(entity, tuya.dataPoints.dimmerLevel, newValue);
6474
+ await tuya.sendDataPoints(entity, [
6475
+ tuya.dpValueFromEnum(tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.white),
6476
+ tuya.dpValueFromIntValue(tuya.dataPoints.dimmerLevel, newValue),
6477
+ ], 'dataRequest', 1);
6476
6478
 
6477
- return {state: {white_brightness: value}};
6479
+ return {state: (key == 'white_brightness') ? {white_brightness: value} : {brightness: value}};
6478
6480
  } else if (key == 'color_temp') {
6479
6481
  const [colorTempMin, colorTempMax] = [250, 454];
6480
6482
  const preset = {
@@ -6496,8 +6498,10 @@ const converters = {
6496
6498
  }
6497
6499
  const data = utils.mapNumberRange(value, colorTempMax, colorTempMin, 0, 1000);
6498
6500
 
6499
- await tuya.sendDataPointEnum(entity, tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.white);
6500
- await tuya.sendDataPointValue(entity, tuya.dataPoints.silvercrestSetColorTemp, data);
6501
+ await tuya.sendDataPoints(entity, [
6502
+ tuya.dpValueFromEnum(tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.white),
6503
+ tuya.dpValueFromIntValue(tuya.dataPoints.silvercrestSetColorTemp, data),
6504
+ ], 'dataRequest', 1);
6501
6505
 
6502
6506
  return {state: {color_temp: value}};
6503
6507
  } else if (key == 'color' || (separateWhite && (key == 'brightness'))) {
@@ -6550,12 +6554,11 @@ const converters = {
6550
6554
  }
6551
6555
 
6552
6556
  // Scale 0-255 to 0-1000 what the device expects.
6553
- if (b) {
6557
+ if (b != null) {
6554
6558
  hsb.b = make4sizedString(utils.mapNumberRange(b, 0, 255, 0, 1000).toString(16));
6555
- } else if (state.brightness) {
6559
+ } else if (state.brightness != null) {
6556
6560
  hsb.b = make4sizedString(utils.mapNumberRange(state.brightness, 0, 255, 0, 1000).toString(16));
6557
6561
  }
6558
-
6559
6562
  return hsb;
6560
6563
  };
6561
6564
 
@@ -6572,15 +6575,18 @@ const converters = {
6572
6575
  data = data.concat(tuya.convertStringToHexArray(hsb.s));
6573
6576
  data = data.concat(tuya.convertStringToHexArray(hsb.b));
6574
6577
 
6575
- await tuya.sendDataPointEnum(entity, tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.color);
6576
- await tuya.sendDataPointStringBuffer(entity, tuya.dataPoints.silvercrestSetColor, data);
6578
+ const commands = [
6579
+ tuya.dpValueFromEnum(tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.color),
6580
+ tuya.dpValueFromStringBuffer(tuya.dataPoints.silvercrestSetColor, data),
6581
+ ];
6577
6582
 
6578
6583
  if (separateWhite && meta.state.white_brightness != undefined) {
6579
6584
  // restore white state
6580
6585
  const newValue = utils.mapNumberRange(meta.state.white_brightness, 0, 255, 0, 1000);
6581
- await tuya.sendDataPointEnum(entity, tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.white);
6582
- await tuya.sendDataPointValue(entity, tuya.dataPoints.dimmerLevel, newValue);
6586
+ commands.push(tuya.dpValueFromEnum(tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.white));
6587
+ commands.push(tuya.dpValueFromIntValue(tuya.dataPoints.dimmerLevel, newValue));
6583
6588
  }
6589
+ await tuya.sendDataPoints(entity, commands, 'dataRequest', 1);
6584
6590
 
6585
6591
  return {state: newState};
6586
6592
  }
package/devices/adeo.js CHANGED
@@ -6,6 +6,18 @@ const tz = require('../converters/toZigbee');
6
6
  const e = exposes.presets;
7
7
 
8
8
  module.exports = [
9
+ {
10
+ zigbeeModel: ['LDSENK01F'],
11
+ model: 'LDSENK01F',
12
+ vendor: 'ADEO',
13
+ description: '10A EU smart plug',
14
+ extend: extend.switch(),
15
+ configure: async (device, coordinatorEndpoint, logger) => {
16
+ const endpoint = device.getEndpoint(1);
17
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
18
+ await reporting.onOff(endpoint);
19
+ },
20
+ },
9
21
  {
10
22
  zigbeeModel: ['LXEK-5'],
11
23
  model: 'HR-C99C-Z-C045',
@@ -29,6 +29,15 @@ const hueExtend = {
29
29
  };
30
30
 
31
31
  module.exports = [
32
+ {
33
+ zigbeeModel: ['LCX004'],
34
+ model: '929002994901',
35
+ vendor: 'Philips',
36
+ description: 'Hue gradient lightstrip',
37
+ meta: {turnsOffAtBrightness1: true},
38
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
39
+ ota: ota.zigbeeOTA,
40
+ },
32
41
  {
33
42
  zigbeeModel: ['929003047501'],
34
43
  model: '929003047501',
@@ -71,7 +71,8 @@ module.exports = [
71
71
  fromZigbee: [fz.battery, fz.command_on, fz.command_off, fz.command_step, fz.command_move, fz.command_stop, fz.command_recall,
72
72
  fz.command_move_hue, fz.command_move_to_color, fz.command_move_to_color_temp],
73
73
  exposes: [e.battery(), e.action(['on', 'off', 'brightness_step_up', 'brightness_step_down', 'brightness_move_up',
74
- 'brightness_move_down', 'brightness_stop', 'recall_1', 'recall_2', 'recall_3'])],
74
+ 'brightness_move_down', 'brightness_stop', 'recall_1', 'recall_2', 'recall_3', 'hue_move', 'color_temperature_move',
75
+ 'color_move', 'hue_stop'])],
75
76
  toZigbee: [],
76
77
  meta: {multiEndpoint: true, battery: {dontDividePercentage: true}},
77
78
  configure: async (device, coordinatorEndpoint) => {
@@ -5,7 +5,10 @@ const ea = exposes.access;
5
5
 
6
6
  module.exports = [
7
7
  {
8
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_6qoazbre'}],
8
+ fingerprint: [
9
+ {modelID: 'TS0601', manufacturerName: '_TZE200_6qoazbre'},
10
+ {modelID: 'TS0601', manufacturerName: '_TZE200_fcooykb4'},
11
+ ],
9
12
  model: 'WZ5_dim',
10
13
  vendor: 'Skydance',
11
14
  description: 'Zigbee & RF 5 in 1 LED controller (DIM mode)',
@@ -17,7 +20,10 @@ module.exports = [
17
20
  ],
18
21
  },
19
22
  {
20
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_gz3n0tzf'}],
23
+ fingerprint: [
24
+ {modelID: 'TS0601', manufacturerName: '_TZE200_gz3n0tzf'},
25
+ {modelID: 'TS0601', manufacturerName: '_TZE200_nthosjmx'},
26
+ ],
21
27
  model: 'WZ5_cct',
22
28
  vendor: 'Skydance',
23
29
  description: 'Zigbee & RF 5 in 1 LED controller (CCT mode)',
@@ -29,7 +35,10 @@ module.exports = [
29
35
  ],
30
36
  },
31
37
  {
32
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_9hghastn'}],
38
+ fingerprint: [
39
+ {modelID: 'TS0601', manufacturerName: '_TZE200_9hghastn'},
40
+ {modelID: 'TS0601', manufacturerName: '_TZE200_9mt3kgn0'},
41
+ ],
33
42
  model: 'WZ5_rgb',
34
43
  vendor: 'Skydance',
35
44
  description: 'Zigbee & RF 5 in 1 LED controller (RGB mode)',
@@ -41,7 +50,10 @@ module.exports = [
41
50
  ],
42
51
  },
43
52
  {
44
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_3thxjahu'}],
53
+ fingerprint: [
54
+ {modelID: 'TS0601', manufacturerName: '_TZE200_3thxjahu'},
55
+ {modelID: 'TS0601', manufacturerName: '_TZE200_g9jdneiu'},
56
+ ],
45
57
  model: 'WZ5_rgbw',
46
58
  vendor: 'Skydance',
47
59
  description: 'Zigbee & RF 5 in 1 LED controller (RGBW mode)',
@@ -56,7 +68,10 @@ module.exports = [
56
68
  meta: {separateWhite: true},
57
69
  },
58
70
  {
59
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_mde0utnv'}],
71
+ fingerprint: [
72
+ {modelID: 'TS0601', manufacturerName: '_TZE200_mde0utnv'},
73
+ {modelID: 'TS0601', manufacturerName: '_TZE200_aa9awrng'},
74
+ ],
60
75
  model: 'WZ5_rgbcct',
61
76
  vendor: 'Skydance',
62
77
  description: 'Zigbee & RF 5 in 1 LED controller (RGB+CCT mode)',
package/devices/tuya.js CHANGED
@@ -12,7 +12,7 @@ const utils = require('../lib/utils');
12
12
 
13
13
  const TS011Fplugs = ['_TZ3000_5f43h46b', '_TZ3000_cphmq0q7', '_TZ3000_dpo1ysak', '_TZ3000_ew3ldmgx', '_TZ3000_gjnozsaz',
14
14
  '_TZ3000_jvzvulen', '_TZ3000_mraovvmm', '_TZ3000_nfnmi125', '_TZ3000_ps3dmato', '_TZ3000_w0qqde0g', '_TZ3000_u5u4cakc',
15
- '_TZ3000_rdtixbnu', '_TZ3000_typdpbpg', '_TZ3000_v1pdxuqq', '_TZ3000_bfn1w0mm'];
15
+ '_TZ3000_rdtixbnu', '_TZ3000_typdpbpg', '_TZ3000_v1pdxuqq'];
16
16
 
17
17
  const tzLocal = {
18
18
  TS0504B_color: {
@@ -162,7 +162,8 @@ module.exports = [
162
162
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_0rn9qhnu'},
163
163
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_bicjqpg4'},
164
164
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_cmaky9gq'},
165
- {modelID: 'TS0505B', manufacturerName: '_TZ3000_tza2vjxx'}],
165
+ {modelID: 'TS0505B', manufacturerName: '_TZ3000_tza2vjxx'},
166
+ {modelID: 'TS0505B', manufacturerName: '_TZ3210_bfwvfyx1'}],
166
167
  model: 'TS0505B',
167
168
  vendor: 'TuYa',
168
169
  description: 'Zigbee RGB+CCT light',
@@ -177,6 +178,7 @@ module.exports = [
177
178
  {
178
179
  fingerprint: [{modelID: 'TS0503B', manufacturerName: '_TZ3000_i8l0nqdu'},
179
180
  {modelID: 'TS0503B', manufacturerName: '_TZ3210_a5fxguxr'},
181
+ {modelID: 'TS0503B', manufacturerName: '_TZ3210_778drfdt'},
180
182
  {modelID: 'TS0503B', manufacturerName: '_TZ3000_g5xawfcq'}],
181
183
  model: 'TS0503B',
182
184
  vendor: 'TuYa',
@@ -187,7 +189,9 @@ module.exports = [
187
189
  },
188
190
  {
189
191
  fingerprint: [{modelID: 'TS0504B', manufacturerName: '_TZ3000_ukuvyhaa'},
190
- {modelID: 'TS0504B', manufacturerName: '_TZ3210_bfvybixd'}, {modelID: 'TS0504B', manufacturerName: '_TZ3210_sroezl0s'}],
192
+ {modelID: 'TS0504B', manufacturerName: '_TZ3210_bfvybixd'},
193
+ {modelID: 'TS0504B', manufacturerName: '_TZ3210_sroezl0s'},
194
+ {modelID: 'TS0504B', manufacturerName: '_TZ3210_1elppmba'}],
191
195
  model: 'TS0504B',
192
196
  vendor: 'TuYa',
193
197
  description: 'Zigbee RGBW light',
@@ -199,7 +203,8 @@ module.exports = [
199
203
  fingerprint: [{modelID: 'TS0501B', manufacturerName: '_TZ3000_4whigl8i'},
200
204
  {modelID: 'TS0501B', manufacturerName: '_TZ3210_4whigl8i'},
201
205
  {modelID: 'TS0501B', manufacturerName: '_TZ3210_9q49basr'},
202
- {modelID: 'TS0501B', manufacturerName: '_TZ3210_grnwgegn'}],
206
+ {modelID: 'TS0501B', manufacturerName: '_TZ3210_grnwgegn'},
207
+ {modelID: 'TS0501B', manufacturerName: '_TZ3210_wuheofsg'}],
203
208
  model: 'TS0501B',
204
209
  description: 'Zigbee light',
205
210
  vendor: 'TuYa',
@@ -309,7 +314,8 @@ module.exports = [
309
314
  ],
310
315
  },
311
316
  {
312
- fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_oiymh3qu'}],
317
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_oiymh3qu'},
318
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_o1jzcxou'}],
313
319
  model: 'TS011F_socket_module',
314
320
  vendor: 'TuYa',
315
321
  description: 'Socket module',
@@ -901,7 +907,7 @@ module.exports = [
901
907
  'Mode of this device, in the `heat` mode the TS0601 will remain continuously heating, i.e. it does not regulate ' +
902
908
  'to the desired temperature. If you want TRV to properly regulate the temperature you need to use mode `auto` ' +
903
909
  'instead setting the desired temperature.')
904
- .withLocalTemperatureCalibration(-30, 30, 0.1, ea.STATE_SET)
910
+ .withLocalTemperatureCalibration(-9, 9, 1, ea.STATE_SET)
905
911
  .withAwayMode().withPreset(['schedule', 'manual', 'boost', 'complex', 'comfort', 'eco']),
906
912
  e.auto_lock(), e.away_mode(), e.away_preset_days(), e.boost_time(), e.comfort_temperature(), e.eco_temperature(), e.force(),
907
913
  e.max_temperature(), e.min_temperature(), e.away_preset_temperature(),
@@ -1116,7 +1122,8 @@ module.exports = [
1116
1122
  {
1117
1123
  fingerprint: [
1118
1124
  {modelID: 'TS011F', manufacturerName: '_TZ3000_hyfvrar3'},
1119
- {modelID: 'TS011F', manufacturerName: '_TZ3000_cymsnfvf'}],
1125
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_cymsnfvf'},
1126
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_bfn1w0mm'}],
1120
1127
  model: 'TS011F_plug_2',
1121
1128
  description: 'Smart plug (without power monitoring)',
1122
1129
  vendor: 'TuYa',
@@ -1831,9 +1838,29 @@ module.exports = [
1831
1838
  model: 'ERS-10TZBVK-AA',
1832
1839
  vendor: 'TuYa',
1833
1840
  description: 'Smart knob',
1834
- fromZigbee: [fz.command_step, fz.command_toggle, fz.command_move_hue],
1835
- toZigbee: [],
1836
- exposes: [e.action(['toggle', 'brightness_step_up', 'brightness_step_down'])],
1841
+ fromZigbee: [
1842
+ fz.command_step, fz.command_toggle, fz.command_move_hue, fz.command_step_color_temperature, fz.command_stop_move_raw,
1843
+ fz.tuya_multi_action, fz.tuya_operation_mode, fz.battery,
1844
+ ],
1845
+ toZigbee: [tz.tuya_operation_mode],
1846
+ exposes: [
1847
+ e.action([
1848
+ 'toggle', 'brightness_step_up', 'brightness_step_down', 'color_temperature_step_up', 'color_temperature_step_down',
1849
+ 'saturation_move', 'hue_move', 'hue_stop', 'single', 'double', 'hold', 'rotate_left', 'rotate_right',
1850
+ ]),
1851
+ exposes.numeric('action_step_size', ea.STATE).withValueMin(0).withValueMax(255),
1852
+ exposes.numeric('action_transition_time', ea.STATE).withUnit('s'),
1853
+ exposes.numeric('action_rate', ea.STATE).withValueMin(0).withValueMax(255),
1854
+ e.battery(),
1855
+ exposes.enum('operation_mode', ea.ALL, ['command', 'event']).withDescription(
1856
+ 'Operation mode: "command" - for group control, "event" - for clicks'),
1857
+ ],
1858
+ configure: async (device, coordinatorEndpoint, logger) => {
1859
+ const endpoint = device.getEndpoint(1);
1860
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
1861
+ await reporting.batteryPercentageRemaining(endpoint);
1862
+ await endpoint.read('genOnOff', ['tuyaOperationMode']);
1863
+ },
1837
1864
  },
1838
1865
  {
1839
1866
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_kzm5w4iz'}],
package/devices/xiaomi.js CHANGED
@@ -1402,7 +1402,8 @@ module.exports = [
1402
1402
  model: 'SSM-U01',
1403
1403
  vendor: 'Xiaomi',
1404
1404
  description: 'Aqara single switch module T1 (with neutral)',
1405
- fromZigbee: [fz.on_off, fz.metering, fz.electrical_measurement, fz.device_temperature, fz.aqara_opple],
1405
+ // Ignore energy metering reports, rely on aqara_opple: https://github.com/Koenkk/zigbee2mqtt/issues/10709
1406
+ fromZigbee: [fz.on_off, fz.electrical_measurement, fz.device_temperature, fz.aqara_opple, fz.ignore_metering],
1406
1407
  exposes: [e.switch(), e.energy(), e.power(), e.device_temperature(), e.power_outage_memory(), e.switch_type()],
1407
1408
  toZigbee: [tz.xiaomi_switch_type, tz.on_off, tz.xiaomi_switch_power_outage_memory],
1408
1409
  configure: async (device, coordinatorEndpoint, logger) => {
package/index.js CHANGED
@@ -77,7 +77,7 @@ function addDefinition(definition) {
77
77
 
78
78
  definition.toZigbee.push(tz.scene_store, tz.scene_recall, tz.scene_add, tz.scene_remove, tz.scene_remove_all, tz.read, tz.write);
79
79
 
80
- if (definition.exposes && Array.isArray(definition.exposes)) {
80
+ if (definition.exposes && Array.isArray(definition.exposes) && !definition.exposes.find((e) => e.name === 'linkquality')) {
81
81
  definition.exposes = definition.exposes.concat([exposes.presets.linkquality()]);
82
82
  }
83
83
 
@@ -4,8 +4,10 @@ const common = require('./common');
4
4
  const axios = common.getAxios();
5
5
  const fs = require('fs');
6
6
  const URI = require('uri-js');
7
+ const path = require('path');
7
8
 
8
- let overrideFileName = null;
9
+ let overrideIndexFileName = null;
10
+ let dataDir = null;
9
11
 
10
12
  /**
11
13
  * Helper functions
@@ -22,7 +24,7 @@ function isValidUrl(url) {
22
24
  return parsed.scheme === 'http' || parsed.scheme === 'https';
23
25
  }
24
26
 
25
- async function getFile(urlOrName) {
27
+ async function getIndexFile(urlOrName) {
26
28
  if (isValidUrl(urlOrName)) {
27
29
  return (await axios.get(urlOrName)).data;
28
30
  }
@@ -30,14 +32,33 @@ async function getFile(urlOrName) {
30
32
  return JSON.parse(fs.readFileSync(urlOrName));
31
33
  }
32
34
 
35
+ async function getFirmwareFile(image, logger) {
36
+ let urlOrName = image.url;
37
+
38
+ // First try to download firmware file with the URL provided
39
+ if (isValidUrl(urlOrName)) {
40
+ logger.debug(`ZigbeeOTA: downloading firmware image from ${urlOrName}`);
41
+ return await axios.get(urlOrName, {responseType: 'arraybuffer'});
42
+ }
43
+
44
+ // If the file name is not a full path, then treat it as a relative to the data directory
45
+ if (!path.isAbsolute(urlOrName) && dataDir) {
46
+ urlOrName = path.join(dataDir, urlOrName);
47
+ }
48
+
49
+ logger.debug(`ZigbeeOTA: getting local firmware file ${urlOrName}`);
50
+ return {data: fs.readFileSync(urlOrName)};
51
+ }
52
+
53
+
33
54
  async function getIndex(logger) {
34
55
  const index = (await axios.get(url)).data;
35
56
 
36
57
  logger.debug(`ZigbeeOTA: downloaded main index`);
37
58
 
38
- if (overrideFileName) {
39
- logger.debug(`ZigbeeOTA: Loading override index ${overrideFileName}`);
40
- const localIndex = await getFile(overrideFileName);
59
+ if (overrideIndexFileName) {
60
+ logger.debug(`ZigbeeOTA: Loading override index ${overrideIndexFileName}`);
61
+ const localIndex = await getIndexFile(overrideIndexFileName);
41
62
 
42
63
  // Resulting index will have overriden items first
43
64
  return localIndex.concat(index);
@@ -58,6 +79,7 @@ async function getImageMeta(current, logger, device) {
58
79
  // For this case additional identification through the modelId is done.
59
80
  // In the case of Tuya and Moes, additional identification is carried out through the manufacturerName.
60
81
  const image = images.find((i) => i.imageType === imageType && i.manufacturerCode === manufacturerCode &&
82
+ (!i.minFileVersion || current.fileVersion >= i.minFileVersion) && (!i.maxFileVersion || current.fileVersion <= i.maxFileVersion) &&
61
83
  (!i.modelId || i.modelId === modelId) && (!i.manufacturerName || i.manufacturerName.includes(manufacturerName)));
62
84
 
63
85
  assert(image !== undefined, `No image available for imageType '${imageType}'`);
@@ -78,7 +100,7 @@ async function isUpdateAvailable(device, logger, requestPayload=null) {
78
100
  }
79
101
 
80
102
  async function updateToLatest(device, logger, onProgress) {
81
- return common.updateToLatest(device, logger, onProgress, common.getNewImage, getImageMeta);
103
+ return common.updateToLatest(device, logger, onProgress, common.getNewImage, getImageMeta, getFirmwareFile);
82
104
  }
83
105
 
84
106
  module.exports = {
@@ -86,6 +108,9 @@ module.exports = {
86
108
  isUpdateAvailable,
87
109
  updateToLatest,
88
110
  useIndexOverride: (indexFileName) => {
89
- overrideFileName = indexFileName;
111
+ overrideIndexFileName = indexFileName;
112
+ },
113
+ setDataDir: (dir) => {
114
+ dataDir = dir;
90
115
  },
91
116
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.377",
3
+ "version": "14.0.381",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.377",
3
+ "version": "14.0.381",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [