mirror of https://github.com/arendst/Tasmota.git
Zigbee Tuya wildcard support
This commit is contained in:
parent
e1f5390c32
commit
c83abd12c8
|
@ -1472,15 +1472,20 @@ void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attrib
|
||||||
uint16_t cluster = attr.cluster;
|
uint16_t cluster = attr.cluster;
|
||||||
uint16_t attribute = attr.attr_id;
|
uint16_t attribute = attr.attr_id;
|
||||||
uint32_t ccccaaaa = (attr.cluster << 16) | attr.attr_id;
|
uint32_t ccccaaaa = (attr.cluster << 16) | attr.attr_id;
|
||||||
|
|
||||||
// Look for an entry in the converter table
|
// Look for an entry in the converter table
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
// first search in device plug-ins
|
// 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();
|
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)) {
|
if (found && (matched_attr.map_type != Z_Data_Type::Z_Unknown)) {
|
||||||
// We apply an automatic mapping to Z_Data_XXX object
|
// We apply an automatic mapping to Z_Data_XXX object
|
||||||
// First we find or instantiate the correct Z_Data_XXX according to the endpoint
|
// First we find or instantiate the correct Z_Data_XXX according to the endpoint
|
||||||
|
|
|
@ -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
|
// 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) {
|
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;
|
const char * command_name = nullptr;
|
||||||
uint8_t conv_direction;
|
uint8_t conv_direction;
|
||||||
Z_XYZ_Var xyz;
|
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));
|
//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++) {
|
for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) {
|
||||||
const Z_CommandConverter *conv = &Z_Commands[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
|
// TODO Berry encode command
|
||||||
|
|
||||||
if (command_name) {
|
if (command_name) {
|
||||||
|
@ -570,22 +580,21 @@ void parseSingleTuyaAttribute(Z_attribute & attr, const SBuffer &buf,
|
||||||
|
|
||||||
//
|
//
|
||||||
// Tuya - MOES specifc cluster 0xEF00
|
// Tuya - MOES specifc cluster 0xEF00
|
||||||
// See https://medium.com/@dzegarra/zigbee2mqtt-how-to-add-support-for-a-new-tuya-based-device-part-2-5492707e882d
|
// https://developer.tuya.com/en/docs/iot-device-dev/tuya-zigbee-universal-docking-access-standard?id=K9ik6zvofpzql#subtitle-6-Private%20cluster
|
||||||
// and https://github.com/Koenkk/zigbee-herdsman-converters/blob/9f503d47d3df6a99d133b78d2b52aa5c701ddddf/converters/fromZigbee.js#L339
|
|
||||||
//
|
//
|
||||||
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) {
|
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);
|
// uint16_t seq_number = buf.get16BigEndian(0)
|
||||||
// uint8_t transid = buf.get8(1);
|
uint8_t dpid = buf.get8(2); // dpid from Tuya documentation
|
||||||
uint8_t dp = buf.get8(2); // dpid from Tuya documentation
|
|
||||||
uint8_t attr_type = buf.get8(3); // data type from Tuya documentation
|
uint8_t attr_type = buf.get8(3); // data type from Tuya documentation
|
||||||
uint16_t len = buf.get16BigEndian(4);
|
uint16_t len = buf.get16BigEndian(4);
|
||||||
|
|
||||||
if ((1 == cmd) || (2 == cmd)) { // attribute report or attribute response
|
if ((1 == cmd) || (2 == cmd)) { // attribute report or attribute response
|
||||||
// create a synthetic attribute with id 'dp'
|
// create a synthetic attribute with id 'dpid'
|
||||||
Z_attribute & attr = attr_list.addAttribute(cluster, (attr_type << 8) | dp);
|
Z_attribute & attr = attr_list.addAttribute(cluster, (attr_type << 8) | dpid);
|
||||||
parseSingleTuyaAttribute(attr, buf, 6, len, attr_type);
|
parseSingleTuyaAttribute(attr, buf, 6, len, attr_type);
|
||||||
return true; // true = remove the original Tuya attribute
|
return true; // true = remove the original Tuya attribute
|
||||||
}
|
}
|
||||||
|
// TODO Cmd 0x24 to sync clock with coordinator time
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue