Merge pull request #16614 from s-hadinger/zigbee_tuya_wildcard

Zigbee Tuya wildcard support
This commit is contained in:
s-hadinger 2022-09-21 23:15:28 +02:00 committed by GitHub
commit f70822b54d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 19 deletions

View File

@ -1472,15 +1472,20 @@ void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attrib
uint16_t cluster = attr.cluster;
uint16_t attribute = attr.attr_id;
uint32_t ccccaaaa = (attr.cluster << 16) | attr.attr_id;
// Look for an entry in the converter table
bool found = false;
// first search in device plug-ins
const Z_attribute_match matched_attr = Z_findAttributeMatcherById(shortaddr, cluster, attribute, true);
Z_attribute_match matched_attr = Z_findAttributeMatcherById(shortaddr, cluster, attribute, true);
found = matched_attr.found();
// special case for Tuya attributes, also search for type `FF` if not found
if (!found && cluster == 0xEF00) {
// search for attribute `FFxx` for wildcard types
matched_attr = Z_findAttributeMatcherById(shortaddr, cluster, 0xFF00 | (attribute & 0x00FF), true);
found = matched_attr.found();
}
float fval = attr.getFloat();
float fval = attr.getFloat();
if (found && (matched_attr.map_type != Z_Data_Type::Z_Unknown)) {
// We apply an automatic mapping to Z_Data_XXX object
// First we find or instantiate the correct Z_Data_XXX according to the endpoint

View File

@ -338,11 +338,30 @@ void parseXYZ(const char *model, const SBuffer &payload, struct Z_XYZ_Var *xyz)
}
// Parse a cluster specific command, and try to convert into human readable
// Includes specific handling for Tuya attributes
void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster, uint8_t cmd, bool direction, uint16_t shortaddr, uint8_t srcendpoint, const SBuffer &payload) {
const char * command_name = nullptr;
uint8_t conv_direction;
Z_XYZ_Var xyz;
// always report attribute in raw format
// Format: "0001!06": "00" = "<cluster>!<cmd>": "<payload>" for commands to devices
// Format: "0004<00": "00" = "<cluster><<cmd>": "<payload>" for commands to devices
// char attrid_str[12];
// snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '?' : '!', cmd);
// Z_attribute & attr_raw = attr_list.addAttribute(attrid_str);
Z_attribute & attr_raw = attr_list.addAttributeCmd(cluster, cmd, direction, false /* cluster specific */);
attr_raw.setBuf(payload, 0, payload.len());
// Take a shotcut in case of Tuya attribute which follow a different scheme
if (cluster == 0xEF00) {
// Tuya Cmd
if (convertTuyaSpecificCluster(attr_list, cluster, cmd, direction, shortaddr, srcendpoint, payload)) {
attr_list.removeAttribute(&attr_raw); // remove raw command
}
return; // abort, normal processing doesn't apply here
}
//AddLog(LOG_LEVEL_INFO, PSTR(">>> len = %d - %02X%02X%02X"), payload.len(), payload.get8(0), payload.get8(1), payload.get8(2));
for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) {
const Z_CommandConverter *conv = &Z_Commands[i];
@ -396,15 +415,6 @@ void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster,
}
}
// always report attribute in raw format
// Format: "0001!06": "00" = "<cluster>!<cmd>": "<payload>" for commands to devices
// Format: "0004<00": "00" = "<cluster><<cmd>": "<payload>" for commands to devices
// char attrid_str[12];
// snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '?' : '!', cmd);
// Z_attribute & attr_raw = attr_list.addAttribute(attrid_str);
Z_attribute & attr_raw = attr_list.addAttributeCmd(cluster, cmd, direction, false /* cluster specific */);
attr_raw.setBuf(payload, 0, payload.len());
// TODO Berry encode command
if (command_name) {
@ -570,22 +580,21 @@ void parseSingleTuyaAttribute(Z_attribute & attr, const SBuffer &buf,
//
// Tuya - MOES specifc cluster 0xEF00
// See https://medium.com/@dzegarra/zigbee2mqtt-how-to-add-support-for-a-new-tuya-based-device-part-2-5492707e882d
// and https://github.com/Koenkk/zigbee-herdsman-converters/blob/9f503d47d3df6a99d133b78d2b52aa5c701ddddf/converters/fromZigbee.js#L339
// https://developer.tuya.com/en/docs/iot-device-dev/tuya-zigbee-universal-docking-access-standard?id=K9ik6zvofpzql#subtitle-6-Private%20cluster
//
bool convertTuyaSpecificCluster(class Z_attribute_list &attr_list, uint16_t cluster, uint8_t cmd, bool direction, uint16_t shortaddr, uint8_t srcendpoint, const SBuffer &buf) {
// uint8_t status = buf.get8(0);
// uint8_t transid = buf.get8(1);
uint8_t dp = buf.get8(2); // dpid from Tuya documentation
// uint16_t seq_number = buf.get16BigEndian(0)
uint8_t dpid = buf.get8(2); // dpid from Tuya documentation
uint8_t attr_type = buf.get8(3); // data type from Tuya documentation
uint16_t len = buf.get16BigEndian(4);
if ((1 == cmd) || (2 == cmd)) { // attribute report or attribute response
// create a synthetic attribute with id 'dp'
Z_attribute & attr = attr_list.addAttribute(cluster, (attr_type << 8) | dp);
// create a synthetic attribute with id 'dpid'
Z_attribute & attr = attr_list.addAttribute(cluster, (attr_type << 8) | dpid);
parseSingleTuyaAttribute(attr, buf, 6, len, attr_type);
return true; // true = remove the original Tuya attribute
}
// TODO Cmd 0x24 to sync clock with coordinator time
return false;
}