async def test_mija_battery(zigpy_device_from_quirk, voltage, bpr): """Test xiaomi batter voltage to % battery left.""" data_1 = b"\x1c4\x12\x02\n\x02\xffL\x06\x00\x10\x01!" data_2 = b"!\xa8\x01$\x00\x00\x00\x00\x00!n\x00 P" device = zigpy_device_from_quirk(zhaquirks.xiaomi.mija.motion.Motion) device.handle_message(0x260, 0x0000, 1, 1, data_1 + t.uint16_t(voltage).serialize() + data_2) power_cluster = device.endpoints[1].power assert power_cluster["battery_percentage_remaining"] == bpr
async def test_xiaomi_battery(zigpy_device_from_quirk, voltage, bpr): """Test xiaomi batter voltage to % battery left.""" data_1 = b'\x1c_\x11I\n\x01\xffB"\x01!' data_2 = ( b"\x03(\r\x04!\xa8\x13\x05!\xcb\x00\x06$\x01\x00\x00\x00\x00\x08!\x04\x02\n!" b"\x00\x00d\x10\x00") device = zigpy_device_from_quirk( zhaquirks.xiaomi.aqara.vibration_aq1.VibrationAQ1) device.handle_message(0x260, 0x0000, 1, 1, data_1 + t.uint16_t(voltage).serialize() + data_2) power_cluster = device.endpoints[1].power assert power_cluster["battery_percentage_remaining"] == bpr
def handle_message(self, is_reply, sender, profile, cluster, src_ep, dst_ep, tsn, command_id, args): try: device = self.get_device(nwk=sender) except KeyError: LOGGER.warning("Message on unknown device 0x%04x", sender) return return device.handle_message(is_reply, profile, cluster, src_ep, dst_ep, tsn, command_id, args)
def handle_zcl(self, dataPayload: ZclDataPayload): # LOGGER.debug("Received ZCL data %s", dataPayload) # if (dataPayload.frame && dataPayload.frame.Cluster.name === 'touchlink') { # // This is handled by touchlink # return # } nwk = dataPayload.address try: device: zigpy.device.Device = self.get_device(nwk=nwk) except KeyError: LOGGER.debug("Received ZCL frame from unknown device: %s", nwk) return # device.updateLastSeen() # endpoint: zigpy.endpoint.Endpoint # try: endpoint = device.endpoints[dataPayload.endpoint] except KeyError: LOGGER.debug("ZCL data is from unknown endpoint %d from device %s, creating it...", dataPayload.endpoint, nwk) endpoint = device.add_endpoint(dataPayload.endpoint) # cluster = Cluster.from_id(endpoint, dataPayload.clusterid) # hdr, data = cluster.deserialize(dataPayload.data) # LOGGER.info("ZLC: %s %s", hdr.command_id, data) # LOGGER.debug("ZLC: %s", hdr) profile = 0 device.handle_message( profile, dataPayload.clusterid, dataPayload.endpoint, dataPayload.dstendpoint, dataPayload.data, ) # endpoint.handle_message(profile, dataPayload.clusterid, hdr, data) # if hdr.frame_control.is_general(): # if hdr.command_id == Command.Report_Attributes: # pass # else: # pass # # if hdr.command_id == Command.Read_Attributes_rsp or hdr.command_id == Command.Report_Attributes: # # Some device report, e.g. it's modelID through a readResponse or attributeReport # for key, value in data.items(): # property = cluster.discover_attributes.ReportablePropertiesMapping[key] # if property && !device[property.key]: # property.set(value, device) # # endpoint.saveClusterAttributeKeyValue(clusterName, data) ''' // Parse command for event let type: Events.MessagePayloadType = undefined let data: KeyValue let clusterName = undefined const meta: {zclTransactionSequenceNumber?: number} = {} const frame = dataPayload.frame const command = frame.getCommand() clusterName = frame.Cluster.name meta.zclTransactionSequenceNumber = frame.Header.transactionSequenceNumber if (frame.isGlobal()) { if (frame.isCommand('report')) { type = 'attributeReport' data = ZclFrameConverter.attributeKeyValue(dataPayload.frame) } else if (frame.isCommand('read')) { type = 'read' data = ZclFrameConverter.attributeList(dataPayload.frame) } else if (frame.isCommand('write')) { type = 'write' data = ZclFrameConverter.attributeKeyValue(dataPayload.frame) } else { /* istanbul ignore else */ if (frame.isCommand('readRsp')) { type = 'readResponse' data = ZclFrameConverter.attributeKeyValue(dataPayload.frame) } } } else { /* istanbul ignore else */ if (frame.isSpecific()) { if (Events.CommandsLookup[command.name]) { type = Events.CommandsLookup[command.name] data = dataPayload.frame.Payload } else { debug.log("Skipping command '${command.name}' because it is missing from the lookup") } } } if (type === 'readResponse' || type === 'attributeReport') { // Some device report, e.g. it's modelID through a readResponse or attributeReport for (const [key, value] of Object.entries(data)) { const property = Device.ReportablePropertiesMapping[key] if (property && !device[property.key]) { property.set(value, device) } } endpoint.saveClusterAttributeKeyValue(clusterName, data) } if (type && data) { const endpoint = device.getEndpoint(dataPayload.endpoint) const linkquality = dataPayload.linkquality const groupID = dataPayload.groupID const eventData: Events.MessagePayload = { type: type, device, endpoint, data, linkquality, groupID, cluster: clusterName, meta } this.emit(Events.Events.message, eventData) } const frame = dataPayload.frame // Send a default response if necessary. if (!frame.Header.frameControl.disableDefaultResponse) { try { await endpoint.defaultResponse( frame.getCommand().ID, 0, frame.Cluster.ID, frame.Header.transactionSequenceNumber, ) } catch (error) { debug.error("Default response to ${device.ieeeAddr} failed") } } // Reponse to time reads if (frame.isGlobal() && frame.isCluster('genTime') && frame.isCommand('read')) { const time = Math.round(((new Date()).getTime() - OneJanuary2000) / 1000) try { await endpoint.readResponse(frame.Cluster.ID, frame.Header.transactionSequenceNumber, {time}) } catch (error) { debug.error("genTime response to ${device.ieeeAddr} failed") } } ''' pass