2019-09-09 10:48:09 -07:00
const data = require ( './stub/data' ) ;
const logger = require ( './stub/logger' ) ;
2020-09-24 09:06:43 -07:00
const stringify = require ( 'json-stable-stringify-without-jsonify' ) ;
2019-09-09 10:48:09 -07:00
const zigbeeHerdsman = require ( './stub/zigbeeHerdsman' ) ;
const MQTT = require ( './stub/mqtt' ) ;
2018-11-26 09:47:44 -07:00
const settings = require ( '../lib/util/settings' ) ;
2019-09-09 10:48:09 -07:00
const Controller = require ( '../lib/controller' ) ;
const flushPromises = ( ) => new Promise ( setImmediate ) ;
const mocksClear = [ MQTT . publish , logger . warn , logger . debug ] ;
2020-04-15 13:34:59 -07:00
describe ( 'Receive' , ( ) => {
2019-09-09 10:48:09 -07:00
let controller ;
beforeEach ( async ( ) => {
jest . useRealTimers ( ) ;
data . writeDefaultConfiguration ( ) ;
settings . _reRead ( ) ;
data . writeEmptyState ( ) ;
controller = new Controller ( ) ;
await controller . start ( ) ;
mocksClear . forEach ( ( m ) => m . mockClear ( ) ) ;
2020-10-24 08:13:42 -07:00
delete zigbeeHerdsman . devices . WXKG11LM . linkquality ;
2019-09-09 10:48:09 -07:00
} ) ;
it ( 'Should handle a zigbee message' , async ( ) => {
const device = zigbeeHerdsman . devices . WXKG11LM ;
2020-10-24 08:13:42 -07:00
device . linkquality = 10 ;
2019-09-09 10:48:09 -07:00
const data = { onOff : 1 }
const payload = { data , cluster : 'genOnOff' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
2020-08-13 11:00:35 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/button' , stringify ( { action : 'single' , click : 'single' , linkquality : 10 } ) , { retain : false , qos : 0 } , expect . any ( Function ) ) ;
2019-09-09 10:48:09 -07:00
} ) ;
it ( 'Should handle a zigbee message which uses ep (left)' , async ( ) => {
2020-12-28 13:15:45 -07:00
const device = zigbeeHerdsman . devices . WXKG02LM _rev1 ;
2019-09-09 10:48:09 -07:00
const data = { onOff : 1 }
const payload = { data , cluster : 'genOnOff' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/button_double_key' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { click : 'left' , action : 'single_left' } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 0 , "retain" : false } ) ;
} ) ;
it ( 'Should handle a zigbee message which uses ep (right)' , async ( ) => {
2020-12-28 13:15:45 -07:00
const device = zigbeeHerdsman . devices . WXKG02LM _rev1 ;
2019-09-09 10:48:09 -07:00
const data = { onOff : 1 }
const payload = { data , cluster : 'genOnOff' , device , endpoint : device . getEndpoint ( 2 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/button_double_key' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { click : 'right' , action : 'single_right' } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 0 , "retain" : false } ) ;
} ) ;
it ( 'Should handle a zigbee message with default precision' , async ( ) => {
const device = zigbeeHerdsman . devices . WSDCGQ11LM ;
const data = { measuredValue : - 85 }
const payload = { data , cluster : 'msTemperatureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/weather_sensor' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { temperature : - 0.85 } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 1 , "retain" : false } ) ;
} ) ;
2020-08-02 01:08:55 -07:00
it ( 'Should allow to invert cover' , async ( ) => {
const device = zigbeeHerdsman . devices . J1 ;
// Non-inverted (open = 100, close = 0)
await zigbeeHerdsman . events . message ( { data : { currentPositionLiftPercentage : 90 , currentPositionTiltPercentage : 80 } , cluster : 'closuresWindowCovering' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
2020-10-24 08:13:42 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/J1_cover' , stringify ( { position : 10 , tilt : 20 } ) , { retain : false , qos : 0 } , expect . any ( Function ) ) ;
2020-08-02 01:08:55 -07:00
// Inverted
MQTT . publish . mockClear ( ) ;
settings . set ( [ 'devices' , device . ieeeAddr , 'invert_cover' ] , true ) ;
await zigbeeHerdsman . events . message ( { data : { currentPositionLiftPercentage : 90 , currentPositionTiltPercentage : 80 } , cluster : 'closuresWindowCovering' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
2020-10-24 08:13:42 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/J1_cover' , stringify ( { position : 90 , tilt : 80 } ) , { retain : false , qos : 0 } , expect . any ( Function ) ) ;
2020-08-02 01:08:55 -07:00
} ) ;
2020-07-26 05:19:33 -07:00
it ( 'Should allow to disable the legacy integration' , async ( ) => {
const device = zigbeeHerdsman . devices . WXKG11LM ;
settings . set ( [ 'devices' , device . ieeeAddr , 'legacy' ] , false ) ;
const data = { onOff : 1 }
const payload = { data , cluster : 'genOnOff' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
2020-10-24 08:13:42 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/button' , stringify ( { action : 'single' } ) , { retain : false , qos : 0 } , expect . any ( Function ) ) ;
2020-07-26 05:19:33 -07:00
} ) ;
2019-09-09 10:48:09 -07:00
it ( 'Should debounce messages' , async ( ) => {
jest . useFakeTimers ( ) ;
const device = zigbeeHerdsman . devices . WSDCGQ11LM ;
settings . set ( [ 'devices' , device . ieeeAddr , 'debounce' ] , 0.1 ) ;
const data1 = { measuredValue : 8 }
const payload1 = { data : data1 , cluster : 'msTemperatureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload1 ) ;
const data2 = { measuredValue : 1 }
const payload2 = { data : data2 , cluster : 'msRelativeHumidity' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload2 ) ;
const data3 = { measuredValue : 2 }
const payload3 = { data : data3 , cluster : 'msPressureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload3 ) ;
await flushPromises ( ) ;
jest . advanceTimersByTime ( 50 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 0 ) ;
jest . runAllTimers ( ) ;
2019-09-12 13:48:23 -07:00
await flushPromises ( ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/weather_sensor' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { temperature : 0.08 , humidity : 0.01 , pressure : 2 } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 1 , "retain" : false } ) ;
} ) ;
2020-02-27 13:06:27 -07:00
it ( 'Should debounce and retain messages when set via device_options' , async ( ) => {
jest . useFakeTimers ( ) ;
const device = zigbeeHerdsman . devices . WSDCGQ11LM ;
settings . set ( [ 'device_options' , 'debounce' ] , 0.1 ) ;
settings . set ( [ 'device_options' , 'retain' ] , true ) ;
delete settings . get ( ) . devices [ '0x0017880104e45522' ] [ 'retain' ] ;
const data1 = { measuredValue : 8 }
const payload1 = { data : data1 , cluster : 'msTemperatureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload1 ) ;
const data2 = { measuredValue : 1 }
const payload2 = { data : data2 , cluster : 'msRelativeHumidity' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload2 ) ;
const data3 = { measuredValue : 2 }
const payload3 = { data : data3 , cluster : 'msPressureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload3 ) ;
await flushPromises ( ) ;
jest . advanceTimersByTime ( 50 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 0 ) ;
jest . runAllTimers ( ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/weather_sensor' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { temperature : 0.08 , humidity : 0.01 , pressure : 2 } ) ;
2020-02-27 13:06:27 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 1 , "retain" : true } ) ;
} ) ;
2019-11-20 13:21:23 -07:00
it ( 'Should debounce messages only with the same payload values for provided debounce_ignore keys' , async ( ) => {
jest . useFakeTimers ( ) ;
const device = zigbeeHerdsman . devices . WSDCGQ11LM ;
settings . set ( [ 'devices' , device . ieeeAddr , 'debounce' ] , 0.1 ) ;
settings . set ( [ 'devices' , device . ieeeAddr , 'debounce_ignore' ] , [ 'temperature' ] ) ;
const tempMsg = { data : { measuredValue : 8 } , cluster : 'msTemperatureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 13 } ;
await zigbeeHerdsman . events . message ( tempMsg ) ;
const pressureMsg = { data : { measuredValue : 2 } , cluster : 'msPressureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 13 } ;
await zigbeeHerdsman . events . message ( pressureMsg ) ;
const tempMsg2 = { data : { measuredValue : 7 } , cluster : 'msTemperatureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 13 } ;
await zigbeeHerdsman . events . message ( tempMsg2 ) ;
const humidityMsg = { data : { measuredValue : 3 } , cluster : 'msRelativeHumidity' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 13 } ;
await zigbeeHerdsman . events . message ( humidityMsg ) ;
await flushPromises ( ) ;
jest . advanceTimersByTime ( 50 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { temperature : 0.08 , pressure : 2 } ) ;
2019-11-20 13:21:23 -07:00
jest . runAllTimers ( ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 2 ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 1 ] [ 1 ] ) ) . toStrictEqual ( { temperature : 0.07 , pressure : 2 , humidity : 0.03 } ) ;
2020-05-29 10:24:59 -07:00
} ) ;
it ( 'Shouldnt republish old state' , async ( ) => {
// https://github.com/Koenkk/zigbee2mqtt/issues/3572
jest . useFakeTimers ( ) ;
const device = zigbeeHerdsman . devices . bulb ;
settings . set ( [ 'devices' , device . ieeeAddr , 'debounce' ] , 0.1 ) ;
await zigbeeHerdsman . events . message ( { data : { onOff : 0 } , cluster : 'genOnOff' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ) ;
2020-08-13 11:00:35 -07:00
await MQTT . events . message ( 'zigbee2mqtt/bulb/set' , stringify ( { state : 'ON' } ) ) ;
2020-05-29 10:24:59 -07:00
await flushPromises ( ) ;
jest . runAllTimers ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 2 ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { state : 'ON' } ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 1 ] [ 1 ] ) ) . toStrictEqual ( { state : 'ON' } ) ;
2019-11-20 13:21:23 -07:00
} ) ;
2019-09-09 10:48:09 -07:00
it ( 'Should handle a zigbee message with 1 precision' , async ( ) => {
const device = zigbeeHerdsman . devices . WSDCGQ11LM ;
settings . set ( [ 'devices' , device . ieeeAddr , 'temperature_precision' ] , 1 ) ;
const data = { measuredValue : - 85 }
const payload = { data , cluster : 'msTemperatureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/weather_sensor' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { temperature : - 0.8 } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 1 , "retain" : false } ) ;
} ) ;
it ( 'Should handle a zigbee message with 0 precision' , async ( ) => {
const device = zigbeeHerdsman . devices . WSDCGQ11LM ;
settings . set ( [ 'devices' , device . ieeeAddr , 'temperature_precision' ] , 0 ) ;
const data = { measuredValue : - 85 }
const payload = { data , cluster : 'msTemperatureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/weather_sensor' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { temperature : - 1 } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 1 , "retain" : false } ) ;
} ) ;
it ( 'Should handle a zigbee message with 1 precision when set via device_options' , async ( ) => {
const device = zigbeeHerdsman . devices . WSDCGQ11LM ;
settings . set ( [ 'device_options' , 'temperature_precision' ] , 1 ) ;
const data = { measuredValue : - 85 }
const payload = { data , cluster : 'msTemperatureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/weather_sensor' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { temperature : - 0.8 } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 1 , "retain" : false } ) ;
} ) ;
it ( 'Should handle a zigbee message with 2 precision when overrides device_options' , async ( ) => {
const device = zigbeeHerdsman . devices . WSDCGQ11LM ;
settings . set ( [ 'device_options' , 'temperature_precision' ] , 1 ) ;
settings . set ( [ 'devices' , device . ieeeAddr , 'temperature_precision' ] , 0 ) ;
const data = { measuredValue : - 85 }
const payload = { data , cluster : 'msTemperatureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/weather_sensor' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { temperature : - 1 } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 1 , "retain" : false } ) ;
} ) ;
2020-02-23 12:47:38 -07:00
it ( 'WSDCGQ11LM pressure precision from non ZCL properties' , async ( ) => {
const device = zigbeeHerdsman . devices . WSDCGQ11LM ;
settings . set ( [ 'devices' , device . ieeeAddr , 'temperature_precision' ] , 1 ) ;
MQTT . publish . mockClear ( ) ;
let payload = { data : { "65281" : { "1" : 2985 , "4" : 5032 , "5" : 9 , "6" : [ 0 , 1 ] , "10" : 0 , "100" : 2345 , "101" : 4608 , "102" : 91552 } } , cluster : 'genBasic' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { "battery" : 91 , "voltage" : 2985 , "temperature" : 23.5 , "humidity" : 46.08 , "pressure" : 915.5 } ) ;
2020-02-23 12:47:38 -07:00
MQTT . publish . mockClear ( ) ;
payload = { data : { "16" : 9354 , "20" : - 1 , "measuredValue" : 915 } , cluster : 'msPressureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { "battery" : 91 , "voltage" : 2985 , "temperature" : 23.5 , "humidity" : 46.08 , "pressure" : 935.4 } ) ;
2020-02-23 12:47:38 -07:00
} ) ;
2019-09-09 10:48:09 -07:00
it ( 'Should handle a zigbee message with voltage 3010' , async ( ) => {
2020-12-28 13:15:45 -07:00
const device = zigbeeHerdsman . devices . WXKG02LM _rev1 ;
2019-09-09 10:48:09 -07:00
const data = { '65281' : { '1' : 3010 } }
const payload = { data , cluster : 'genBasic' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/button_double_key' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { battery : 100 , voltage : 3010 } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 0 , "retain" : false } ) ;
} ) ;
it ( 'Should handle a zigbee message with voltage 2850' , async ( ) => {
2020-12-28 13:15:45 -07:00
const device = zigbeeHerdsman . devices . WXKG02LM _rev1 ;
2019-09-09 10:48:09 -07:00
const data = { '65281' : { '1' : 2850 } }
const payload = { data , cluster : 'genBasic' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/button_double_key' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { battery : 35 , voltage : 2850 } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 0 , "retain" : false } ) ;
} ) ;
it ( 'Should handle a zigbee message with voltage 2650' , async ( ) => {
2020-12-28 13:15:45 -07:00
const device = zigbeeHerdsman . devices . WXKG02LM _rev1 ;
2019-09-09 10:48:09 -07:00
const data = { '65281' : { '1' : 2650 } }
const payload = { data , cluster : 'genBasic' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/button_double_key' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { battery : 14 , voltage : 2650 } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 0 , "retain" : false } ) ;
} ) ;
it ( 'Should handle a zigbee message with voltage 2000' , async ( ) => {
2020-12-28 13:15:45 -07:00
const device = zigbeeHerdsman . devices . WXKG02LM _rev1 ;
2019-09-09 10:48:09 -07:00
const data = { '65281' : { '1' : 2000 } }
const payload = { data , cluster : 'genBasic' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/button_double_key' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { battery : 0 , voltage : 2000 } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 0 , "retain" : false } ) ;
} ) ;
it ( 'Should publish 1 message when converted twice' , async ( ) => {
const device = zigbeeHerdsman . devices . RTCGQ11LM ;
const data = { '65281' : { '1' : 3045 , '3' : 19 , '4' : 17320 , '5' : 35 , '6' : [ 0 , 3 ] , '10' : 51107 , '11' : 381 , '100' : 0 } }
const payload = { data , cluster : 'genBasic' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/occupancy_sensor' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { 'battery' : 100 , 'illuminance' : 381 , "illuminance_lux" : 381 , 'voltage' : 3045 } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 0 , "retain" : false } ) ;
} ) ;
it ( 'Should publish 1 message when converted twice' , async ( ) => {
const device = zigbeeHerdsman . devices . RTCGQ11LM ;
const data = { '9999' : { '1' : 3045 } } ;
const payload = { data , cluster : 'genBasic' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 0 ) ;
} ) ;
it ( 'Should publish last_seen epoch' , async ( ) => {
2020-12-28 13:15:45 -07:00
const device = zigbeeHerdsman . devices . WXKG02LM _rev1 ;
2019-09-09 10:48:09 -07:00
settings . set ( [ 'advanced' , 'last_seen' ] , 'epoch' ) ;
const data = { onOff : 1 } ;
const payload = { data , cluster : 'genOnOff' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/button_double_key' ) ;
expect ( typeof JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) . last _seen ) . toBe ( 'number' )
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 0 , "retain" : false } ) ;
} ) ;
it ( 'Should publish last_seen ISO_8601' , async ( ) => {
2020-12-28 13:15:45 -07:00
const device = zigbeeHerdsman . devices . WXKG02LM _rev1 ;
2019-09-09 10:48:09 -07:00
settings . set ( [ 'advanced' , 'last_seen' ] , 'ISO_8601' ) ;
const data = { onOff : 1 } ;
const payload = { data , cluster : 'genOnOff' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/button_double_key' ) ;
expect ( typeof JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) . last _seen ) . toBe ( 'string' )
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 0 , "retain" : false } ) ;
} ) ;
it ( 'Should publish last_seen ISO_8601_local' , async ( ) => {
2020-12-28 13:15:45 -07:00
const device = zigbeeHerdsman . devices . WXKG02LM _rev1 ;
2019-09-09 10:48:09 -07:00
settings . set ( [ 'advanced' , 'last_seen' ] , 'ISO_8601_local' ) ;
const data = { onOff : 1 } ;
const payload = { data , cluster : 'genOnOff' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/button_double_key' ) ;
expect ( typeof JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) . last _seen ) . toBe ( 'string' )
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 0 , "retain" : false } ) ;
} ) ;
2020-08-23 13:05:48 -07:00
it ( 'Should handle forwarded Xiaomi messages' , async ( ) => {
2019-09-09 10:48:09 -07:00
const device = zigbeeHerdsman . devices . ZNCZ02LM ;
2020-08-23 13:05:48 -07:00
const payload = { data : { measuredValue : - 85 } , cluster : 'msTemperatureMeasurement' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 , groupID : 6539 } ;
2019-09-09 10:48:09 -07:00
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
2020-08-23 13:05:48 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/weather_sensor' ,
2020-10-24 08:13:42 -07:00
stringify ( { temperature : - 0.85 } ) ,
2020-08-23 13:05:48 -07:00
{ "qos" : 1 , "retain" : false } ,
expect . any ( Function ) ,
)
2019-09-09 10:48:09 -07:00
} ) ;
it ( 'Should handle messages from Xiaomi router devices' , async ( ) => {
const device = zigbeeHerdsman . devices . ZNCZ02LM ;
const data = { onOff : 1 } ;
const payload = { data , cluster : 'genOnOff' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 20 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
2020-10-09 12:40:33 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 2 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/power_plug' ,
2020-10-24 08:13:42 -07:00
stringify ( { state : 'ON' } ) ,
2020-10-09 12:40:33 -07:00
{ retain : false , qos : 0 } ,
expect . any ( Function )
) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/switch_group' ,
stringify ( { 'state' : 'ON' } ) ,
{ retain : false , qos : 0 } ,
expect . any ( Function )
) ;
2019-09-09 10:48:09 -07:00
} ) ;
it ( 'Should not handle messages from coordinator' , async ( ) => {
const device = zigbeeHerdsman . devices . coordinator ;
const data = { onOff : 1 } ;
const payload = { data , cluster : 'genOnOff' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 0 ) ;
} ) ;
2020-07-22 05:00:27 -07:00
it ( 'Should not handle messages from unsupported devices and link to docs' , async ( ) => {
2019-09-09 10:48:09 -07:00
const device = zigbeeHerdsman . devices . unsupported ;
const data = { onOff : 1 } ;
2020-07-22 05:00:27 -07:00
logger . warn . mockClear ( ) ;
2019-09-09 10:48:09 -07:00
const payload = { data , cluster : 'genOnOff' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
2020-11-11 10:27:20 -07:00
expect ( logger . warn ) . toHaveBeenCalledWith ( ` Received message from unsupported device with Zigbee model 'notSupportedModelID' and manufacturer name 'notSupportedMfg' ` ) ;
2020-07-22 05:00:27 -07:00
expect ( logger . warn ) . toHaveBeenCalledWith ( ` Please see: https://www.zigbee2mqtt.io/how_tos/how_to_support_new_devices.html. ` ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 0 ) ;
} ) ;
2020-07-22 05:00:27 -07:00
it ( 'Should not handle messages from still interviewing devices with unknown definition' , async ( ) => {
2019-09-09 10:48:09 -07:00
const device = zigbeeHerdsman . devices . interviewing ;
const data = { onOff : 1 } ;
2020-07-22 05:00:27 -07:00
logger . debug . mockClear ( ) ;
2019-09-09 10:48:09 -07:00
const payload = { data , cluster : 'genOnOff' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 0 ) ;
2020-07-22 05:00:27 -07:00
expect ( logger . debug ) . toHaveBeenCalledWith ( ` Skipping message, definition is undefined and still interviewing ` ) ;
2019-09-09 10:48:09 -07:00
} ) ;
it ( 'Should handle a command' , async ( ) => {
const device = zigbeeHerdsman . devices . E1743 ;
const data = { } ;
const payload = { data , cluster : 'genLevelCtrl' , device , endpoint : device . getEndpoint ( 1 ) , type : 'commandStopWithOnOff' , linkquality : 10 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/ikea_onoff' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { 'click' : 'brightness_stop' , action : 'brightness_stop' } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 0 , "retain" : false } ) ;
} ) ;
it ( 'Should add elapsed' , async ( ) => {
settings . set ( [ 'advanced' , 'elapsed' ] , true ) ;
const device = zigbeeHerdsman . devices . E1743 ;
const payload = { data : { } , cluster : 'genLevelCtrl' , device , endpoint : device . getEndpoint ( 1 ) , type : 'commandStopWithOnOff' } ;
const oldNow = Date . now ;
Date . now = jest . fn ( )
Date . now . mockReturnValue ( new Date ( 150 ) ) ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
Date . now . mockReturnValue ( new Date ( 200 ) ) ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 2 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/ikea_onoff' ) ;
2020-07-26 05:19:33 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { 'click' : 'brightness_stop' , action : 'brightness_stop' } ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 2 ] ) . toStrictEqual ( { "qos" : 0 , "retain" : false } ) ;
expect ( MQTT . publish . mock . calls [ 1 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/ikea_onoff' ) ;
2020-07-26 05:19:33 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 1 ] [ 1 ] ) ) . toMatchObject ( { 'click' : 'brightness_stop' , action : 'brightness_stop' } ) ;
2019-09-09 10:48:09 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 1 ] [ 1 ] ) . elapsed ) . toBe ( 50 ) ;
expect ( MQTT . publish . mock . calls [ 1 ] [ 2 ] ) . toStrictEqual ( { "qos" : 0 , "retain" : false } ) ;
Date . now = oldNow ;
2018-11-27 13:50:55 -07:00
} ) ;
2019-09-09 10:48:09 -07:00
it ( 'Should log when message is from supported device but has no converters' , async ( ) => {
const device = zigbeeHerdsman . devices . ZNCZ02LM ;
const data = { inactiveText : 'hello' } ;
const payload = { data , cluster : 'genBinaryOutput' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 20 } ;
await zigbeeHerdsman . events . message ( payload ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 0 ) ;
2019-12-17 11:19:57 -07:00
expect ( logger . debug ) . toHaveBeenCalledWith ( 'No converter available for \'ZNCZ02LM\' with cluster \'genBinaryOutput\' and type \'attributeReport\' and data \'{"inactiveText":"hello"}\'' ) ;
2018-11-26 09:47:44 -07:00
} ) ;
2019-09-26 00:43:40 -07:00
2020-01-17 14:51:37 -07:00
it ( 'Should report correct energy and power values for different versions of SP600' , async ( ) => {
// https://github.com/Koenkk/zigbee-herdsman-converters/issues/915, OLD and NEW use different date code
// divisor of OLD is not correct and therefore underreports by factor 10.
const data = { instantaneousDemand : 496 , currentSummDelivered : [ 0 , 6648 ] }
const SP600 _NEW = zigbeeHerdsman . devices . SP600 _NEW ;
await zigbeeHerdsman . events . message ( { data , cluster : 'seMetering' , device : SP600 _NEW , endpoint : SP600 _NEW . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ) ;
2019-09-26 00:43:40 -07:00
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
2020-01-17 14:51:37 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/SP600_NEW' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { energy : 0.66 , power : 49.6 } ) ;
2020-01-17 14:51:37 -07:00
MQTT . publish . mockClear ( ) ;
const SP600 _OLD = zigbeeHerdsman . devices . SP600 _OLD ;
await zigbeeHerdsman . events . message ( { data , cluster : 'seMetering' , device : SP600 _OLD , endpoint : SP600 _OLD . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/SP600_OLD' ) ;
2020-10-24 08:13:42 -07:00
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { energy : 6.648 , power : 496 } ) ;
2019-09-26 00:43:40 -07:00
} ) ;
2018-11-26 09:47:44 -07:00
} ) ;