mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-08-29 07:08:56 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3046680f61 | ||
|
|
f206945506 | ||
|
|
2e96c8b03a | ||
|
|
43699e133a | ||
|
|
a293b665b4 | ||
|
|
ad9421a9b0 | ||
|
|
134f67134b | ||
|
|
c7fddbc6e3 | ||
|
|
29e5b9682c | ||
|
|
33bed2bbfb | ||
|
|
528539214c | ||
|
|
855e9e0eb1 | ||
|
|
845bed4e11 | ||
|
|
8e49dab722 | ||
|
|
9a28f116b1 | ||
|
|
cb64a865d9 | ||
|
|
520f59f47c | ||
|
|
c88666bde7 | ||
|
|
24a85abcd8 | ||
|
|
8929544a12 | ||
|
|
fed84cfd5e | ||
|
|
739e6fb66b | ||
|
|
2a6659582b | ||
|
|
3f8371bef2 | ||
|
|
3d79688ffd | ||
|
|
3795562383 | ||
|
|
f816c8e740 | ||
|
|
b2331da671 | ||
|
|
e7e752a032 | ||
|
|
fe0919d02a | ||
|
|
5aedf6b2ee | ||
|
|
5244fa0ed8 | ||
|
|
856ecf47f1 | ||
|
|
772f6c0bde | ||
|
|
ff61695355 | ||
|
|
07446ce1c1 | ||
|
|
20df5e5639 | ||
|
|
7ae77ea528 | ||
|
|
bf1111edcb | ||
|
|
4c57323eae | ||
|
|
90d8326e0c | ||
|
|
e792f8bc8c | ||
|
|
a12d9fb73e | ||
|
|
cb47c12b55 | ||
|
|
26e2757df6 | ||
|
|
dabc944cd3 | ||
|
|
575e6fd4a3 | ||
|
|
305cb259b3 | ||
|
|
04bd928f3a | ||
|
|
e0ba80249c |
@@ -76,15 +76,13 @@ steps:
|
||||
displayName: 'Docker build release'
|
||||
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'), ne(variables['Build.Reason'], 'PullRequest'))
|
||||
|
||||
# Trigger downstream
|
||||
# Trigger Home Assistant Zigbee2mqtt addon build
|
||||
- bash: |
|
||||
BODY="{\"request\": {\"branch\": \"master\"}}"
|
||||
curl -s -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Travis-API-Version: 3" \
|
||||
-H "Authorization: token $(TRAVIS_TOKEN)" \
|
||||
-d "$BODY" \
|
||||
"https://api.travis-ci.org/repo/danielwelch%2Fhassio-zigbee2mqtt/requests"
|
||||
curl -s \
|
||||
--request POST \
|
||||
--header "Content-Type: application/json" \
|
||||
--data '{"definition": {"id": 1}}' \
|
||||
-u "$(HASSIO_TRIGGER_SECRET)" \
|
||||
"https://dev.azure.com/danielwelch2101/hassio-zigbee2mqtt/_apis/build/builds?api-version=5.1"
|
||||
displayName: 'Trigger Hass.io build'
|
||||
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/dev'), ne(variables['Build.Reason'], 'PullRequest'))
|
||||
|
||||
+8
-6
@@ -19,6 +19,7 @@ const ExtensionHomeAssistant = require('./extension/homeassistant');
|
||||
const ExtensionConfigure = require('./extension/configure');
|
||||
const ExtensionDeviceGroupMembership = require('./extension/legacy/deviceGroupMembership');
|
||||
const ExtensionBridgeLegacy = require('./extension/legacy/bridgeLegacy');
|
||||
// const ExtensionBridge = require('./extension/bridge');
|
||||
const ExtensionGroups = require('./extension/groups');
|
||||
const ExtensionAvailability = require('./extension/availability');
|
||||
const ExtensionBind = require('./extension/bind');
|
||||
@@ -48,6 +49,7 @@ class Controller {
|
||||
new ExtensionBind(...args),
|
||||
new ExtensionOnEvent(...args),
|
||||
new ExtensionOTAUpdate(...args),
|
||||
// new ExtensionBridge(...args),
|
||||
];
|
||||
|
||||
/* istanbul ignore else */
|
||||
@@ -249,12 +251,6 @@ class Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
const isDevice = resolvedEntity.type === 'device';
|
||||
|
||||
if (isDevice && settings.get().advanced.last_seen !== 'disable' && resolvedEntity.device.lastSeen) {
|
||||
payload.last_seen = utils.formatDate(resolvedEntity.device.lastSeen, settings.get().advanced.last_seen);
|
||||
}
|
||||
|
||||
let messagePayload = {...payload};
|
||||
const currentState = this.state.exists(resolvedEntity.settings.ID) ?
|
||||
this.state.get(resolvedEntity.settings.ID) : {};
|
||||
@@ -279,6 +275,7 @@ class Controller {
|
||||
options.properties = {messageExpiryInterval: retention};
|
||||
}
|
||||
|
||||
const isDevice = resolvedEntity.type === 'device';
|
||||
if (isDevice && settings.get().mqtt.include_device_information) {
|
||||
const attributes = [
|
||||
'ieeeAddr', 'networkAddress', 'type', 'manufacturerID', 'manufacturerName', 'powerSource',
|
||||
@@ -293,6 +290,11 @@ class Controller {
|
||||
attributes.forEach((a) => messagePayload.device[a] = resolvedEntity.device[a]);
|
||||
}
|
||||
|
||||
const lastSeen = settings.get().advanced.last_seen;
|
||||
if (isDevice && lastSeen !== 'disable' && resolvedEntity.device.lastSeen) {
|
||||
messagePayload.last_seen = utils.formatDate(resolvedEntity.device.lastSeen, lastSeen);
|
||||
}
|
||||
|
||||
// filter mqtt message attributes
|
||||
if (deviceOptions.filtered_attributes) {
|
||||
deviceOptions.filtered_attributes.forEach((a) => delete messagePayload[a]);
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/* istanbul ignore file newApi */
|
||||
|
||||
const logger = require('../util/logger');
|
||||
const utils = require('../util/utils');
|
||||
const Extension = require('./extension');
|
||||
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
|
||||
const settings = require('../util/settings');
|
||||
|
||||
const requestRegex = new RegExp(`${settings.get().mqtt.base_topic}/bridge/request/(.*)`);
|
||||
|
||||
class BridgeLegacy extends Extension {
|
||||
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
|
||||
super(zigbee, mqtt, state, publishEntityState, eventBus);
|
||||
|
||||
|
||||
this.requestLookup = {
|
||||
'permitjoin': this.requestPermitJoin.bind(this),
|
||||
'device/remove': this.deviceRemove.bind(this),
|
||||
'device/forceremove': this.deviceForceRemove.bind(this),
|
||||
'device/ban': this.deviceBan.bind(this),
|
||||
'group/remove': this.groupRemove.bind(this),
|
||||
};
|
||||
}
|
||||
|
||||
async onMQTTConnected() {
|
||||
this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/request/+`);
|
||||
await this.publishInfo();
|
||||
await this.publishDevices();
|
||||
await this.publishGroups();
|
||||
}
|
||||
|
||||
async onMQTTMessage(topic, message) {
|
||||
const match = topic.match(requestRegex);
|
||||
if (match && this.requestLookup[match[1].toLowerCase()]) {
|
||||
message = JSON.parse(message);
|
||||
try {
|
||||
const response = await this.requestLookup[match[1].toLowerCase()](message);
|
||||
await this.mqtt.publish(`bridge/response/${match[1]}`, JSON.stringify(response));
|
||||
} catch (error) {
|
||||
logger.error(`Request '${topic}' failed with error: '${error.message}'`);
|
||||
const response = utils.getResponse(message, {}, error.message);
|
||||
await this.mqtt.publish(`bridge/response/${match[1]}`, JSON.stringify(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async onZigbeeEvent(type, data, resolvedEntity) {
|
||||
if (['deviceJoined', 'deviceLeave', 'deviceInterview'].includes(type)) {
|
||||
let payload;
|
||||
const ieeeAddress = data.device ? data.device.ieeeAddr : data.ieeeAddr;
|
||||
if (type === 'deviceJoined') payload = {friendlyName: resolvedEntity.settings.friendlyName, ieeeAddress};
|
||||
else if (type === 'deviceInterview') {
|
||||
payload = {friendlyName: resolvedEntity.settings.friendlyName, status: data.status, ieeeAddress};
|
||||
if (data.status === 'successful') {
|
||||
payload.supported = !!resolvedEntity.definition;
|
||||
payload.definition = resolvedEntity.definition ? {
|
||||
model: resolvedEntity.definition.model,
|
||||
vendor: resolvedEntity.definition.vendor,
|
||||
description: resolvedEntity.definition.description,
|
||||
supports: resolvedEntity.definition.supports,
|
||||
} : null;
|
||||
}
|
||||
} else payload = {ieeeAddress}; // deviceLeave
|
||||
|
||||
await this.mqtt.publish('bridge/event', JSON.stringify({type, data: payload}), {retain: false, qos: 0});
|
||||
}
|
||||
|
||||
if ('deviceLeave' === type || ('deviceInterview' === type && data.status !== 'started')) {
|
||||
await this.publishDevices();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests
|
||||
*/
|
||||
|
||||
async deviceRemove(message) {
|
||||
return this.removeForceRemoveOrBanEntity('remove', 'device', message);
|
||||
}
|
||||
|
||||
async deviceForceRemove(message) {
|
||||
return this.removeForceRemoveOrBanEntity('force_remove', 'device', message);
|
||||
}
|
||||
|
||||
async deviceBan(message) {
|
||||
return this.removeForceRemoveOrBanEntity('ban', 'device', message);
|
||||
}
|
||||
|
||||
async groupRemove(message) {
|
||||
return this.removeForceRemoveOrBanEntity('remove', 'group', message);
|
||||
}
|
||||
|
||||
async requestPermitJoin(message) {
|
||||
const value = typeof message === 'object' ? message.value : message;
|
||||
await this.zigbee.permitJoin(value);
|
||||
await this.publishInfo();
|
||||
return utils.getResponse(message, {value: value}, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utils
|
||||
*/
|
||||
|
||||
async removeForceRemoveOrBanEntity(action, entityType, message) {
|
||||
const ID = typeof message === 'object' ? message.ID : message.trim();
|
||||
const entity = this.zigbee.resolveEntity(ID);
|
||||
if (!entity || entity.type !== entityType) {
|
||||
throw new Error(`${ID} is not a ${entityType}`);
|
||||
}
|
||||
|
||||
const lookup = {
|
||||
ban: ['banned', 'Banning', 'ban'],
|
||||
force_remove: ['force_removed', 'Force removing', 'force remove'],
|
||||
remove: ['removed', 'Removing', 'remove'],
|
||||
};
|
||||
|
||||
try {
|
||||
logger.info(`${lookup[action][1]} '${entity.settings.friendlyName}'`);
|
||||
if (entity.type === 'device') {
|
||||
if (action === 'ban') {
|
||||
settings.banDevice(entity.settings.ID);
|
||||
}
|
||||
|
||||
action === 'force_remove' ?
|
||||
await entity.device.removeFromDatabase() : await entity.device.removeFromNetwork();
|
||||
} else {
|
||||
await entity.group.removeFromDatabase();
|
||||
}
|
||||
|
||||
// Fire event
|
||||
if (entity.type === 'device') {
|
||||
this.eventBus.emit('deviceRemoved', {device: entity.device});
|
||||
}
|
||||
|
||||
// Remove from configuration.yaml
|
||||
entity.type === 'device' ?
|
||||
settings.removeDevice(entity.settings.ID) : settings.removeGroup(entity.settings.ID);
|
||||
|
||||
// Remove from state
|
||||
this.state.remove(entity.settings.ID);
|
||||
|
||||
logger.info(`Successfully ${lookup[action][0]} ${entity.settings.friendlyName}`);
|
||||
entity.type === 'device' ? this.publishDevices() : this.publishGroups();
|
||||
return utils.getResponse(message, {ID}, null);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to ${lookup[action][2]} ${entity.settings.friendlyName} (${error})`);
|
||||
}
|
||||
}
|
||||
|
||||
async publishInfo() {
|
||||
const info = await utils.getZigbee2mqttVersion();
|
||||
const coordinator = await this.zigbee.getCoordinatorVersion();
|
||||
const payload = {
|
||||
version: info.version,
|
||||
commit: info.commitHash,
|
||||
coordinator,
|
||||
logLevel: logger.getLevel(),
|
||||
permitJoin: await this.zigbee.getPermitJoin(),
|
||||
};
|
||||
|
||||
await this.mqtt.publish('bridge/info', JSON.stringify(payload), {retain: true, qos: 0});
|
||||
}
|
||||
|
||||
async publishDevices(topic, message) {
|
||||
const devices = this.zigbee.getClients().map((device) => {
|
||||
const definition = zigbeeHerdsmanConverters.findByDevice(device);
|
||||
const resolved = this.zigbee.resolveEntity(device);
|
||||
const definitionPayload = definition ? {
|
||||
model: definition.model,
|
||||
vendor: definition.vendor,
|
||||
description: definition.description,
|
||||
supports: definition.supports,
|
||||
} : null;
|
||||
|
||||
return {
|
||||
ieeeAddress: device.ieeeAddr,
|
||||
type: device.type,
|
||||
networkAddress: device.networkAddress,
|
||||
supported: !!definition,
|
||||
friendlyName: resolved.settings.friendlyName,
|
||||
definition: definitionPayload,
|
||||
powerSource: device.powerSource,
|
||||
softwareBuildID: device.softwareBuildID,
|
||||
dateCode: device.dateCode,
|
||||
interviewing: device.interviewing,
|
||||
interviewCompleted: device.interviewCompleted,
|
||||
};
|
||||
});
|
||||
|
||||
await this.mqtt.publish('bridge/devices', JSON.stringify(devices), {retain: true, qos: 0});
|
||||
}
|
||||
|
||||
async publishGroups(topic, message) {
|
||||
const groups = this.zigbee.getGroups().map((group) => {
|
||||
const resolved = this.zigbee.resolveEntity(group);
|
||||
return {
|
||||
ID: group.groupID,
|
||||
friendlyName: resolved.settings.friendlyName,
|
||||
members: group.members.map((m) => {
|
||||
return {
|
||||
ieeeAddress: m.deviceIeeeAddress,
|
||||
endpoint: m.ID,
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
await this.mqtt.publish('bridge/groups', JSON.stringify(groups), {retain: true, qos: 0});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BridgeLegacy;
|
||||
@@ -95,14 +95,14 @@ const cfg = {
|
||||
device_class: 'safety',
|
||||
},
|
||||
},
|
||||
'binary_sensor_router': {
|
||||
'binary_sensor_led': {
|
||||
type: 'binary_sensor',
|
||||
object_id: 'router',
|
||||
object_id: 'led',
|
||||
discovery_payload: {
|
||||
payload_on: true,
|
||||
payload_off: false,
|
||||
value_template: '{{ value_json.state }}',
|
||||
device_class: 'connectivity',
|
||||
value_template: '{{ value_json.led }}',
|
||||
device_class: 'light',
|
||||
},
|
||||
},
|
||||
'binary_sensor_battery_low': {
|
||||
@@ -406,6 +406,22 @@ const cfg = {
|
||||
icon: 'mdi:weight',
|
||||
},
|
||||
},
|
||||
'sensor_requested_brightness_level': {
|
||||
type: 'sensor',
|
||||
object_id: 'requested_brightness_level',
|
||||
discovery_payload: {
|
||||
value_template: '{{ value_json.requested_brightness_level }}',
|
||||
icon: 'mdi:brightness-5',
|
||||
},
|
||||
},
|
||||
'sensor_requested_brightness_percent': {
|
||||
type: 'sensor',
|
||||
object_id: 'requested_brightness_percent',
|
||||
discovery_payload: {
|
||||
value_template: '{{ value_json.requested_brightness_percent }}',
|
||||
icon: 'mdi:brightness-5',
|
||||
},
|
||||
},
|
||||
|
||||
// Light
|
||||
'light_brightness_colorxy_white': {
|
||||
@@ -417,6 +433,7 @@ const cfg = {
|
||||
white_value: true,
|
||||
schema: 'json',
|
||||
command_topic: true,
|
||||
brightness_scale: 254,
|
||||
},
|
||||
},
|
||||
'light_brightness_colortemp_colorxy_white': {
|
||||
@@ -429,6 +446,7 @@ const cfg = {
|
||||
schema: 'json',
|
||||
command_topic: true,
|
||||
color_temp: true,
|
||||
brightness_scale: 254,
|
||||
},
|
||||
},
|
||||
'light_brightness_colortemp_colorxy': {
|
||||
@@ -440,6 +458,7 @@ const cfg = {
|
||||
xy: true,
|
||||
schema: 'json',
|
||||
command_topic: true,
|
||||
brightness_scale: 254,
|
||||
},
|
||||
},
|
||||
'light_brightness_colorxy': {
|
||||
@@ -450,6 +469,7 @@ const cfg = {
|
||||
xy: true,
|
||||
schema: 'json',
|
||||
command_topic: true,
|
||||
brightness_scale: 254,
|
||||
},
|
||||
},
|
||||
'light_brightness_colortemp_colorhs': {
|
||||
@@ -461,6 +481,7 @@ const cfg = {
|
||||
hs: true,
|
||||
schema: 'json',
|
||||
command_topic: true,
|
||||
brightness_scale: 254,
|
||||
},
|
||||
},
|
||||
'light_brightness_colortemp': {
|
||||
@@ -471,6 +492,7 @@ const cfg = {
|
||||
color_temp: true,
|
||||
schema: 'json',
|
||||
command_topic: true,
|
||||
brightness_scale: 254,
|
||||
},
|
||||
},
|
||||
'light_brightness': {
|
||||
@@ -480,6 +502,7 @@ const cfg = {
|
||||
brightness: true,
|
||||
schema: 'json',
|
||||
command_topic: true,
|
||||
brightness_scale: 254,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -678,16 +701,16 @@ const thermostat = (minTemp=7, maxTemp=30, temperatureStateProperty='occupied_he
|
||||
};
|
||||
};
|
||||
|
||||
const thermostatHeatCool = /* istanbul ignore next */ (minTemp=7, maxTemp=30, tempStep=0.5, fanModes=[]) => {
|
||||
const thermostatHeatCool = /* istanbul ignore next */ (minTemp=7, maxTemp=30, tempStep=0.5, opModes, fanModes=[]) => {
|
||||
return {
|
||||
type: 'climate',
|
||||
object_id: 'climate',
|
||||
discovery_payload: {
|
||||
state_topic: false,
|
||||
unit_of_measurement: '°C',
|
||||
temperature_unit: 'C',
|
||||
min_temp: `${minTemp}`,
|
||||
max_temp: `${maxTemp}`,
|
||||
modes: ['off', 'auto', 'heat', 'cool'],
|
||||
modes: opModes,
|
||||
mode_state_topic: true,
|
||||
mode_state_template: '{{ value_json.system_mode }}',
|
||||
mode_command_topic: true,
|
||||
@@ -730,7 +753,7 @@ const mapping = {
|
||||
'MCCGQ11LM': [cfg.binary_sensor_contact, cfg.sensor_battery],
|
||||
'SJCGQ11LM': [cfg.binary_sensor_water_leak, cfg.sensor_battery],
|
||||
'MFKZQ01LM': [cfg.sensor_action, cfg.sensor_battery],
|
||||
'ZNCZ02LM': [cfg.switch, cfg.sensor_power],
|
||||
'ZNCZ02LM': [cfg.switch, cfg.sensor_power, cfg.sensor_temperature, cfg.sensor_consumption],
|
||||
'QBCZ11LM': [cfg.switch, cfg.sensor_power],
|
||||
'LED1545G12': [cfg.light_brightness_colortemp],
|
||||
'LED1623G12': [cfg.light_brightness],
|
||||
@@ -746,7 +769,7 @@ const mapping = {
|
||||
'JTYJ-GD-01LM/BW': [cfg.binary_sensor_smoke, cfg.sensor_battery, cfg.sensor_sensitivity, cfg.sensor_smoke_density],
|
||||
'PLUG EDP RE:DY': [cfg.switch, cfg.sensor_power],
|
||||
'SWITCH EDP RE:DY': [cfg.switch],
|
||||
'CC2530.ROUTER': [cfg.binary_sensor_router],
|
||||
'CC2530.ROUTER': [cfg.binary_sensor_led],
|
||||
'AA70155': [cfg.light_brightness_colortemp],
|
||||
'A9A19A60WESDZ02': [cfg.light_brightness_colortemp],
|
||||
'4058075816718': [cfg.light_brightness_colortemp_colorxy],
|
||||
@@ -793,8 +816,9 @@ const mapping = {
|
||||
'SL 110 N': [cfg.light_brightness],
|
||||
'SL 110 M': [cfg.light_brightness],
|
||||
'SL 110 W': [cfg.light_brightness],
|
||||
'AE 260': [cfg.light_brightness],
|
||||
'AA68199': [cfg.light_brightness_colortemp],
|
||||
'QBKG11LM': [cfg.switch, cfg.sensor_power, cfg.sensor_click],
|
||||
'QBKG11LM': [cfg.switch, cfg.sensor_power, cfg.sensor_click, cfg.sensor_temperature],
|
||||
'QBKG12LM': [
|
||||
switchEndpoint('left'), switchEndpoint('right'), cfg.sensor_power, cfg.sensor_click,
|
||||
cfg.sensor_temperature,
|
||||
@@ -858,7 +882,7 @@ const mapping = {
|
||||
'7299355PH': [cfg.light_brightness_colorxy],
|
||||
'45857GE': [cfg.light_brightness],
|
||||
'A6121': [cfg.sensor_lock],
|
||||
'433714': [cfg.light_brightness],
|
||||
'433714': [cfg.light_brightness_colortemp],
|
||||
'3261030P7': [cfg.light_brightness_colortemp],
|
||||
'3216431P5': [cfg.light_brightness_colortemp],
|
||||
'DJT11LM': [cfg.sensor_action, cfg.sensor_battery, cfg.sensor_sensitivity, cfg.sensor_strength],
|
||||
@@ -886,7 +910,8 @@ const mapping = {
|
||||
'3216331P5': [cfg.light_brightness_colortemp],
|
||||
'AC08562': [cfg.light_brightness],
|
||||
'900008-WW': [cfg.light_brightness],
|
||||
'Mega23M12': [cfg.light_brightness_colortemp_colorxy],
|
||||
'Mega23M12': [lightEndpoint('light_brightness_colortemp_colorxy', 'rgb'),
|
||||
lightEndpoint('light_brightness', 'white')],
|
||||
'PSS-23ZBS': [cfg.switch],
|
||||
'HS1SA-M': [cfg.binary_sensor_smoke, cfg.binary_sensor_battery_low],
|
||||
'Z01-A19NAE26': [cfg.light_brightness_colortemp],
|
||||
@@ -904,13 +929,14 @@ const mapping = {
|
||||
'HS1-WL-E': [cfg.binary_sensor_water_leak],
|
||||
'421786': [cfg.light_brightness],
|
||||
'ICZB-IW11D': [cfg.light_brightness],
|
||||
'3321-S': [cfg.binary_sensor_contact, cfg.sensor_temperature],
|
||||
'3321-S': [cfg.binary_sensor_contact, cfg.sensor_temperature, cfg.sensor_battery],
|
||||
'ZPIR-8000': [cfg.binary_sensor_occupancy, cfg.sensor_battery],
|
||||
'ZCTS-808': [cfg.binary_sensor_contact, cfg.sensor_battery],
|
||||
'ZNLDP12LM': [cfg.light_brightness_colortemp],
|
||||
'D1821': [cfg.light_brightness_colortemp_colorxy],
|
||||
'ZNCLDJ11LM': [cfg.cover_position, cfg.sensor_cover],
|
||||
'owvfni3': [cfg.cover_position],
|
||||
'TS0601': [cfg.cover_position],
|
||||
'LTFY004': [cfg.light_brightness_colorxy],
|
||||
'GL-S-007Z': [cfg.light_brightness_colortemp_colorxy],
|
||||
'3325-S': [cfg.sensor_temperature, cfg.binary_sensor_occupancy],
|
||||
@@ -937,7 +963,11 @@ const mapping = {
|
||||
'HGZB-07A': [cfg.light_brightness_colortemp_colorxy],
|
||||
'E1524/E1810': [cfg.sensor_action, cfg.sensor_battery],
|
||||
'GL-C-006': [cfg.light_brightness_colortemp],
|
||||
'GL-C-007': [cfg.light_brightness_colorxy_white],
|
||||
'GL-C-007-1ID': [cfg.light_brightness_colortemp_colorxy],
|
||||
'GL-C-007-2ID': [lightEndpoint('light_brightness_colortemp_colorxy', 'rgb'),
|
||||
lightEndpoint('light_brightness', 'white')],
|
||||
'GL-C-008-2ID': [lightEndpoint('light_brightness_colorxy', 'rgb'),
|
||||
lightEndpoint('light_brightness_colortemp', 'cct')],
|
||||
'GL-C-007S': [cfg.light_brightness_colorxy_white],
|
||||
'GL-C-007/GL-C-008': [cfg.light_brightness_colortemp_colorxy_white],
|
||||
'100.424.11': [cfg.light_brightness_colortemp],
|
||||
@@ -950,7 +980,7 @@ const mapping = {
|
||||
'GL-S-003Z': [cfg.light_brightness_colorxy_white],
|
||||
'GL-S-005Z': [cfg.light_brightness_colortemp_colorxy],
|
||||
'HS1DS-E': [cfg.binary_sensor_contact],
|
||||
'SP600': [cfg.switch, cfg.sensor_power],
|
||||
'SP600': [cfg.switch, cfg.sensor_power, cfg.sensor_energy],
|
||||
'1613V': [cfg.switch, cfg.sensor_power],
|
||||
'XVV-Mega23M12': [cfg.light_brightness_colortemp],
|
||||
'GL-B-007Z': [cfg.light_brightness_colortemp_colorxy],
|
||||
@@ -982,6 +1012,7 @@ const mapping = {
|
||||
'HGZB-042': [switchEndpoint('top'), switchEndpoint('bottom')],
|
||||
'HGZB-42': [switchEndpoint('top'), switchEndpoint('bottom')],
|
||||
'GL-FL-004TZ': [cfg.light_brightness_colortemp_colorxy],
|
||||
'GL-FL-004TZS': [cfg.light_brightness_colortemp_colorxy],
|
||||
'IM6001-OTP05': [cfg.switch],
|
||||
'SV01': [
|
||||
cfg.cover_position, cfg.sensor_temperature, cfg.sensor_pressure,
|
||||
@@ -998,7 +1029,10 @@ const mapping = {
|
||||
cfg.sensor_local_temperature,
|
||||
cfg.lock_keypad_lockout,
|
||||
],
|
||||
'E1525/E1745': [cfg.binary_sensor_occupancy, cfg.sensor_battery],
|
||||
'E1525/E1745': [
|
||||
cfg.binary_sensor_occupancy, cfg.sensor_battery, cfg.sensor_requested_brightness_level,
|
||||
cfg.sensor_requested_brightness_percent,
|
||||
],
|
||||
'ZYCT-202': [cfg.sensor_action],
|
||||
'GR-ZB01-W': [cfg.cover_position],
|
||||
'4090531P7': [cfg.light_brightness_colortemp_colorxy],
|
||||
@@ -1113,6 +1147,7 @@ const mapping = {
|
||||
],
|
||||
'HLC821-Z-SC': [cfg.light_brightness],
|
||||
'RS 228 T': [cfg.light_brightness_colortemp],
|
||||
'RS 229 T': [cfg.light_brightness_colortemp],
|
||||
'67200BL': [cfg.switch],
|
||||
'InstaRemote': [cfg.sensor_action],
|
||||
'100.425.90': [cfg.switch],
|
||||
@@ -1128,7 +1163,7 @@ const mapping = {
|
||||
'ZigUP': [cfg.switch],
|
||||
'YRD256HA20BP': [cfg.sensor_battery, cfg.lock],
|
||||
'SZ-ESW01-AU': [cfg.sensor_power, cfg.switch],
|
||||
'PSM-29ZBSR': [cfg.switch],
|
||||
'PSM-29ZBSR': [cfg.switch, cfg.sensor_power],
|
||||
'ZM350STW1TCF': [cfg.light_brightness_colortemp],
|
||||
'M350STW1': [cfg.light_brightness],
|
||||
'A806S-Q1R': [cfg.light_brightness],
|
||||
@@ -1286,7 +1321,7 @@ const mapping = {
|
||||
'ZM-CSW032-D': [cfg.cover_position],
|
||||
'LH-32ZB': [cfg.sensor_humidity, cfg.sensor_temperature, cfg.sensor_battery],
|
||||
'511.201': [cfg.light_brightness],
|
||||
'ZNCLDJ12LM': [cfg.cover_position],
|
||||
'ZNCLDJ12LM': [cfg.cover_position, cfg.sensor_battery],
|
||||
'046677552343': [cfg.switch],
|
||||
'3115331PH': [cfg.light_brightness_colortemp_colorxy],
|
||||
'ZWLD-100': [cfg.binary_sensor_water_leak, cfg.binary_sensor_battery_low, cfg.sensor_battery],
|
||||
@@ -1413,13 +1448,14 @@ const mapping = {
|
||||
'1744130P7': [cfg.light_brightness_colortemp_colorxy],
|
||||
'1743130P7': [cfg.light_brightness_colortemp_colorxy],
|
||||
'100.110.51': [cfg.light_brightness_colortemp],
|
||||
'ZL1000100-CCT-US-V1A02': [cfg.light_brightness],
|
||||
'ZL1000100-CCT-US-V1A02': [cfg.light_brightness_colortemp],
|
||||
'ZL1000701-27-EU-V1A02': [cfg.light_brightness],
|
||||
'HGZB-DLC4-N12B': [cfg.light_brightness_colortemp_colorxy],
|
||||
'U86KCJ-ZP': [cfg.sensor_action],
|
||||
'HS1HT': [cfg.sensor_temperature, cfg.sensor_humidity, cfg.sensor_battery],
|
||||
'HS2ESK-E': [cfg.switch, cfg.sensor_power],
|
||||
'B01M7Y8BP9': [cfg.sensor_action],
|
||||
'GP-WOU019BBDWG': [cfg.switch, cfg.sensor_power],
|
||||
'GP-WOU019BBDWG': [cfg.switch, cfg.sensor_power, cfg.sensor_energy],
|
||||
'AV2010/21A': [cfg.binary_sensor_battery_low, cfg.binary_sensor_contact, cfg.binary_sensor_tamper],
|
||||
'AL-PIR02': [cfg.binary_sensor_occupancy, cfg.binary_sensor_tamper, cfg.sensor_battery],
|
||||
'MKS-CM-W5': [
|
||||
@@ -1489,6 +1525,9 @@ const mapping = {
|
||||
'PM-S140-ZB': [cfg.switch],
|
||||
'PM-S240-ZB': [switchEndpoint('top'), switchEndpoint('bottom')],
|
||||
'PM-S340-ZB': [switchEndpoint('top'), switchEndpoint('center'), switchEndpoint('bottom')],
|
||||
'PM-S140R-ZB': [cfg.switch],
|
||||
'PM-S240R-ZB': [switchEndpoint('top'), switchEndpoint('bottom')],
|
||||
'PM-S340R-ZB': [switchEndpoint('top'), switchEndpoint('center'), switchEndpoint('bottom')],
|
||||
'U201DST600ZB': [cfg.light_brightness],
|
||||
'U201SRY2KWZB': [cfg.switch],
|
||||
'U202SRY2KWZB': [switchEndpoint('l1'), switchEndpoint('l2')],
|
||||
@@ -1533,7 +1572,7 @@ const mapping = {
|
||||
'E12-N1E': [cfg.light_brightness_colortemp_colorxy],
|
||||
'4040B': [cfg.sensor_power, switchEndpoint('l1'), switchEndpoint('l2')],
|
||||
'3460-L': [cfg.sensor_action, cfg.sensor_temperature, cfg.sensor_battery],
|
||||
'3157100': [thermostatHeatCool(10, 30, 1, ['auto', 'on']), cfg.sensor_battery],
|
||||
'3157100': [thermostatHeatCool(10, 30, 1, ['off', 'heat', 'cool'], ['auto', 'on']), cfg.sensor_battery],
|
||||
'4257050-RZHAC': [cfg.switch, cfg.sensor_power],
|
||||
'27087-03': [cfg.switch, cfg.sensor_battery],
|
||||
'99140-002': [cfg.lock, cfg.sensor_battery],
|
||||
@@ -1541,12 +1580,16 @@ const mapping = {
|
||||
'GL-S-004ZS': [cfg.light_brightness_colortemp_colorxy],
|
||||
'7121131PU': [cfg.light_brightness_colortemp_colorxy],
|
||||
'RL804QZB': [switchEndpoint('l1'), switchEndpoint('l2'), switchEndpoint('l3')],
|
||||
'RC-2000WH': [thermostatHeatCool(10, 30, 1, ['auto', 'on', 'smart'])],
|
||||
'RC-2000WH': [thermostatHeatCool(10, 30, 1, ['off', 'auto', 'heat', 'cool'], ['auto', 'on', 'smart'])],
|
||||
'TH1300ZB': [thermostat()],
|
||||
'SP 220': [cfg.switch],
|
||||
'511.040': [cfg.light_brightness_colortemp_colorxy],
|
||||
'511.344': [cfg.sensor_battery, cfg.sensor_action, cfg.sensor_action_color, cfg.sensor_action_color_temperature],
|
||||
'SMSZB-120': [cfg.binary_sensor_smoke, cfg.sensor_temperature, cfg.sensor_battery],
|
||||
'MOT003': [
|
||||
cfg.sensor_temperature, cfg.binary_sensor_occupancy, cfg.sensor_illuminance,
|
||||
cfg.sensor_illuminance_lux, cfg.binary_sensor_battery_low, cfg.sensor_battery,
|
||||
],
|
||||
'HALIGHTDIMWWE14': [cfg.light_brightness],
|
||||
'GreenPower_On_Off_Switch': [cfg.sensor_action],
|
||||
'GreenPower_7': [cfg.sensor_action],
|
||||
@@ -1573,7 +1616,7 @@ const mapping = {
|
||||
'676-00301024955Z': [cfg.light_brightness],
|
||||
'1743030P7': [cfg.light_brightness_colortemp_colorxy],
|
||||
'XBee': [],
|
||||
'ZL1000701-27-EU-V1A02': [cfg.light_brightness],
|
||||
'ZBHT-1': [cfg.sensor_temperature, cfg.sensor_humidity, cfg.sensor_battery],
|
||||
'rgbw2.zbee27': [cfg.light_brightness_colortemp_colorxy],
|
||||
'MCLH-05': [cfg.binary_sensor_occupancy, cfg.sensor_battery],
|
||||
'5045148P7': [cfg.light_brightness_colortemp_colorxy],
|
||||
@@ -1587,8 +1630,37 @@ const mapping = {
|
||||
'ZS1100400-IN-V1A02': [cfg.binary_sensor_occupancy, cfg.binary_sensor_battery_low],
|
||||
'MCLH-08': [cfg.sensor_temperature, cfg.sensor_humidity, cfg.sensor_eco2, cfg.sensor_voc],
|
||||
'GL-FL-005TZ': [cfg.light_brightness_colortemp_colorxy],
|
||||
'ED2004-012': [],
|
||||
'ED2004-012': [cfg.switch],
|
||||
'ZG192910-4': [cfg.light_brightness_colortemp],
|
||||
'SLT2': [],
|
||||
'ZL1000700-22-EU-V1A02': [cfg.light_brightness],
|
||||
'SLB2': [],
|
||||
'8840100H': [cfg.binary_sensor_water_leak, cfg.sensor_temperature, cfg.sensor_battery],
|
||||
'404037': [cfg.light_brightness_colortemp],
|
||||
'9290022408': [cfg.switch],
|
||||
'HGZB-14A': [cfg.binary_sensor_water_leak, cfg.sensor_battery],
|
||||
'TERNCY-DC01': [cfg.sensor_temperature, cfg.binary_sensor_contact],
|
||||
'ZS110050078': [cfg.binary_sensor_contact, cfg.binary_sensor_battery_low],
|
||||
'HGZB-DLC4-N15B': [cfg.light_brightness_colortemp_colorxy],
|
||||
'ECW-100-A03': [switchEndpoint('top'), switchEndpoint('center'), switchEndpoint('bottom')],
|
||||
'4098430P7': [cfg.light_brightness_colortemp],
|
||||
'PQC19-DY01': [cfg.light_brightness],
|
||||
'DIYRuZ_FreePad': [cfg.sensor_action, cfg.sensor_battery],
|
||||
'ST20': [cfg.sensor_temperature, cfg.sensor_humidity, cfg.sensor_battery],
|
||||
'ST21': [cfg.sensor_temperature, cfg.sensor_humidity, cfg.sensor_battery],
|
||||
'T30W3Z': [switchEndpoint('top'), switchEndpoint('center'), switchEndpoint('bottom')],
|
||||
'T21W2Z': [switchEndpoint('top'), switchEndpoint('bottom')],
|
||||
'T21W1Z': [cfg.switch],
|
||||
'W40CZ': [cfg.cover_position],
|
||||
'R11W2Z': [switchEndpoint('l1'), switchEndpoint('l2')],
|
||||
'R20W2Z': [switchEndpoint('l1'), switchEndpoint('l2')],
|
||||
'SW21': [cfg.binary_sensor_water_leak, cfg.binary_sensor_battery_low],
|
||||
'SE21': [cfg.sensor_action],
|
||||
'4052899926127': [cfg.light_brightness],
|
||||
'GL-B-001ZS': [cfg.light_brightness_colortemp_colorxy],
|
||||
'LH-990ZB': [cfg.binary_sensor_occupancy, cfg.binary_sensor_battery_low],
|
||||
'HO-09ZB': [cfg.binary_sensor_contact, cfg.binary_sensor_battery_low],
|
||||
'500.67': [cfg.sensor_action],
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1619,6 +1691,7 @@ class HomeAssistant extends Extension {
|
||||
}
|
||||
|
||||
onDeviceRemoved(device) {
|
||||
delete this.discovered[device.ieeeAddr];
|
||||
const definition = zigbeeHerdsmanConverters.findByDevice(device);
|
||||
if (definition) {
|
||||
logger.info(`Clearing Home Assistant discovery topic for '${device.ieeeAddr}'`);
|
||||
@@ -1766,7 +1839,7 @@ class HomeAssistant extends Extension {
|
||||
discover(resolvedEntity, force=false) {
|
||||
// Check if already discoverd and check if there are configs.
|
||||
const {device, definition} = resolvedEntity;
|
||||
const deviceSettings = resolvedEntity.settings;
|
||||
const deviceSettings = {...settings.get().device_options, ...resolvedEntity.settings};
|
||||
const discover = force || !this.discovered[device.ieeeAddr];
|
||||
if (!discover || !device || !definition || !mapping[definition.model] || !deviceSettings ||
|
||||
(deviceSettings.hasOwnProperty('homeassistant') && !deviceSettings.homeassistant)) {
|
||||
@@ -1960,7 +2033,7 @@ class HomeAssistant extends Extension {
|
||||
}
|
||||
|
||||
onZigbeeEvent(type, data, resolvedEntity) {
|
||||
if (resolvedEntity && type !== 'deviceLeave') {
|
||||
if (resolvedEntity && type !== 'deviceLeave' && this.mqtt.isConnected()) {
|
||||
this.discover(resolvedEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ class EntityPublish extends Extension {
|
||||
const msg = result.state;
|
||||
|
||||
if (endpointName) {
|
||||
for (const key of ['state', 'brightness']) {
|
||||
for (const key of ['state', 'brightness', 'color', 'color_temp']) {
|
||||
if (msg.hasOwnProperty(key)) {
|
||||
msg[`${key}_${endpointName}`] = msg[key];
|
||||
delete msg[key];
|
||||
|
||||
@@ -107,7 +107,7 @@ class Receive extends Extension {
|
||||
});
|
||||
|
||||
// Check if there is an available converter, genOta messages are not interesting.
|
||||
if (!converters.length && data.cluster !== 'genOta') {
|
||||
if (!converters.length && data.cluster !== 'genOta' && data.cluster !== 'genTime') {
|
||||
logger.debug(
|
||||
`No converter available for '${resolvedEntity.definition.model}' with cluster '${data.cluster}' ` +
|
||||
`and type '${data.type}' and data '${JSON.stringify(data.data)}'`,
|
||||
|
||||
+5
-1
@@ -95,11 +95,15 @@ class MQTT extends events.EventEmitter {
|
||||
this.emit('message', {topic, message: message.toString()});
|
||||
}
|
||||
|
||||
isConnected() {
|
||||
return this.client && !this.client.reconnecting;
|
||||
}
|
||||
|
||||
async publish(topic, payload, options, base=settings.get().mqtt.base_topic) {
|
||||
topic = `${base}/${topic}`;
|
||||
options = {qos: 0, retain: false, ...options};
|
||||
|
||||
if (!this.client || this.client.reconnecting) {
|
||||
if (!this.isConnected()) {
|
||||
logger.error(`Not connected to MQTT server!`);
|
||||
logger.error(`Cannot send message: topic: '${topic}', payload: '${payload}`);
|
||||
return;
|
||||
|
||||
+16
-1
@@ -29,9 +29,13 @@ function toLocalISOString(dDate) {
|
||||
|
||||
const endpointNames = [
|
||||
'left', 'right', 'center', 'bottom_left', 'bottom_right', 'default',
|
||||
'top_left', 'top_right', 'white', 'rgb', 'system', 'top', 'bottom', 'center_left', 'center_right',
|
||||
'top_left', 'top_right', 'white', 'rgb', 'cct', 'system', 'top', 'bottom', 'center_left', 'center_right',
|
||||
'ep1', 'ep2', 'row_1', 'row_2', 'row_3', 'row_4', 'relay',
|
||||
'l1', 'l2', 'l3', 'l4', 'l5', 'l6', 'l7', 'l8',
|
||||
'button_1', 'button_2', 'button_3', 'button_4', 'button_5',
|
||||
'button_6', 'button_7', 'button_8', 'button_9', 'button_10',
|
||||
'button_11', 'button_12', 'button_13', 'button_14', 'button_15',
|
||||
'button_16', 'button_17', 'button_18', 'button_19', 'button_20',
|
||||
];
|
||||
|
||||
function flatten(arr) {
|
||||
@@ -120,6 +124,16 @@ function getObjectsProperty(objects, key, defaultValue) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/* istanbul ignore next newApi */
|
||||
function getResponse(request, data, error) {
|
||||
const response = {data, status: error ? 'error' : 'ok'};
|
||||
if (error) response.error = error;
|
||||
if (typeof request === 'object' && request.hasOwnProperty('transaction')) {
|
||||
response.transaction = request.transaction;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
millisecondsToSeconds: (milliseconds) => milliseconds / 1000,
|
||||
secondsToMilliseconds: (seconds) => seconds * 1000,
|
||||
@@ -136,4 +150,5 @@ module.exports = {
|
||||
isBatteryPowered: (device) => device.powerSource && device.powerSource === 'Battery',
|
||||
formatDate: (date, type) => formatDate(date, type),
|
||||
equalsPartial,
|
||||
getResponse,
|
||||
};
|
||||
|
||||
+12
-2
@@ -149,9 +149,11 @@ class Zigbee extends events.EventEmitter {
|
||||
* }
|
||||
*/
|
||||
resolveEntity(key) {
|
||||
/* istanbul ignore next newApi */
|
||||
assert(
|
||||
typeof key === 'string' || typeof key === 'number' ||
|
||||
key.constructor.name === 'Device', `Wrong type '${typeof key}'`,
|
||||
key.constructor.name === 'Device' || key.constructor.name === 'Group',
|
||||
`Wrong type '${typeof key}'`,
|
||||
);
|
||||
|
||||
if (typeof key === 'string' || typeof key === 'number') {
|
||||
@@ -215,7 +217,7 @@ class Zigbee extends events.EventEmitter {
|
||||
if (!group) group = this.createGroup(entity.ID);
|
||||
return {type: 'group', group, settings: entity, name: entity.friendlyName};
|
||||
}
|
||||
} else {
|
||||
} /* istanbul ignore else newApi */ else if (key.constructor.name === 'Device') {
|
||||
const setting = settings.getEntity(key.ieeeAddr);
|
||||
return {
|
||||
type: 'device',
|
||||
@@ -225,6 +227,14 @@ class Zigbee extends events.EventEmitter {
|
||||
name: setting ? setting.friendlyName : (key.type === 'Coordinator' ? 'Coordinator' : key.ieeeAddr),
|
||||
definition: zigbeeHerdsmanConverters.findByDevice(key),
|
||||
};
|
||||
} else { // Group
|
||||
const setting = settings.getEntity(key.groupID);
|
||||
return {
|
||||
type: 'group',
|
||||
group: key,
|
||||
settings: setting,
|
||||
name: setting.friendlyName,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Generated
+858
-1866
File diff suppressed because it is too large
Load Diff
+3
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "zigbee2mqtt",
|
||||
"version": "1.13.0",
|
||||
"version": "1.13.1",
|
||||
"description": "Zigbee to MQTT bridge using Zigbee-herdsman",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
@@ -45,8 +45,8 @@
|
||||
"rimraf": "*",
|
||||
"semver": "*",
|
||||
"winston": "*",
|
||||
"zigbee-herdsman": "0.12.83",
|
||||
"zigbee-herdsman-converters": "12.0.81"
|
||||
"zigbee-herdsman": "0.12.90",
|
||||
"zigbee-herdsman-converters": "12.0.92"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "*",
|
||||
|
||||
+21
-2
@@ -1,6 +1,7 @@
|
||||
const data = require('./stub/data');
|
||||
const logger = require('./stub/logger');
|
||||
const zigbeeHerdsman = require('./stub/zigbeeHerdsman');
|
||||
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
|
||||
const MQTT = require('./stub/mqtt');
|
||||
const settings = require('../lib/util/settings');
|
||||
const Controller = require('../lib/controller');
|
||||
@@ -48,6 +49,8 @@ describe('Publish', () => {
|
||||
Object.values(zigbeeHerdsman.groups).forEach((g) => {
|
||||
g.command.mockClear();
|
||||
});
|
||||
|
||||
zigbeeHerdsmanConverters.toZigbeeConverters.__clearStore__();
|
||||
});
|
||||
|
||||
it('Should publish messages to zigbee devices', async () => {
|
||||
@@ -586,6 +589,22 @@ describe('Publish', () => {
|
||||
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 20, transtime: 200}, {}]);
|
||||
});
|
||||
|
||||
it('Transition parameter should not influence brightness on state ON', async () => {
|
||||
// https://github.com/Koenkk/zigbee2mqtt/issues/3563
|
||||
const device = zigbeeHerdsman.devices.bulb_color;
|
||||
const endpoint = device.getEndpoint(1);
|
||||
await MQTT.events.message('zigbee2mqtt/bulb_color/set', JSON.stringify({"state": "ON", "brightness": 50}));
|
||||
await flushPromises();
|
||||
await MQTT.events.message('zigbee2mqtt/bulb_color/set', JSON.stringify({"state": "ON"}));
|
||||
await flushPromises();
|
||||
await MQTT.events.message('zigbee2mqtt/bulb_color/set', JSON.stringify({"state": "ON", "transition": 1}));
|
||||
await flushPromises();
|
||||
expect(endpoint.command).toHaveBeenCalledTimes(3);
|
||||
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 50, transtime: 0}, {}]);
|
||||
expect(endpoint.command.mock.calls[1]).toEqual(["genOnOff", "on", {}, {}]);
|
||||
expect(endpoint.command.mock.calls[2]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 50, transtime: 10}, {}]);
|
||||
});
|
||||
|
||||
it('Should use transition when color temp', async () => {
|
||||
const device = zigbeeHerdsman.devices.bulb_color;
|
||||
settings.set(['devices', device.ieeeAddr, 'transition'], 20);
|
||||
@@ -719,7 +738,7 @@ describe('Publish', () => {
|
||||
await MQTT.events.message('zigbee2mqtt/bulb_color/set', JSON.stringify(payload));
|
||||
await flushPromises();
|
||||
expect(endpoint.command).toHaveBeenCalledTimes(1);
|
||||
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 255, transtime: 30}, {}]);
|
||||
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 254, transtime: 30}, {}]);
|
||||
});
|
||||
|
||||
it('Should turn device on with on/off with transition when transition 0 is provided', async () => {
|
||||
@@ -729,7 +748,7 @@ describe('Publish', () => {
|
||||
await MQTT.events.message('zigbee2mqtt/bulb_color/set', JSON.stringify(payload));
|
||||
await flushPromises();
|
||||
expect(endpoint.command).toHaveBeenCalledTimes(1);
|
||||
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 255, transtime: 0}, {}]);
|
||||
expect(endpoint.command.mock.calls[0]).toEqual(["genLevelCtrl", "moveToLevelWithOnOff", {level: 254, transtime: 0}, {}]);
|
||||
});
|
||||
|
||||
it('Should turn device off with onOff on off with transition', async () => {
|
||||
|
||||
Reference in New Issue
Block a user