def test_mi_curtain(): device = XDevice(ZIGBEE, 'lumi.curtain.acn002', ZDID, ZMAC, ZNWK) assert device.info.name == 'Aqara Roller Shade E1 CN' device.setup_converters() p = device.decode_lumi([ {"siid": 2, "piid": 1, "value": 0}, {"siid": 2, "piid": 3, "value": 0}, {"siid": 2, "piid": 4, "value": 60}, {"siid": 2, "piid": 5, "value": 60} ]) assert p == {'position': 60, 'target_position': 60} p = device.decode_lumi([ {"siid": 3, "piid": 1, "value": 1}, {"siid": 3, "piid": 2, "value": 7317}, {"siid": 3, "piid": 3, "value": 0}, {"siid": 3, "piid": 4, "value": 48} ]) assert p == { 'battery': 48, 'battery_charging': False, 'battery_low': False, 'battery_voltage': 7317 } p = device.decode_lumi([{"siid": 2, "piid": 6, "value": 0}]) assert p == {'run_state': 'closing'} p = device.decode_lumi([{"siid": 2, "piid": 2, "value": 1}]) assert p == {'motor': 'close'} p = device.encode({'motor': 'open'}) assert p == {"mi_spec": [{'siid': 2, 'piid': 2, 'value': 2}]} p = device.encode({"position": 60}) assert p == {'mi_spec': [{'siid': 2, 'piid': 4, 'value': 60}]}
def test_lock(): device = XDevice(BLE, 1694, DID2, MAC) assert device.info.name == "Aqara Door Lock N100 (Bluetooth)" device.setup_converters() p = device.decode("mibeacon", {'eid': 4106, 'edata': '3259f80362'}) assert p == {'battery': 50}
def test_light(): device = XDevice(ZIGBEE, 'ikea.light.led1650r5', ZDID, ZMAC, ZNWK) assert device.info.name == 'IKEA Bulb GU10 400 lm' device.setup_converters() p = device.decode_lumi([{"res_name": "14.1.85", "value": 80}]) assert p == {'brightness': 204.0}
def test_mesh(): device = XDevice(MESH, 1771, "123", "112233aabbcc") assert device.info.name == 'Xiaomi Mesh Bulb' device.setup_converters() p = device.decode_lumi([{ 'did': '1234567890', 'siid': 2, 'piid': 1, 'value': True, 'code': 0 }, { 'did': '1234567890', 'siid': 2, 'piid': 2, 'value': 65535, 'code': 0 }, { 'did': '1234567890', 'siid': 2, 'piid': 3, 'value': 4000, 'code': 0 }]) assert p == {'light': True, 'brightness': 255.0, 'color_temp': 250}
def test_sensor_ht_heartbeat(): device = XDevice(ZIGBEE, 'lumi.sensor_ht', ZDID, ZMAC, ZNWK) device.setup_converters() assert device.info.name == 'Xiaomi TH Sensor' p = device.decode_lumi([ {"res_name": "8.0.2008", "value": 2955}, {"res_name": "8.0.2001", "value": 59}, {"res_name": "8.0.2011", "value": 1}, {"res_name": "8.0.2010", "value": 3}, {"res_name": "8.0.2012", "value": 10}, {"res_name": "8.0.2013", "value": 1}, {"res_name": "8.0.2002", "value": 11651}, {"res_name": "8.0.2003", "value": 2}, {"res_name": "8.0.2004", "value": 0}, {"res_name": "8.0.2005", "value": 0}, {"res_name": "8.0.2033", "value": 0}, {"res_name": "0.1.85", "value": 2384}, {"res_name": "0.2.85", "value": 4509}, {"res_name": "8.0.2036", "value": ""}, {"res_name": "8.0.2022", "value": 0}, {"res_name": "8.0.2023", "value": 0}, {"res_name": "8.0.2007", "value": 216} ]) assert p == { 'battery': 51, "battery_voltage": 2955, 'resets': 11651, 'temperature': 23.84, 'humidity': 45.09, 'parent': "-", 'fw_ver': 0, 'battery_original': 59 }
def test_gateway_stats(): device = XDevice(GATEWAY, 'lumi.gateway.mgl03', DID, MAC) device.setup_converters() p = device.decode(GATEWAY, {'networkUp': False}) assert p == { 'network_pan_id': None, 'radio_channel': None, 'radio_tx_power': None } p = device.decode( GATEWAY, { 'networkUp': True, 'networkPanId': '0x9180', 'radioTxPower': 7, 'radioChannel': 15 }) assert p == { 'network_pan_id': '0x9180', 'radio_tx_power': 7, 'radio_channel': 15 } p = device.decode( GATEWAY, { 'free_mem': 3488, 'ip': '192.168.1.123', 'load_avg': '1.92|2.00|2.25|5/91|21135', 'rssi': 58, 'run_time': 367357, 'setupcode': '123-45-678', 'ssid': 'WiFi', 'tz': 'GMT3' }) assert p == { 'free_mem': 3488, 'load_avg': '1.92|2.00|2.25|5/91|21135', 'rssi': -42, 'uptime': '4 days, 06:02:37' } p = device.decode( GATEWAY, { 'serial': """serinfo:1.0 driver revision: 0: uart:16550A mmio:0x18147000 irq:17 tx:6337952 rx:0 RTS|CTS|DTR 1: uart:16550A mmio:0x18147400 irq:46 tx:19370 rx:154557484 oe:1684 RTS|DTR 2: uart:16550A mmio:0x18147800 irq:47 tx:1846359 rx:3845724 oe:18 RTS|DTR""" }) assert p == { 'bluetooth_tx': 19370, 'bluetooth_rx': 154557484, 'bluetooth_oe': 1684, 'zigbee_tx': 1846359, 'zigbee_rx': 3845724, 'zigbee_oe': 18 }
def test_kettle(): device = XDevice(BLE, 131, DID, MAC) assert device.info.name == "Xiaomi Kettle" device.setup_converters() p = device.decode("mibeacon", {'eid': 4101, 'edata': '0063'}) assert p == {'power': False, 'state': 'idle', 'temperature': 99} p = device.decode("mibeacon", {'eid': 4101, 'edata': '0154'}) assert p == {'power': True, 'state': 'heat', 'temperature': 84}
def test_new_th(): device = XDevice(BLE, 4611, DID, MAC) assert device.info.name == "Xiaomi TH Sensor" device.setup_converters() p = device.decode("mibeacon", {'eid': 19464, 'edata': 'cdcc3e42'}) assert p == {'humidity': 47.7} p = device.decode("mibeacon", {'eid': 19457, 'edata': 'cdcca841'}) assert p == {'temperature': 21.1}
def test_resets(): device = XDevice(ZIGBEE, 'lumi.plug', ZDID, ZMAC, ZNWK) device.setup_converters() params = [{"res_name": "8.0.2002", "value": 24}] assert device.decode_lumi(params) == {'resets': 24, 'new_resets': 0} params = [{"res_name": "8.0.2002", "value": 27}] assert device.decode_lumi(params) == {'resets': 27, 'new_resets': 3}
def test_gateway(): device = XDevice(GATEWAY, "lumi.gateway.mgl03", DID, MAC) assert device.info.name == "Xiaomi Gateway 3" device.setup_converters() p = device.decode_lumi([{"res_name": "8.0.2109", "value": 60}]) assert p == {'pair': True} p = device.encode({'pair': False}) assert p == {"params": [{"res_name": "8.0.2109", "value": 0}]} # old zigbee pairing p = device.decode_lumi([{ "res_name": "8.0.2111", "value": { "code": 0, "install_code": "", "mac": "", "message": "no data" }, "error_code": 0 }]) assert p # _sync.zigbee3_get_install_code error p = device.decode_lumi([{ "res_name": "8.0.2111", "value": { "code": -4001002, "install_code": "", "mac": "", "message": "no data" }, "error_code": 0 }]) assert p # zigbee3 pairing p = device.decode_lumi([{ "res_name": "8.0.2111", "value": { "code": 0, "install_code": "<36 hex>", "mac": "<16 hex>" }, "error_code": 0 }]) assert p p = device.decode_lumi([{ "res_name": "8.0.2155", "value": "{\"cloud_link\":1,\"tz_updated\":\"GMT3\"}" }]) assert p == {'cloud_link': True}
def test_opple_buttons(): device = XDevice(ZIGBEE, 'lumi.remote.b686opcn01', ZDID, ZMAC, ZNWK) assert device.info.name == 'Aqara Opple Six Button CN' device.setup_converters() p = device.decode_lumi([{"res_name": "13.1.85", "value": 1}]) assert p == {'action': 'button_1_single', 'button_1': 1} p = device.decode_lumi([{"res_name": "13.2.85", "value": 16}]) assert p == {'action': 'button_2_hold', 'button_2': 16}
def test_event(): device = XDevice(MESH, 1946, "123", "112233aabbcc") device.setup_converters() p = device.decode_miot([{ "did": "1234567890", "siid": 8, "eiid": 1, "arguments": [] }]) assert p == {'button_1': 1, 'action': 'button_1_single'}
def test_sensor_motion(): device = XDevice(ZIGBEE, 'lumi.sensor_motion.aq2', ZDID, ZMAC, ZNWK) assert device.info.name == 'Aqara Motion Sensor' device.setup_converters() p = device.decode_lumi([ {"res_name": "0.3.85", "value": 6}, {"res_name": "0.4.85", "value": 6}, {"res_name": "3.1.85", "value": 1} ]) assert p == {'illuminance': 6, 'motion': True}
def test_aqara_cube(): device = XDevice(ZIGBEE, "lumi.sensor_cube", ZDID, ZMAC, ZNWK) assert device.info.name == "Aqara Cube" device.setup_converters() p = silabs.decode({ "clusterId": "0x0012", "sourceEndpoint": "0x02", "APSPlayload": "0x18140A5500215900" }) p = device.decode_zigbee(p) assert p == {'action': 'flip90', 'from_side': 3, 'to_side': 1}
def test_night_light(): device = XDevice(BLE, 2038, DID, MAC) assert device.info.name == "Xiaomi Night Light 2" device.setup_converters() p = device.decode("mibeacon", {"eid": 15, "edata": "640000"}) assert p == {'light': True, 'motion': True} p = device.decode("mibeacon", {'eid': 4103, 'edata': '640000'}) assert p == {'light': True} p = device.decode("mibeacon", {'eid': 4106, 'edata': '64'}) assert p == {'battery': 100} p = device.decode("mibeacon", {'eid': 4119, 'edata': '78000000'}) assert p == {'idle_time': 120}
def test_lock_s2(): device = XDevice(ZIGBEE, 'lumi.lock.acn02', ZDID, ZMAC, ZNWK) assert device.info.name == 'Aqara Door Lock S2 CN' device.setup_converters() p = device.decode_lumi([{"res_name": "13.16.85", "value": 17}]) assert p == {'square': True, 'reverse': False, 'latch': True} p = device.decode_lumi([ {"res_name": "13.1.85", "value": 65536}, {"res_name": "13.15.85", "value": 1} ]) assert p == {'action': 'lock', 'key_id': 65536}
def test_lumi_encode(): device = XDevice(ZIGBEE, 'lumi.plug', ZDID, ZMAC, ZNWK) device.setup_converters() p = device.encode({'plug': True}) assert p == {"params": [{'res_name': '4.1.85', 'value': 1}]} device = XDevice(ZIGBEE, 'lumi.switch.l0agl1', ZDID, ZMAC, ZNWK) assert device.info.name == 'Aqara Relay T1 EU (no N)' device.setup_converters() p = device.encode({'switch': True}) assert p == {'mi_spec': [{'siid': 2, 'piid': 1, 'value': True}]}
def test_lock_s2_pro(): device = XDevice(ZIGBEE, 'lumi.lock.acn03', ZDID, ZMAC, ZNWK) assert device.info.name == 'Aqara Door Lock S2 Pro CN' device.setup_converters() p = device.decode_lumi([ {"res_name": "13.16.85", "value": 81}, {"res_name": "3.1.85", "value": 0}, {"res_name": "13.28.85", "value": 3} ]) assert p == { 'lock': True, 'square': True, 'reverse': False, 'latch': True, 'action': 'lock', 'lock_state': 'door_locked' } p = device.decode_lumi([ {"res_name": "13.16.85", "value": 64}, {"res_name": "13.25.85", "value": 0}, {"res_name": "13.28.85", "value": 2} ]) assert p == { 'lock': True, 'square': False, 'reverse': False, 'latch': False, 'action': 'lock', 'lock_control': 'in_unlocked', 'lock_state': 'door_without_lift' } p = device.decode_lumi([{"res_name": "13.5.85", "value": 512}]) assert p == {'action': 'doorbell'} p = device.decode_lumi([ {"res_name": "13.1.85", "value": 131072}, {"res_name": "13.15.85", "value": 2} ]) assert p == {'action': 'lock', 'key_id': 131072} p = device.decode_lumi([{"res_name": "13.5.85", "value": 4}]) assert p == {'action': 'alarm', 'alarm': 'unlocked'} p = device.decode_lumi([ {"res_name": "13.26.85", "value": 2}, {"res_name": "13.28.85", "value": 1} ]) assert p == { 'action': 'lock', 'door_state': 'ajar', 'lock_state': 'door_opened' } p = device.decode_lumi([{"res_name": "13.4.85", "value": 1}]) assert p == {'action': 'error', 'error': 'fing_wrong', 'fing_wrong': 1} p = device.decode_lumi([{"res_name": "13.3.85", "value": 3}]) assert p == {'action': 'error', 'error': 'psw_wrong', 'psw_wrong': 3}
def test_error(): device = XDevice(ZIGBEE, 'lumi.motion.agl04', ZDID, ZMAC, ZNWK) assert device.info.name == 'Aqara Precision Motion Sensor EU' device.setup_converters() p = device.decode_lumi([{"siid": 10, "piid": 1, "code": -5020}]) assert p == {} device = XDevice(ZIGBEE, 'lumi.sensor_magnet.aq2', ZDID, ZMAC, ZNWK) assert device.info.name == 'Aqara Door/Window Sensor' device.setup_converters() p = device.decode_lumi([{"res_name": "8.0.2102", "error_code": -5020}]) assert p == {}
def test_mi_spec(): device = XDevice(ZIGBEE, 'lumi.sen_ill.mgl01', ZDID, ZMAC, ZNWK) assert device.info.name == 'Xiaomi Light Sensor EU' device.setup_converters() p = device.decode_lumi([{'siid': 3, 'piid': 1, 'value': 3100}]) assert p == {'battery': 80, 'battery_voltage': 3100} device = XDevice(ZIGBEE, 'lumi.motion.agl04', ZDID, ZMAC, ZNWK) assert device.info.name == 'Aqara Precision Motion Sensor EU' device.setup_converters() p = device.decode_lumi([{'siid': 4, 'eiid': 1, 'arguments': []}]) assert p == {'motion': True}
def test_gateway(): device = XDevice(GATEWAY, 'lumi.gateway.mgl03', "123456", "aabbccddeeff") assert device.info.name == 'Xiaomi Gateway 3' device.setup_converters() p = device.decode_lumi([{ "res_name": "8.0.2082", "value": "lumi.1234567890" }]) assert p == {"remove_did": "lumi.1234567890"} p = device.decode_lumi([{ "res_name": "8.0.2082", "value": {"did": "lumi.1234567890"} }]) assert p == {"remove_did": "lumi.1234567890"}
def test_tuya_button(): device = XDevice(ZIGBEE, "TS004F", ZDID, ZMAC, ZNWK) device.setup_converters() p0 = silabs.decode({ "clusterId": "0x0006", "sourceEndpoint": "0x03", "APSPlayload": "0x010AFD02", }) p = device.decode_zigbee(p0) assert p == {'button_3': 'hold', 'action': 'button_3_hold'} # test processing same sequence p = device.decode_zigbee(p0) assert p == {}
def test_zigbee_stats(): stats.now = lambda: datetime(2021, 12, 31, 23, 59) device = XDevice(ZIGBEE, 'lumi.plug', ZDID, ZMAC, ZNWK) device.setup_converters({ZIGBEE: "sensor"}) p = device.decode(ZIGBEE, { 'sourceAddress': '0x9B43', 'eui64': '0x00158D0000AABBCC', 'destinationEndpoint': '0x01', 'clusterId': '0x000A', 'profileId': '0x0104', 'sourceEndpoint': '0x01', 'APSCounter': '0x71', 'APSPlayload': '0x1071000000', 'rssi': -61, 'linkQuality': 156 }) assert p == { 'zigbee': p['zigbee'], # 'ieee': '0x00158D0000AABBCC', 'nwk': '0x9B43', 'msg_received': 1, 'msg_missed': 0, 'linkquality': 156, 'rssi': -61, 'last_msg': 'Time' } p = device.decode(ZIGBEE, { 'sourceAddress': '0x9B43', 'eui64': '0x00158D0000AABBCC', 'destinationEndpoint': '0x01', 'clusterId': '0x000A', 'profileId': '0x0104', 'sourceEndpoint': '0x01', 'APSCounter': '0x73', 'APSPlayload': '0x1075000000', 'rssi': -61, 'linkQuality': 156 }) assert p == { 'zigbee': p['zigbee'], # 'ieee': '0x00158D0000AABBCC', 'nwk': '0x9B43', 'msg_received': 2, 'msg_missed': 1, 'linkquality': 156, 'rssi': -61, 'last_msg': 'Time' } p = device.decode(ZIGBEE, { 'eui64': '', 'nwk': '0x9B43', 'ago': 60, 'type': 'device', 'parent': '0xABCD' }) assert p == {'parent': '0xABCD'} p = device.decode(ZIGBEE, {'parent': '0xABCD'}) assert p == {'parent': '0xABCD'} p = device.decode(ZIGBEE, {'resets': 10}) assert p == {'new_resets': 0} p = device.decode(ZIGBEE, {'resets': 15}) assert p == {'new_resets': 5}
def test_lumi_curtain(): device = XDevice(ZIGBEE, 'lumi.curtain', ZDID, ZMAC, ZNWK) assert device.info.name == 'Aqara Curtain' device.setup_converters() p = device.decode_lumi([{'res_name': '14.2.85', 'value': 1}]) assert p == {'motor': 'open'} p = device.decode_lumi([{"res_name": "1.1.85", "value": 100}]) assert p == {'position': 100} p = device.encode({"motor": "stop"}) assert p == {"params": [{'res_name': '14.2.85', 'value': 2}]} p = device.encode({"position": 48}) assert p == {"params": [{'res_name': '1.1.85', 'value': 48}]}
def test_brightness(): device = XDevice(MESH, 3164, "123", "112233aabbcc") device.setup_converters() p = device.encode({'light': True, 'brightness': 15.0, 'color_temp': 300}) assert p['mi_spec'] == [{ 'siid': 2, 'piid': 1, 'value': True }, { 'siid': 2, 'piid': 2, 'value': 6 }, { 'siid': 2, 'piid': 3, 'value': 3333 }]
def test_plug_heartbeat(): device = XDevice(ZIGBEE, 'lumi.plug', ZDID, ZMAC, ZNWK) assert device.info.name == 'Xiaomi Plug CN' device.setup_converters() params = [{ "res_name": "4.1.85", "value": 1 }, { "res_name": "8.0.2006", "value": 39 }, { "res_name": "0.12.85", "value": 14.56 }, { "res_name": "0.13.85", "value": 357696.31 }, { "res_name": "8.0.2002", "value": 24 }, { "res_name": "8.0.2231", "value": 0 }, { "res_name": "8.0.2022", "value": 90 }, { "res_name": "8.0.2023", "value": 19 }, { "res_name": "8.0.2228", "value": 4367 }, { "res_name": "8.0.2007", "value": 160 }] assert device.decode_lumi(params) == { 'plug': True, 'power': 14.56, 'energy': 357.7, 'resets': 24, 'fw_ver': 90, 'chip_temperature': 39, 'new_resets': 0, }
def test_config(): device = XDevice(ZIGBEE, "TS004F", ZDID, ZMAC, ZNWK) device.setup_converters() gw = type("", (), {"ieee": "0xAABBCC"}) p = {} for conv in device.converters: if isinstance(conv, ZConverter): conv.config(device, p, gw) assert p['commands'] == [{ 'commandcli': 'raw 6 {10000004000000010005000700feff}' }, { 'commandcli': 'send 0x12ab 1 1' }, { 'commandcli': 'zcl global read 57345 53265' }, { 'commandcli': 'send 0x12ab 1 1' }, { 'commandcli': 'zdo bind 0x12ab 1 1 6 {0000112233aabbcc} {0xAABBCC}' }, { 'commandcli': 'zdo bind 0x12ab 2 1 6 {0000112233aabbcc} {0xAABBCC}' }, { 'commandcli': 'zdo bind 0x12ab 3 1 6 {0000112233aabbcc} {0xAABBCC}' }, { 'commandcli': 'zdo bind 0x12ab 4 1 6 {0000112233aabbcc} {0xAABBCC}' }, { 'commandcli': 'zdo bind 0x12ab 1 1 1 {0000112233aabbcc} {0xAABBCC}' }, { 'commandcli': 'zcl global write 6 32772 48 {01}' }, { 'commandcli': 'send 0x12ab 1 1' }]
def test_climate(): device = XDevice(ZIGBEE, "lumi.airrtc.tcpecn02", ZDID, ZMAC, ZNWK) assert device.info.name == 'Aqara Thermostat S2 CN' device.setup_converters() p = device.decode_lumi([ {"res_name": "14.2.85", "value": 268435455}, {"res_name": "14.8.85", "value": 15}, {"res_name": "14.9.85", "value": 255}, {"res_name": "14.10.85", "value": 15}, {"res_name": "3.2.85", "value": 63}, {"res_name": "3.1.85", "value": 0} ]) assert p == { 'climate': 268435455, 'hvac_mode': 'off', 'target_temp': 0, 'fan_mode': None, 'current_temp': 63 } params = [ {"res_name": "14.2.85", "value": 288366197}, {"res_name": "14.8.85", "value": 1}, {"res_name": "14.9.85", "value": 30}, {"res_name": "14.10.85", "value": 3}, {"res_name": "3.2.85", "value": 29}, {"res_name": "3.1.85", "value": 1} ] p = device.decode_lumi(params) assert p == { 'climate': 288366197, 'hvac_mode': 'cool', 'target_temp': 30, 'fan_mode': 'auto', 'current_temp': 29 } x = params[0]["value"] p = device.encode({"climate": {"climate": x, "fan_mode": "low"}}) y = p["params"][0]["value"] assert x != y p = device.encode({"climate": {"climate": y, "fan_mode": "auto"}}) y = p["params"][0]["value"] assert x == y
def test_(): device = XDevice(ZIGBEE, "MS01", ZDID, ZMAC, ZNWK) assert device.info.name == "Sonoff Motion Sensor" device.setup_converters() p = silabs.decode({ "clusterId": "0x0001", "sourceEndpoint": "0x01", "APSPlayload": "0x18AC0A2000201E" }) p = device.decode_zigbee(p) assert p == {'battery_voltage': 3000} p = silabs.decode({ "clusterId": "0x0001", "sourceEndpoint": "0x01", "APSPlayload": "0x18AD0A210020C8" }) p = device.decode_zigbee(p) assert p == {'battery': 100} p = silabs.decode({ "clusterId": "0x0500", "sourceEndpoint": "0x01", "APSPlayload": "0x190300000000000000", }) p = device.decode_zigbee(p) assert p == {'occupancy': False} p = silabs.decode({ "clusterId": "0x0500", "sourceEndpoint": "0x01", "APSPlayload": "0x190400010000000000" }) p = device.decode_zigbee(p) assert p == {'occupancy': True}