diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index 2fd3f8053..1d2d2ca52 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -247,6 +247,32 @@ public: uint16_t x, y; // last color [x,y] | 0xFFFF not set, default 0 }; +/*********************************************************************************************\ + * Device specific: PIR +\*********************************************************************************************/ +class Z_Data_PIR : public Z_Data { +public: + Z_Data_PIR(uint8_t endpoint = 0) : + Z_Data(Z_Data_Type::Z_PIR, endpoint), + occupancy(0xFF), + illuminance(0xFFFF) + {} + + inline bool validOccupancy(void) const { return 0xFF != occupancy; } + inline bool validIlluminance(void) const { return 0xFFFF != illuminance; } + + inline uint8_t getOccupancy(void) const { return occupancy; } + inline uint16_t getIlluminance(void) const { return illuminance; } + + inline void setOccupancy(uint8_t _occupancy) { occupancy = _occupancy; } + inline void setilluminance(uint16_t _illuminance) { illuminance = _illuminance; } + + static const Z_Data_Type type = Z_Data_Type::Z_PIR; + // PIR + uint8_t occupancy; // map8 + uint16_t illuminance; // illuminance +}; + /*********************************************************************************************\ * Device specific: Sensors: temp, humidity, pressure... \*********************************************************************************************/ @@ -363,6 +389,8 @@ Z_Data & Z_Data_Set::getByType(Z_Data_Type type, uint8_t ep) { return get(ep); case Z_Data_Type::Z_OnOff: return get(ep); + case Z_Data_Type::Z_PIR: + return get(ep); default: return *(Z_Data*)nullptr; } diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 845d554df..f7a25af7e 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -504,7 +504,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Zuint8, Cx0300, 0x003C, Z_(ColorPointBIntensity), Cm1, 0 }, // Illuminance Measurement cluster - { Zuint16, Cx0400, 0x0000, Z_(Illuminance), Cm1, 0 }, // Illuminance (in Lux) + { Zuint16, Cx0400, 0x0000, Z_(Illuminance), Cm1 + Z_EXPORT_DATA, Z_MAPPING(Z_Data_PIR, illuminance) }, // Illuminance (in Lux) { Zuint16, Cx0400, 0x0001, Z_(IlluminanceMinMeasuredValue), Cm1, 0 }, // { Zuint16, Cx0400, 0x0002, Z_(IlluminanceMaxMeasuredValue), Cm1, 0 }, // { Zuint16, Cx0400, 0x0003, Z_(IlluminanceTolerance), Cm1, 0 }, // @@ -552,7 +552,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Zunk, Cx0405, 0xFFFF, Z_(), Cm0, 0 }, // Remove all other values // Occupancy Sensing cluster - { Zmap8, Cx0406, 0x0000, Z_(Occupancy), Cm1, 0 }, // Occupancy (map8) + { Zmap8, Cx0406, 0x0000, Z_(Occupancy), Cm1 + Z_EXPORT_DATA, Z_MAPPING(Z_Data_PIR, occupancy) }, // Occupancy (map8) { Zenum8, Cx0406, 0x0001, Z_(OccupancySensorType), Cm1, 0 }, // OccupancySensorType { Zunk, Cx0406, 0xFFFF, Z_(), Cm0, 0 }, // Remove all other values @@ -749,7 +749,6 @@ public: void parseResponse(void); void parseResponseOld(void); void parseClusterSpecificCommand(Z_attribute_list& attr_list); - void postProcessAttributes(uint16_t shortaddr, Z_attribute_list& attr_list); // synthetic attributes converters void syntheticAqaraSensor(Z_attribute_list &attr_list, class Z_attribute &attr); @@ -1755,14 +1754,13 @@ void ZCLFrame::syntheticAqaraVibration(class Z_attribute_list &attr_list, class /// Publish a message for `"Occupancy":0` when the timer expired void Z_OccupancyCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { Z_attribute_list attr_list; - attr_list.addAttribute(F(OCCUPANCY)).setUInt(0); + attr_list.addAttribute(0x0406, 0x0000).setUInt(0); // Occupancy + Z_postProcessAttributes(shortaddr, endpoint, attr_list); // make sure all is updated accordingly zigbee_devices.jsonPublishNow(shortaddr, attr_list); } // ====================================================================== -void ZCLFrame::postProcessAttributes(uint16_t shortaddr, Z_attribute_list& attr_list) { - // source endpoint - uint8_t src_ep = _srcendpoint; +void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attribute_list& attr_list) { uint8_t count_ep = zigbee_devices.countEndpoints(shortaddr); Z_Device & device = zigbee_devices.getShortAddr(shortaddr); @@ -1822,8 +1820,10 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, Z_attribute_list& attr_ // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "Mapping type=%d offset=%d zigbee_type=%02X value=%d\n"), (uint8_t) map_type, map_offset, zigbee_type, ival32); switch (zigbee_type) { case Zenum8: + case Zmap8: case Zuint8: *(uint8_t*)attr_address = uval32; break; case Zenum16: + case Zmap16: case Zuint16: *(uint16_t*)attr_address = uval32; break; case Zuint32: *(uint32_t*)attr_address = uval32; break; case Zint8: *(int8_t*)attr_address = ival32; break; @@ -1963,7 +1963,9 @@ void Z_Data::toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const uint32_t uval32; switch (zigbee_type) { case Zenum8: + case Zmap8: case Zuint8: uval32 = *(uint8_t*)attr_address; if (uval32 != 0xFF) data_size = 8; break; + case Zmap16: case Zenum16: case Zuint16: uval32 = *(uint16_t*)attr_address; if (uval32 != 0xFFFF) data_size = 16; break; case Zuint32: uval32 = *(uint32_t*)attr_address; if (uval32 != 0xFFFFFFFF) data_size = 32; break; diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 3baad68c8..07cd1dc39 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -1515,7 +1515,7 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) { zcl_received.generateSyntheticAttributes(attr_list); zcl_received.computeSyntheticAttributes(attr_list); zcl_received.generateCallBacks(attr_list); // set deferred callbacks, ex: Occupancy - zcl_received.postProcessAttributes(srcaddr, attr_list); + Z_postProcessAttributes(srcaddr, zcl_received.getSrcEndpoint(), attr_list); // since we just receveived data from the device, it is reachable zigbee_devices.resetTimersForDevice(srcaddr, 0 /* groupaddr */, Z_CAT_REACHABILITY); // remove any reachability timer already there diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index c455e187e..f37e67645 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -1494,6 +1494,9 @@ void CmndZbData(void) { case Z_Data_Type::Z_Alarm: ((Z_Data_Alarm&)data_elt).toAttributes(inner_attr, data_type); break; + case Z_Data_Type::Z_PIR: + ((Z_Data_PIR&)data_elt).toAttributes(inner_attr, data_type); + break; } if ((key[0] != '\0') && (key[0] != '?')) { attr_data.addAttribute(key).setStrRaw(inner_attr.toString(true).c_str());