Merge pull request #9785 from s-hadinger/zigbee_alarm_config

Zigbee alarm config
This commit is contained in:
s-hadinger 2020-11-08 18:32:17 +01:00 committed by GitHub
commit adb9ca7ab6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 2 deletions

View File

@ -74,6 +74,10 @@ public:
void toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const;
// update internal structures after an attribut update
// True if a configuration was changed
inline bool update(void) { return false; }
static const Z_Data_Type type = Z_Data_Type::Z_Unknown;
static bool ConfigToZData(const char * config_str, Z_Data_Type * type, uint8_t * ep, uint8_t * config);
@ -352,6 +356,30 @@ public:
/*********************************************************************************************\
* Device specific: Alarm
\*********************************************************************************************/
// We're lucky that alarm type fits in 12 bits, so we can have a total entry of 16 bits
typedef union Z_Alarm_Types_t {
struct {
uint16_t zcl_type : 12;
uint8_t config : 4;
} t;
uint16_t i;
} Z_Alarm_Types_t;
static const Z_Alarm_Types_t Z_Alarm_Types[] PROGMEM = {
{ .t = { 0x000, 0x0 }}, // 0x0 : Standard CIE
{ .t = { 0x00d, 0x1 }}, // 0x1 : PIR
{ .t = { 0x015, 0x2 }}, // 0x2 : Contact
{ .t = { 0x028, 0x3 }}, // 0x3 : Fire
{ .t = { 0x02a, 0x4 }}, // 0x4 : Leak
{ .t = { 0x02b, 0x5 }}, // 0x5 : CO
{ .t = { 0x02c, 0x6 }}, // 0x6 : Personal
{ .t = { 0x02d, 0x7 }}, // 0x7 : Movement
{ .t = { 0x10f, 0x8 }}, // 0x8 : Panic
{ .t = { 0x115, 0x8 }}, // 0x8 : Panic
{ .t = { 0x21d, 0x8 }}, // 0x8 : Panic
{ .t = { 0x226, 0x9 }}, // 0x9 : Glass break
};
class Z_Data_Alarm : public Z_Data {
public:
Z_Data_Alarm(uint8_t endpoint = 0) :
@ -364,11 +392,26 @@ public:
inline bool validZoneType(void) const { return 0xFFFF != zone_type; }
inline uint16_t getZoneType(void) const { return zone_type; }
inline bool isPIR(void) const { return 0x000d == zone_type; }
inline bool isContact(void) const { return 0x0015 == zone_type; }
inline bool isPIR(void) const { return 0x1 == _config; }
inline bool isContact(void) const { return 0x2 == _config; }
inline void setZoneType(uint16_t _zone_type) { zone_type = _zone_type; }
bool update(void) {
for (uint32_t i=0; i<ARRAY_SIZE(Z_Alarm_Types); i++) {
Z_Alarm_Types_t conv_type;
conv_type.i = pgm_read_word(&Z_Alarm_Types[i].i);
if (zone_type == conv_type.t.zcl_type) {
if (_config == conv_type.t.config) {
return false; // no change
} else {
_config = conv_type.t.config;
return true;
}
}
}
}
// 4 bytes
uint16_t zone_status; // last known state for sensor 1 & 2
uint16_t zone_type; // mapped to the Zigbee standard
@ -401,6 +444,8 @@ public:
// getX() always returns a valid object, and creates the object if there is none
// find() does not create an object if it does not exist, and returns *(X*)nullptr
// Emulate a virtuel update method for Z_Data
static bool updateData(Z_Data & elt);
template <class M>
M & get(uint8_t ep = 0);
@ -413,6 +458,18 @@ public:
M & addIfNull(M & cur, uint8_t ep = 0);
};
bool Z_Data_Set::updateData(Z_Data & elt) {
switch (elt._type) {
case Z_Data_Type::Z_Light: return ((Z_Data_Light&) elt).update(); break;
case Z_Data_Type::Z_Plug: return ((Z_Data_Plug&) elt).update(); break;
case Z_Data_Type::Z_Alarm: return ((Z_Data_Alarm&) elt).update(); break;
case Z_Data_Type::Z_Thermo: return ((Z_Data_Thermo&) elt).update(); break;
case Z_Data_Type::Z_OnOff: return ((Z_Data_OnOff&) elt).update(); break;
case Z_Data_Type::Z_PIR: return ((Z_Data_PIR&) elt).update(); break;
default: return false;
}
}
Z_Data & Z_Data_Set::getByType(Z_Data_Type type, uint8_t ep) {
switch (type) {
case Z_Data_Type::Z_Light:

View File

@ -276,6 +276,7 @@ void hydrateSingleDevice(const SBuffer & buf_d, uint32_t version) {
Z_Data & z_data = device.data.getByType(type, ep);
if (&z_data != nullptr) {
z_data.setConfig(config);
Z_Data_Set::updateData(z_data);
}
}
}

View File

@ -1851,6 +1851,9 @@ void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attrib
case Zint16: *(int16_t*)attr_address = ival32; break;
case Zint32: *(int32_t*)attr_address = ival32; break;
}
if (Z_Data_Set::updateData(data)) {
zigbee_devices.dirty();
}
}
uint16_t uval16 = attr.getUInt(); // call converter to uint only once