mirror of https://github.com/arendst/Tasmota.git
Merge pull request #7944 from s-hadinger/zigbee_simpl
Change Zigbee simplification of devices probing, saving Flash and memory
This commit is contained in:
commit
35f533994f
|
@ -8,6 +8,7 @@
|
||||||
- Add command ``HumOffset -10.0 .. 10.0`` to set global humidity sensor offset (#7934)
|
- Add command ``HumOffset -10.0 .. 10.0`` to set global humidity sensor offset (#7934)
|
||||||
- Add Zigbee support for Hue emulation by Stefan Hadinger
|
- Add Zigbee support for Hue emulation by Stefan Hadinger
|
||||||
- Add Dew Point to Temperature and Humidity sensors
|
- Add Dew Point to Temperature and Humidity sensors
|
||||||
|
- Change Zigbee simplification of devices probing, saving Flash and memory
|
||||||
|
|
||||||
### 8.1.0.10 20200227
|
### 8.1.0.10 20200227
|
||||||
|
|
||||||
|
|
|
@ -388,9 +388,6 @@ enum ZCL_Global_Commands {
|
||||||
#define ZF(s) static const char ZS_ ## s[] PROGMEM = #s;
|
#define ZF(s) static const char ZS_ ## s[] PROGMEM = #s;
|
||||||
#define Z(s) ZS_ ## s
|
#define Z(s) ZS_ ## s
|
||||||
|
|
||||||
const uint16_t Z_ProfileIds[] PROGMEM = { 0x0104, 0x0109, 0xA10E, 0xC05E };
|
|
||||||
const char Z_ProfileNames[] PROGMEM = "ZigBee Home Automation|ZigBee Smart Energy|ZigBee Green Power|ZigBee Light Link";
|
|
||||||
|
|
||||||
typedef struct Z_StatusLine {
|
typedef struct Z_StatusLine {
|
||||||
uint32_t status; // no need to use uint8_t since it uses 32 bits anyways
|
uint32_t status; // no need to use uint8_t since it uses 32 bits anyways
|
||||||
const char * status_msg;
|
const char * status_msg;
|
||||||
|
|
|
@ -28,14 +28,14 @@ const uint16_t kZigbeeSaveDelaySeconds = ZIGBEE_SAVE_DELAY_SECONDS; // wait f
|
||||||
|
|
||||||
typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value);
|
typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value);
|
||||||
|
|
||||||
|
const size_t endpoints_max = 8; // we limit to 8 endpoints
|
||||||
|
|
||||||
typedef struct Z_Device {
|
typedef struct Z_Device {
|
||||||
uint64_t longaddr; // 0x00 means unspecified
|
uint64_t longaddr; // 0x00 means unspecified
|
||||||
char * manufacturerId;
|
char * manufacturerId;
|
||||||
char * modelId;
|
char * modelId;
|
||||||
char * friendlyName;
|
char * friendlyName;
|
||||||
std::vector<uint32_t> endpoints; // encoded as high 16 bits is endpoint, low 16 bits is ProfileId
|
uint8_t endpoints[endpoints_max]; // static array to limit memory consumption, list of endpoints until 0x00 or end of array
|
||||||
std::vector<uint32_t> clusters_in; // encoded as high 16 bits is endpoint, low 16 bits is cluster number
|
|
||||||
std::vector<uint32_t> clusters_out; // encoded as high 16 bits is endpoint, low 16 bits is cluster number
|
|
||||||
// json buffer used for attribute reporting
|
// json buffer used for attribute reporting
|
||||||
DynamicJsonBuffer *json_buffer;
|
DynamicJsonBuffer *json_buffer;
|
||||||
JsonObject *json;
|
JsonObject *json;
|
||||||
|
@ -81,7 +81,6 @@ typedef struct Z_Deferred {
|
||||||
// - shortaddr is unique if not null
|
// - shortaddr is unique if not null
|
||||||
// - longaddr is unique if not null
|
// - longaddr is unique if not null
|
||||||
// - shortaddr and longaddr cannot be both null
|
// - shortaddr and longaddr cannot be both null
|
||||||
// - clusters_in and clusters_out containt only endpoints listed in endpoints
|
|
||||||
class Z_Devices {
|
class Z_Devices {
|
||||||
public:
|
public:
|
||||||
Z_Devices() {};
|
Z_Devices() {};
|
||||||
|
@ -98,20 +97,17 @@ public:
|
||||||
|
|
||||||
uint64_t getDeviceLongAddr(uint16_t shortaddr) const;
|
uint64_t getDeviceLongAddr(uint16_t shortaddr) const;
|
||||||
|
|
||||||
|
uint8_t findFirstEndpoint(uint16_t shortaddr) const;
|
||||||
|
|
||||||
// Add new device, provide ShortAddr and optional longAddr
|
// Add new device, provide ShortAddr and optional longAddr
|
||||||
// If it is already registered, update information, otherwise create the entry
|
// If it is already registered, update information, otherwise create the entry
|
||||||
void updateDevice(uint16_t shortaddr, uint64_t longaddr = 0);
|
void updateDevice(uint16_t shortaddr, uint64_t longaddr = 0);
|
||||||
|
|
||||||
// Add an endpoint to a device
|
// Add an endpoint to a device
|
||||||
void addEndoint(uint16_t shortaddr, uint8_t endpoint);
|
void addEndpoint(uint16_t shortaddr, uint8_t endpoint);
|
||||||
|
|
||||||
// Add endpoint profile
|
|
||||||
void addEndointProfile(uint16_t shortaddr, uint8_t endpoint, uint16_t profileId);
|
|
||||||
|
|
||||||
// Add cluster
|
// Add cluster
|
||||||
void addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster, bool out);
|
void addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster);
|
||||||
|
|
||||||
uint8_t findClusterEndpointIn(uint16_t shortaddr, uint16_t cluster);
|
|
||||||
|
|
||||||
void setManufId(uint16_t shortaddr, const char * str);
|
void setManufId(uint16_t shortaddr, const char * str);
|
||||||
void setModelId(uint16_t shortaddr, const char * str);
|
void setModelId(uint16_t shortaddr, const char * str);
|
||||||
|
@ -175,8 +171,6 @@ public:
|
||||||
private:
|
private:
|
||||||
std::vector<Z_Device*> _devices = {};
|
std::vector<Z_Device*> _devices = {};
|
||||||
std::vector<Z_Deferred> _deferred = {}; // list of deferred calls
|
std::vector<Z_Deferred> _deferred = {}; // list of deferred calls
|
||||||
// std::vector<Z_Device> _devices = std::vector<Z_Device>(4);
|
|
||||||
// std::vector<Z_Deferred> _deferred = std::vector<Z_Deferred>(4); // list of deferred calls
|
|
||||||
uint32_t _saveTimer = 0;
|
uint32_t _saveTimer = 0;
|
||||||
uint8_t _seqNumber = 0; // global seqNumber if device is unknown
|
uint8_t _seqNumber = 0; // global seqNumber if device is unknown
|
||||||
|
|
||||||
|
@ -186,9 +180,6 @@ private:
|
||||||
template < typename T>
|
template < typename T>
|
||||||
static int32_t findEndpointInVector(const std::vector<T> & vecOfElements, uint8_t element);
|
static int32_t findEndpointInVector(const std::vector<T> & vecOfElements, uint8_t element);
|
||||||
|
|
||||||
// find the first endpoint match for a cluster
|
|
||||||
static int32_t findClusterEndpoint(const std::vector<uint32_t> & vecOfElements, uint16_t element);
|
|
||||||
|
|
||||||
Z_Device & getShortAddr(uint16_t shortaddr); // find Device from shortAddr, creates it if does not exist
|
Z_Device & getShortAddr(uint16_t shortaddr); // find Device from shortAddr, creates it if does not exist
|
||||||
const Z_Device & getShortAddrConst(uint16_t shortaddr) const ; // find Device from shortAddr, creates it if does not exist
|
const Z_Device & getShortAddrConst(uint16_t shortaddr) const ; // find Device from shortAddr, creates it if does not exist
|
||||||
Z_Device & getLongAddr(uint64_t longaddr); // find Device from shortAddr, creates it if does not exist
|
Z_Device & getLongAddr(uint64_t longaddr); // find Device from shortAddr, creates it if does not exist
|
||||||
|
@ -226,31 +217,13 @@ int32_t Z_Devices::findEndpointInVector(const std::vector<T> & vecOfElements, u
|
||||||
|
|
||||||
int32_t found = 0;
|
int32_t found = 0;
|
||||||
for (auto &elem : vecOfElements) {
|
for (auto &elem : vecOfElements) {
|
||||||
if ( ((elem >> 16) & 0xFF) == element) { return found; }
|
if (elem == element) { return found; }
|
||||||
found++;
|
found++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Find the first endpoint match for a cluster, whether in or out
|
|
||||||
// Clusters are stored in the format 0x00EECCCC (EE=endpoint, CCCC=cluster number)
|
|
||||||
// In:
|
|
||||||
// _devices.clusters_in or _devices.clusters_out
|
|
||||||
// cluster number looked for
|
|
||||||
// Out:
|
|
||||||
// Index of found Endpoint_Cluster number, or -1 if not found
|
|
||||||
//
|
|
||||||
int32_t Z_Devices::findClusterEndpoint(const std::vector<uint32_t> & vecOfElements, uint16_t cluster) {
|
|
||||||
int32_t found = 0;
|
|
||||||
for (auto &elem : vecOfElements) {
|
|
||||||
if ((elem & 0xFFFF) == cluster) { return found; }
|
|
||||||
found++;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Create a new Z_Device entry in _devices. Only to be called if you are sure that no
|
// Create a new Z_Device entry in _devices. Only to be called if you are sure that no
|
||||||
// entry with same shortaddr or longaddr exists.
|
// entry with same shortaddr or longaddr exists.
|
||||||
|
@ -263,9 +236,7 @@ Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) {
|
||||||
nullptr, // ManufId
|
nullptr, // ManufId
|
||||||
nullptr, // DeviceId
|
nullptr, // DeviceId
|
||||||
nullptr, // FriendlyName
|
nullptr, // FriendlyName
|
||||||
std::vector<uint32_t>(), // at least one endpoint
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }, // endpoints
|
||||||
std::vector<uint32_t>(), // try not to allocate if not needed
|
|
||||||
std::vector<uint32_t>(), // try not to allocate if not needed
|
|
||||||
nullptr, nullptr,
|
nullptr, nullptr,
|
||||||
shortaddr,
|
shortaddr,
|
||||||
0, // seqNumber
|
0, // seqNumber
|
||||||
|
@ -293,13 +264,6 @@ void Z_Devices::freeDeviceEntry(Z_Device *device) {
|
||||||
free(device);
|
free(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Z_Devices::shrinkToFit(uint16_t shortaddr) {
|
|
||||||
Z_Device & device = getShortAddr(shortaddr);
|
|
||||||
device.endpoints.shrink_to_fit();
|
|
||||||
device.clusters_in.shrink_to_fit();
|
|
||||||
device.clusters_out.shrink_to_fit();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Scan all devices to find a corresponding shortaddr
|
// Scan all devices to find a corresponding shortaddr
|
||||||
// Looks info device.shortaddr entry
|
// Looks info device.shortaddr entry
|
||||||
|
@ -489,67 +453,31 @@ void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) {
|
||||||
//
|
//
|
||||||
// Add an endpoint to a shortaddr
|
// Add an endpoint to a shortaddr
|
||||||
//
|
//
|
||||||
void Z_Devices::addEndoint(uint16_t shortaddr, uint8_t endpoint) {
|
void Z_Devices::addEndpoint(uint16_t shortaddr, uint8_t endpoint) {
|
||||||
if (!shortaddr) { return; }
|
if (!shortaddr) { return; }
|
||||||
if (0x00 == endpoint) { return; }
|
if (0x00 == endpoint) { return; }
|
||||||
uint32_t ep_profile = (endpoint << 16);
|
|
||||||
Z_Device &device = getShortAddr(shortaddr);
|
Z_Device &device = getShortAddr(shortaddr);
|
||||||
if (&device == nullptr) { return; } // don't crash if not found
|
if (&device == nullptr) { return; } // don't crash if not found
|
||||||
if (findEndpointInVector(device.endpoints, endpoint) < 0) {
|
|
||||||
device.endpoints.push_back(ep_profile);
|
|
||||||
dirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Z_Devices::addEndointProfile(uint16_t shortaddr, uint8_t endpoint, uint16_t profileId) {
|
for (uint32_t i = 0; i < endpoints_max; i++) {
|
||||||
if (!shortaddr) { return; }
|
if (endpoint == device.endpoints[i]) {
|
||||||
if (0x00 == endpoint) { return; }
|
return; // endpoint already there
|
||||||
uint32_t ep_profile = (endpoint << 16) | profileId;
|
}
|
||||||
Z_Device &device = getShortAddr(shortaddr);
|
if (0 == device.endpoints[i]) {
|
||||||
if (&device == nullptr) { return; } // don't crash if not found
|
device.endpoints[i] = endpoint;
|
||||||
int32_t found = findEndpointInVector(device.endpoints, endpoint);
|
|
||||||
if (found < 0) {
|
|
||||||
device.endpoints.push_back(ep_profile);
|
|
||||||
dirty();
|
|
||||||
} else {
|
|
||||||
if (device.endpoints[found] != ep_profile) {
|
|
||||||
device.endpoints[found] = ep_profile;
|
|
||||||
dirty();
|
dirty();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Z_Devices::addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster, bool out) {
|
// Find the first endpoint of the device
|
||||||
if (!shortaddr) { return; }
|
uint8_t Z_Devices::findFirstEndpoint(uint16_t shortaddr) const {
|
||||||
Z_Device & device = getShortAddr(shortaddr);
|
int32_t found = findShortAddr(shortaddr);
|
||||||
if (&device == nullptr) { return; } // don't crash if not found
|
if (found < 0) return 0; // avoid creating an entry if the device was never seen
|
||||||
uint32_t ep_cluster = (endpoint << 16) | cluster;
|
const Z_Device &device = devicesAt(found);
|
||||||
if (!out) {
|
|
||||||
if (!findInVector(device.clusters_in, ep_cluster)) {
|
|
||||||
device.clusters_in.push_back(ep_cluster);
|
|
||||||
dirty();
|
|
||||||
}
|
|
||||||
} else { // out
|
|
||||||
if (!findInVector(device.clusters_out, ep_cluster)) {
|
|
||||||
device.clusters_out.push_back(ep_cluster);
|
|
||||||
dirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for the best endpoint match to send a command for a specific Cluster ID
|
return device.endpoints[0]; // returns 0x00 if no endpoint
|
||||||
// return 0x00 if none found
|
|
||||||
uint8_t Z_Devices::findClusterEndpointIn(uint16_t shortaddr, uint16_t cluster){
|
|
||||||
int32_t short_found = findShortAddr(shortaddr);
|
|
||||||
if (short_found < 0) return 0; // avoid creating an entry if the device was never seen
|
|
||||||
Z_Device &device = getShortAddr(shortaddr);
|
|
||||||
if (&device == nullptr) { return 0; } // don't crash if not found
|
|
||||||
int32_t found = findClusterEndpoint(device.clusters_in, cluster);
|
|
||||||
if (found >= 0) {
|
|
||||||
return (device.clusters_in[found] >> 16) & 0xFF;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Z_Devices::setManufId(uint16_t shortaddr, const char * str) {
|
void Z_Devices::setManufId(uint16_t shortaddr, const char * str) {
|
||||||
|
@ -1069,58 +997,13 @@ String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const {
|
||||||
if (device.manufacturerId) {
|
if (device.manufacturerId) {
|
||||||
dev[F("Manufacturer")] = device.manufacturerId;
|
dev[F("Manufacturer")] = device.manufacturerId;
|
||||||
}
|
}
|
||||||
}
|
JsonArray& dev_endpoints = dev.createNestedArray(F("Endpoints"));
|
||||||
|
for (uint32_t i = 0; i < endpoints_max; i++) {
|
||||||
// If dump_mode == 2, dump a lot more details
|
uint8_t endpoint = device.endpoints[i];
|
||||||
if (3 <= dump_mode) {
|
if (0x00 == endpoint) { break; }
|
||||||
JsonObject& dev_endpoints = dev.createNestedObject(F("Endpoints"));
|
|
||||||
for (std::vector<uint32_t>::const_iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) {
|
|
||||||
uint32_t ep_profile = *ite;
|
|
||||||
uint8_t endpoint = (ep_profile >> 16) & 0xFF;
|
|
||||||
uint16_t profileId = ep_profile & 0xFFFF;
|
|
||||||
|
|
||||||
snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint);
|
snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint);
|
||||||
JsonObject& ep = dev_endpoints.createNestedObject(hex);
|
dev_endpoints.add(hex);
|
||||||
|
|
||||||
snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), profileId);
|
|
||||||
ep[F("ProfileId")] = hex;
|
|
||||||
|
|
||||||
int32_t found = -1;
|
|
||||||
for (uint32_t i = 0; i < sizeof(Z_ProfileIds) / sizeof(Z_ProfileIds[0]); i++) {
|
|
||||||
if (pgm_read_word(&Z_ProfileIds[i]) == profileId) {
|
|
||||||
found = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found > 0) {
|
|
||||||
GetTextIndexed(hex, sizeof(hex), found, Z_ProfileNames);
|
|
||||||
ep[F("ProfileIdName")] = hex;
|
|
||||||
}
|
|
||||||
|
|
||||||
ep.createNestedArray(F("ClustersIn"));
|
|
||||||
ep.createNestedArray(F("ClustersOut"));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (std::vector<uint32_t>::const_iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) {
|
|
||||||
uint16_t cluster = *itc & 0xFFFF;
|
|
||||||
uint8_t endpoint = (*itc >> 16) & 0xFF;
|
|
||||||
|
|
||||||
snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint);
|
|
||||||
JsonArray &cluster_arr = dev_endpoints[hex][F("ClustersIn")];
|
|
||||||
|
|
||||||
snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster);
|
|
||||||
cluster_arr.add(hex);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (std::vector<uint32_t>::const_iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) {
|
|
||||||
uint16_t cluster = *itc & 0xFFFF;
|
|
||||||
uint8_t endpoint = (*itc >> 16) & 0xFF;
|
|
||||||
|
|
||||||
snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint);
|
|
||||||
JsonArray &cluster_arr = dev_endpoints[hex][F("ClustersOut")];
|
|
||||||
|
|
||||||
snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster);
|
|
||||||
cluster_arr.add(hex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,37 +108,25 @@ class SBuffer hibernateDevice(const struct Z_Device &device) {
|
||||||
buf.add8(0x00); // overall length, will be updated later
|
buf.add8(0x00); // overall length, will be updated later
|
||||||
buf.add16(device.shortaddr);
|
buf.add16(device.shortaddr);
|
||||||
buf.add64(device.longaddr);
|
buf.add64(device.longaddr);
|
||||||
uint32_t endpoints = device.endpoints.size();
|
|
||||||
if (endpoints > 254) { endpoints = 254; }
|
uint32_t endpoints_count = 0;
|
||||||
buf.add8(endpoints);
|
for (endpoints_count = 0; endpoints_count < endpoints_max; endpoints_count++) {
|
||||||
|
if (0x00 == device.endpoints[endpoints_count]) { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.add8(endpoints_count);
|
||||||
// iterate on endpoints
|
// iterate on endpoints
|
||||||
for (std::vector<uint32_t>::const_iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) {
|
for (uint32_t i = 0; i < endpoints_max; i++) {
|
||||||
uint32_t ep_profile = *ite;
|
uint8_t endpoint = device.endpoints[i];
|
||||||
uint8_t endpoint = (ep_profile >> 16) & 0xFF;
|
if (0x00 == endpoint) { break; } // stop
|
||||||
uint16_t profileId = ep_profile & 0xFFFF;
|
|
||||||
|
|
||||||
buf.add8(endpoint);
|
buf.add8(endpoint);
|
||||||
buf.add16(profileId);
|
buf.add16(0x0000); // profile_id, not used anymore
|
||||||
for (std::vector<uint32_t>::const_iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) {
|
|
||||||
uint16_t cluster = *itc & 0xFFFF;
|
|
||||||
uint8_t c_endpoint = (*itc >> 16) & 0xFF;
|
|
||||||
|
|
||||||
if (endpoint == c_endpoint) {
|
// removed clusters_in
|
||||||
uint8_t clusterCode = toClusterCode(cluster);
|
|
||||||
if (0xFF != clusterCode) { buf.add8(clusterCode); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf.add8(0xFF); // end of endpoint marker
|
buf.add8(0xFF); // end of endpoint marker
|
||||||
|
|
||||||
for (std::vector<uint32_t>::const_iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) {
|
// no more storage of clusters_out
|
||||||
uint16_t cluster = *itc & 0xFFFF;
|
|
||||||
uint8_t c_endpoint = (*itc >> 16) & 0xFF;
|
|
||||||
|
|
||||||
if (endpoint == c_endpoint) {
|
|
||||||
uint8_t clusterCode = toClusterCode(cluster);
|
|
||||||
if (0xFF != clusterCode) { buf.add8(clusterCode); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf.add8(0xFF); // end of endpoint marker
|
buf.add8(0xFF); // end of endpoint marker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,22 +223,21 @@ void hydrateDevices(const SBuffer &buf) {
|
||||||
for (uint32_t j = 0; j < endpoints; j++) {
|
for (uint32_t j = 0; j < endpoints; j++) {
|
||||||
uint8_t ep = buf_d.get8(d++);
|
uint8_t ep = buf_d.get8(d++);
|
||||||
uint16_t ep_profile = buf_d.get16(d); d += 2;
|
uint16_t ep_profile = buf_d.get16(d); d += 2;
|
||||||
zigbee_devices.addEndointProfile(shortaddr, ep, ep_profile);
|
zigbee_devices.addEndpoint(shortaddr, ep);
|
||||||
|
|
||||||
// in clusters
|
// in clusters
|
||||||
while (d < dev_record_len) { // safe guard against overflow
|
while (d < dev_record_len) { // safe guard against overflow
|
||||||
uint8_t ep_cluster = buf_d.get8(d++);
|
uint8_t ep_cluster = buf_d.get8(d++);
|
||||||
if (0xFF == ep_cluster) { break; } // end of block
|
if (0xFF == ep_cluster) { break; } // end of block
|
||||||
zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), false);
|
// ignore
|
||||||
}
|
}
|
||||||
// out clusters
|
// out clusters
|
||||||
while (d < dev_record_len) { // safe guard against overflow
|
while (d < dev_record_len) { // safe guard against overflow
|
||||||
uint8_t ep_cluster = buf_d.get8(d++);
|
uint8_t ep_cluster = buf_d.get8(d++);
|
||||||
if (0xFF == ep_cluster) { break; } // end of block
|
if (0xFF == ep_cluster) { break; } // end of block
|
||||||
zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), true);
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zigbee_devices.shrinkToFit(shortaddr);
|
|
||||||
//AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Device 0x%04X Memory3.shrink = %d"), shortaddr, ESP.getFreeHeap());
|
//AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Device 0x%04X Memory3.shrink = %d"), shortaddr, ESP.getFreeHeap());
|
||||||
|
|
||||||
// parse 3 strings
|
// parse 3 strings
|
||||||
|
|
|
@ -549,6 +549,7 @@ ZF(ZCLVersion) ZF(AppVersion) ZF(StackVersion) ZF(HWVersion) ZF(Manufacturer) ZF
|
||||||
ZF(DateCode) ZF(PowerSource) ZF(SWBuildID) ZF(Power) ZF(SwitchType) ZF(Dimmer)
|
ZF(DateCode) ZF(PowerSource) ZF(SWBuildID) ZF(Power) ZF(SwitchType) ZF(Dimmer)
|
||||||
ZF(MainsVoltage) ZF(MainsFrequency) ZF(BatteryVoltage) ZF(BatteryPercentage)
|
ZF(MainsVoltage) ZF(MainsFrequency) ZF(BatteryVoltage) ZF(BatteryPercentage)
|
||||||
ZF(CurrentTemperature) ZF(MinTempExperienced) ZF(MaxTempExperienced) ZF(OverTempTotalDwell)
|
ZF(CurrentTemperature) ZF(MinTempExperienced) ZF(MaxTempExperienced) ZF(OverTempTotalDwell)
|
||||||
|
ZF(SceneCount) ZF(CurrentScene) ZF(CurrentGroup) ZF(SceneValid)
|
||||||
ZF(AlarmCount) ZF(Time) ZF(TimeStatus) ZF(TimeZone) ZF(DstStart) ZF(DstEnd)
|
ZF(AlarmCount) ZF(Time) ZF(TimeStatus) ZF(TimeZone) ZF(DstStart) ZF(DstEnd)
|
||||||
ZF(DstShift) ZF(StandardTime) ZF(LocalTime) ZF(LastSetTime) ZF(ValidUntilTime)
|
ZF(DstShift) ZF(StandardTime) ZF(LocalTime) ZF(LastSetTime) ZF(ValidUntilTime)
|
||||||
|
|
||||||
|
@ -660,6 +661,13 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = {
|
||||||
{ 0x0002, 0x0002, Z(MaxTempExperienced), &Z_Copy },
|
{ 0x0002, 0x0002, Z(MaxTempExperienced), &Z_Copy },
|
||||||
{ 0x0002, 0x0003, Z(OverTempTotalDwell), &Z_Copy },
|
{ 0x0002, 0x0003, Z(OverTempTotalDwell), &Z_Copy },
|
||||||
|
|
||||||
|
// Scenes cluster
|
||||||
|
{ 0x0005, 0x0000, Z(SceneCount), &Z_Copy },
|
||||||
|
{ 0x0005, 0x0001, Z(CurrentScene), &Z_Copy },
|
||||||
|
{ 0x0005, 0x0002, Z(CurrentGroup), &Z_Copy },
|
||||||
|
{ 0x0005, 0x0003, Z(SceneValid), &Z_Copy },
|
||||||
|
//{ 0x0005, 0x0004, Z(NameSupport), &Z_Copy },
|
||||||
|
|
||||||
// On/off cluster
|
// On/off cluster
|
||||||
{ 0x0006, 0x0000, Z(Power), &Z_Copy },
|
{ 0x0006, 0x0000, Z(Power), &Z_Copy },
|
||||||
{ 0x0006, 0x8000, Z(Power), &Z_Copy }, // See 7280
|
{ 0x0006, 0x8000, Z(Power), &Z_Copy }, // See 7280
|
||||||
|
@ -933,7 +941,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = {
|
||||||
{ 0x0405, 0x0000, Z(Humidity), &Z_FloatDiv100 }, // Humidity
|
{ 0x0405, 0x0000, Z(Humidity), &Z_FloatDiv100 }, // Humidity
|
||||||
{ 0x0405, 0x0001, Z(HumidityMinMeasuredValue), &Z_Copy }, //
|
{ 0x0405, 0x0001, Z(HumidityMinMeasuredValue), &Z_Copy }, //
|
||||||
{ 0x0405, 0x0002, Z(HumidityMaxMeasuredValue), &Z_Copy }, //
|
{ 0x0405, 0x0002, Z(HumidityMaxMeasuredValue), &Z_Copy }, //
|
||||||
{ 0x0405, 0x0003, Z(HumidityTolerance), &Z_Copy }, //
|
{ 0x0405, 0x0003, "HumidityTolerance", &Z_Copy }, //
|
||||||
{ 0x0405, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values
|
{ 0x0405, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values
|
||||||
|
|
||||||
// Occupancy Sensing cluster
|
// Occupancy Sensing cluster
|
||||||
|
|
|
@ -127,7 +127,7 @@ const Z_CommandConverter Z_Commands[] PROGMEM = {
|
||||||
{ Z(RemoveScene), 0x0005, 0x02, 0x82, Z(xxyyyyzz) }, // xx = status, yyyy = group id, zz = scene id
|
{ Z(RemoveScene), 0x0005, 0x02, 0x82, Z(xxyyyyzz) }, // xx = status, yyyy = group id, zz = scene id
|
||||||
{ Z(RemoveAllScenes),0x0005, 0x03, 0x82, Z(xxyyyy) }, // xx = status, yyyy = group id
|
{ Z(RemoveAllScenes),0x0005, 0x03, 0x82, Z(xxyyyy) }, // xx = status, yyyy = group id
|
||||||
{ Z(StoreScene), 0x0005, 0x04, 0x82, Z(xxyyyyzz) }, // xx = status, yyyy = group id, zz = scene id
|
{ Z(StoreScene), 0x0005, 0x04, 0x82, Z(xxyyyyzz) }, // xx = status, yyyy = group id, zz = scene id
|
||||||
{ Z(GetSceneMembership),0x0005, 0x06, 0x82, Z() }, // specific
|
{ Z(GetSceneMembership),0x0005, 0x06, 0x82,Z(xxyyzzzz) }, // specific
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ZLE(x) ((x) & 0xFF), ((x) >> 8) // Little Endian
|
#define ZLE(x) ((x) & 0xFF), ((x) >> 8) // Little Endian
|
||||||
|
@ -289,7 +289,7 @@ void sendHueUpdate(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uin
|
||||||
if (z_cat >= 0) {
|
if (z_cat >= 0) {
|
||||||
uint8_t endpoint = 0;
|
uint8_t endpoint = 0;
|
||||||
if (!groupaddr) {
|
if (!groupaddr) {
|
||||||
endpoint = zigbee_devices.findClusterEndpointIn(shortaddr, cluster);
|
endpoint = zigbee_devices.findFirstEndpoint(shortaddr);
|
||||||
}
|
}
|
||||||
if ((endpoint) || (groupaddr)) { // send only if we know the endpoint
|
if ((endpoint) || (groupaddr)) { // send only if we know the endpoint
|
||||||
zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms, cluster, endpoint, z_cat, 0 /* value */, &Z_ReadAttrCallback);
|
zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms, cluster, endpoint, z_cat, 0 /* value */, &Z_ReadAttrCallback);
|
||||||
|
@ -395,7 +395,33 @@ void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, boo
|
||||||
for (uint32_t i = 0; i < xyz.y; i++) {
|
for (uint32_t i = 0; i < xyz.y; i++) {
|
||||||
arr.add(payload.get16(2 + 2*i));
|
arr.add(payload.get16(2 + 2*i));
|
||||||
}
|
}
|
||||||
//arr.add(xyz.z);
|
} else if ((cluster == 0x0005) && ((cmd == 0x00) || (cmd == 0x02) || (cmd == 0x03))) {
|
||||||
|
// AddScene or RemoveScene or StoreScene
|
||||||
|
json[command_name2 + F("Status")] = xyz.x;
|
||||||
|
json[command_name2 + F("StatusMsg")] = getZigbeeStatusMessage(xyz.x);
|
||||||
|
json[F("GroupId")] = xyz.y;
|
||||||
|
json[F("SceneId")] = xyz.z;
|
||||||
|
} else if ((cluster == 0x0005) && (cmd == 0x01)) {
|
||||||
|
// ViewScene
|
||||||
|
json[command_name2 + F("Status")] = xyz.x;
|
||||||
|
json[command_name2 + F("StatusMsg")] = getZigbeeStatusMessage(xyz.x);
|
||||||
|
json[F("GroupId")] = xyz.y;
|
||||||
|
json[F("SceneId")] = xyz.z;
|
||||||
|
String scene_payload = json[attrid_str];
|
||||||
|
json[F("ScenePayload")] = scene_payload.substring(8); // remove first 8 characters
|
||||||
|
} else if ((cluster == 0x0005) && (cmd == 0x03)) {
|
||||||
|
// RemoveAllScenes
|
||||||
|
json[command_name2 + F("Status")] = xyz.x;
|
||||||
|
json[command_name2 + F("StatusMsg")] = getZigbeeStatusMessage(xyz.x);
|
||||||
|
json[F("GroupId")] = xyz.y;
|
||||||
|
} else if ((cluster == 0x0005) && (cmd == 0x06)) {
|
||||||
|
// GetSceneMembership
|
||||||
|
json[command_name2 + F("Status")] = xyz.x;
|
||||||
|
json[command_name2 + F("StatusMsg")] = getZigbeeStatusMessage(xyz.x);
|
||||||
|
json[F("Capacity")] = xyz.y;
|
||||||
|
json[F("GroupId")] = xyz.z;
|
||||||
|
String scene_payload = json[attrid_str];
|
||||||
|
json[F("ScenePayload")] = scene_payload.substring(8); // remove first 8 characters
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (0 == xyz.x_type) {
|
if (0 == xyz.x_type) {
|
||||||
|
|
|
@ -190,20 +190,6 @@ void Z_SendActiveEpReq(uint16_t shortaddr) {
|
||||||
Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) };
|
Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) };
|
||||||
|
|
||||||
ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq));
|
ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq));
|
||||||
|
|
||||||
// uint8_t NodeDescReq[] = { Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ,
|
|
||||||
// Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) };
|
|
||||||
|
|
||||||
//ZigbeeZNPSend(NodeDescReq, sizeof(NodeDescReq)); Not sure this is useful
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send ZDO_SIMPLE_DESC_REQ to get full list of supported Clusters for a specific endpoint
|
|
||||||
void Z_SendSimpleDescReq(uint16_t shortaddr, uint8_t endpoint) {
|
|
||||||
uint8_t SimpleDescReq[] = { Z_SREQ | Z_ZDO, ZDO_SIMPLE_DESC_REQ, // 2504
|
|
||||||
Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr),
|
|
||||||
endpoint };
|
|
||||||
|
|
||||||
ZigbeeZNPSend(SimpleDescReq, sizeof(SimpleDescReq));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* Z_DeviceType[] = { "Coordinator", "Router", "End Device", "Unknown" };
|
const char* Z_DeviceType[] = { "Coordinator", "Router", "End Device", "Unknown" };
|
||||||
|
@ -248,13 +234,8 @@ int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) {
|
||||||
uint8_t activeEpCount = buf.get8(7);
|
uint8_t activeEpCount = buf.get8(7);
|
||||||
uint8_t* activeEpList = (uint8_t*) buf.charptr(8);
|
uint8_t* activeEpList = (uint8_t*) buf.charptr(8);
|
||||||
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < activeEpCount; i++) {
|
for (uint32_t i = 0; i < activeEpCount; i++) {
|
||||||
zigbee_devices.addEndoint(nwkAddr, activeEpList[i]);
|
zigbee_devices.addEndpoint(nwkAddr, activeEpList[i]);
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < activeEpCount; i++) {
|
|
||||||
Z_SendSimpleDescReq(nwkAddr, activeEpList[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
||||||
|
@ -292,56 +273,6 @@ void Z_SendAFInfoRequest(uint16_t shortaddr, uint8_t endpoint, uint16_t clusteri
|
||||||
ZigbeeZNPSend(buf.getBuffer(), buf.len());
|
ZigbeeZNPSend(buf.getBuffer(), buf.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf) {
|
|
||||||
// Received ZDO_SIMPLE_DESC_RSP
|
|
||||||
Z_ShortAddress srcAddr = buf.get16(2);
|
|
||||||
uint8_t status = buf.get8(4);
|
|
||||||
Z_ShortAddress nwkAddr = buf.get16(5);
|
|
||||||
uint8_t lenDescriptor = buf.get8(7);
|
|
||||||
uint8_t endpoint = buf.get8(8);
|
|
||||||
uint16_t profileId = buf.get16(9); // The profile Id for this endpoint.
|
|
||||||
uint16_t deviceId = buf.get16(11); // The Device Description Id for this endpoint.
|
|
||||||
uint8_t deviceVersion = buf.get8(13); // 0 – Version 1.00
|
|
||||||
uint8_t numInCluster = buf.get8(14);
|
|
||||||
uint8_t numOutCluster = buf.get8(15 + numInCluster*2);
|
|
||||||
|
|
||||||
if (0 == status) {
|
|
||||||
zigbee_devices.addEndointProfile(nwkAddr, endpoint, profileId);
|
|
||||||
for (uint32_t i = 0; i < numInCluster; i++) {
|
|
||||||
zigbee_devices.addCluster(nwkAddr, endpoint, buf.get16(15 + i*2), false);
|
|
||||||
}
|
|
||||||
for (uint32_t i = 0; i < numOutCluster; i++) {
|
|
||||||
zigbee_devices.addCluster(nwkAddr, endpoint, buf.get16(16 + numInCluster*2 + i*2), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
|
||||||
"\"Status\":%d,\"Endpoint\":\"0x%02X\""
|
|
||||||
",\"ProfileId\":\"0x%04X\",\"DeviceId\":\"0x%04X\",\"DeviceVersion\":%d"
|
|
||||||
"\"InClusters\":["),
|
|
||||||
ZIGBEE_STATUS_SIMPLE_DESC, endpoint,
|
|
||||||
profileId, deviceId, deviceVersion);
|
|
||||||
for (uint32_t i = 0; i < numInCluster; i++) {
|
|
||||||
if (i > 0) { ResponseAppend_P(PSTR(",")); }
|
|
||||||
ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(15 + i*2));
|
|
||||||
}
|
|
||||||
ResponseAppend_P(PSTR("],\"OutClusters\":["));
|
|
||||||
for (uint32_t i = 0; i < numOutCluster; i++) {
|
|
||||||
if (i > 0) { ResponseAppend_P(PSTR(",")); }
|
|
||||||
ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(16 + numInCluster*2 + i*2));
|
|
||||||
}
|
|
||||||
ResponseAppend_P(PSTR("]}}"));
|
|
||||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED));
|
|
||||||
XdrvRulesProcess();
|
|
||||||
|
|
||||||
uint8_t cluster = zigbee_devices.findClusterEndpointIn(nwkAddr, 0x0000);
|
|
||||||
if (cluster) {
|
|
||||||
Z_SendAFInfoRequest(nwkAddr, cluster, 0x0000, 0x01); // TODO, do we need tarnsacId counter?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) {
|
int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) {
|
||||||
uint8_t status = buf.get8(2);
|
uint8_t status = buf.get8(2);
|
||||||
Z_IEEEAddress ieeeAddr = buf.get64(3);
|
Z_IEEEAddress ieeeAddr = buf.get64(3);
|
||||||
|
@ -353,14 +284,6 @@ int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) {
|
||||||
zigbee_devices.updateDevice(nwkAddr, ieeeAddr);
|
zigbee_devices.updateDevice(nwkAddr, ieeeAddr);
|
||||||
char hex[20];
|
char hex[20];
|
||||||
Uint64toHex(ieeeAddr, hex, 64);
|
Uint64toHex(ieeeAddr, hex, 64);
|
||||||
// Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
|
||||||
// "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\""
|
|
||||||
// "}}"),
|
|
||||||
// ZIGBEE_STATUS_DEVICE_IEEE, hex, nwkAddr
|
|
||||||
// );
|
|
||||||
|
|
||||||
// MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED));
|
|
||||||
// XdrvRulesProcess();
|
|
||||||
// Ping response
|
// Ping response
|
||||||
const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr);
|
const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr);
|
||||||
if (friendlyName) {
|
if (friendlyName) {
|
||||||
|
@ -417,7 +340,9 @@ int32_t Z_DataConfirm(int32_t res, const class SBuffer &buf) {
|
||||||
char status_message[32];
|
char status_message[32];
|
||||||
|
|
||||||
if (status) { // only report errors
|
if (status) { // only report errors
|
||||||
strncpy_P(status_message, (const char*) getZigbeeStatusMessage(status), sizeof(status_message));
|
const char * statm = (const char*) getZigbeeStatusMessage(status);
|
||||||
|
if (nullptr == statm) { statm = PSTR(""); }
|
||||||
|
strncpy_P(status_message, statm, sizeof(status_message));
|
||||||
status_message[sizeof(status_message)-1] = 0; // truncate if needed, strlcpy is safer but strlcpy_P does not exist
|
status_message[sizeof(status_message)-1] = 0; // truncate if needed, strlcpy is safer but strlcpy_P does not exist
|
||||||
|
|
||||||
Response_P(PSTR("{\"" D_JSON_ZIGBEE_CONFIRM "\":{\"" D_CMND_ZIGBEE_ENDPOINT "\":%d"
|
Response_P(PSTR("{\"" D_JSON_ZIGBEE_CONFIRM "\":{\"" D_CMND_ZIGBEE_ENDPOINT "\":%d"
|
||||||
|
@ -442,7 +367,7 @@ int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) {
|
||||||
char hex[20];
|
char hex[20];
|
||||||
Uint64toHex(ieeeAddr, hex, 64);
|
Uint64toHex(ieeeAddr, hex, 64);
|
||||||
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
||||||
"\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\""
|
"\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\""
|
||||||
",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"),
|
",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"),
|
||||||
ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr,
|
ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr,
|
||||||
(capabilities & 0x04) ? "true" : "false",
|
(capabilities & 0x04) ? "true" : "false",
|
||||||
|
@ -467,7 +392,7 @@ int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) {
|
||||||
char hex[20];
|
char hex[20];
|
||||||
Uint64toHex(ieeeAddr, hex, 64);
|
Uint64toHex(ieeeAddr, hex, 64);
|
||||||
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
||||||
"\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\""
|
"\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\""
|
||||||
",\"ParentNetwork\":\"0x%04X\"}}"),
|
",\"ParentNetwork\":\"0x%04X\"}}"),
|
||||||
ZIGBEE_STATUS_DEVICE_INDICATION, hex, srcAddr, parentNw
|
ZIGBEE_STATUS_DEVICE_INDICATION, hex, srcAddr, parentNw
|
||||||
);
|
);
|
||||||
|
@ -600,7 +525,6 @@ const Z_Dispatcher Z_DispatchTable[] PROGMEM = {
|
||||||
{ AREQ_PERMITJOIN_OPEN_XX, &Z_ReceivePermitJoinStatus },
|
{ AREQ_PERMITJOIN_OPEN_XX, &Z_ReceivePermitJoinStatus },
|
||||||
{ AREQ_ZDO_NODEDESCRSP, &Z_ReceiveNodeDesc },
|
{ AREQ_ZDO_NODEDESCRSP, &Z_ReceiveNodeDesc },
|
||||||
{ AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp },
|
{ AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp },
|
||||||
{ AREQ_ZDO_SIMPLEDESCRSP, &Z_ReceiveSimpleDesc },
|
|
||||||
{ AREQ_ZDO_IEEE_ADDR_RSP, &Z_ReceiveIEEEAddr },
|
{ AREQ_ZDO_IEEE_ADDR_RSP, &Z_ReceiveIEEEAddr },
|
||||||
{ AREQ_ZDO_BIND_RSP, &Z_BindRsp },
|
{ AREQ_ZDO_BIND_RSP, &Z_BindRsp },
|
||||||
};
|
};
|
||||||
|
@ -635,24 +559,21 @@ int32_t Z_Query_Bulbs(uint8_t value) {
|
||||||
|
|
||||||
if (0 <= device.bulbtype) {
|
if (0 <= device.bulbtype) {
|
||||||
uint16_t cluster;
|
uint16_t cluster;
|
||||||
uint8_t endpoint;
|
uint8_t endpoint = zigbee_devices.findFirstEndpoint(device.shortaddr);
|
||||||
|
|
||||||
cluster = 0x0006;
|
cluster = 0x0006;
|
||||||
endpoint = zigbee_devices.findClusterEndpointIn(device.shortaddr, cluster);
|
|
||||||
if (endpoint) { // send only if we know the endpoint
|
if (endpoint) { // send only if we know the endpoint
|
||||||
zigbee_devices.setTimer(device.shortaddr, 0 /* groupaddr */, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback);
|
zigbee_devices.setTimer(device.shortaddr, 0 /* groupaddr */, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback);
|
||||||
wait_ms += inter_message_ms;
|
wait_ms += inter_message_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
cluster = 0x0008;
|
cluster = 0x0008;
|
||||||
endpoint = zigbee_devices.findClusterEndpointIn(device.shortaddr, cluster);
|
|
||||||
if (endpoint) { // send only if we know the endpoint
|
if (endpoint) { // send only if we know the endpoint
|
||||||
zigbee_devices.setTimer(device.shortaddr, 0 /* groupaddr */, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback);
|
zigbee_devices.setTimer(device.shortaddr, 0 /* groupaddr */, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback);
|
||||||
wait_ms += inter_message_ms;
|
wait_ms += inter_message_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
cluster = 0x0300;
|
cluster = 0x0300;
|
||||||
endpoint = zigbee_devices.findClusterEndpointIn(device.shortaddr, cluster);
|
|
||||||
if (endpoint) { // send only if we know the endpoint
|
if (endpoint) { // send only if we know the endpoint
|
||||||
zigbee_devices.setTimer(device.shortaddr, 0 /* groupaddr */, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback);
|
zigbee_devices.setTimer(device.shortaddr, 0 /* groupaddr */, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback);
|
||||||
wait_ms += inter_message_ms;
|
wait_ms += inter_message_ms;
|
||||||
|
|
|
@ -394,7 +394,7 @@ void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint,
|
||||||
|
|
||||||
if ((0 == endpoint) && (shortaddr)) {
|
if ((0 == endpoint) && (shortaddr)) {
|
||||||
// endpoint is not specified, let's try to find it from shortAddr, unless it's a group address
|
// endpoint is not specified, let's try to find it from shortAddr, unless it's a group address
|
||||||
endpoint = zigbee_devices.findClusterEndpointIn(shortaddr, cluster);
|
endpoint = zigbee_devices.findFirstEndpoint(shortaddr);
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint);
|
||||||
}
|
}
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: shortaddr 0x%04X, groupaddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"),
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: shortaddr 0x%04X, groupaddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"),
|
||||||
|
@ -847,7 +847,7 @@ void CmndZbRead(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((0 == endpoint) && (device)) { // try to compute the endpoint
|
if ((0 == endpoint) && (device)) { // try to compute the endpoint
|
||||||
endpoint = zigbee_devices.findClusterEndpointIn(device, cluster);
|
endpoint = zigbee_devices.findFirstEndpoint(device);
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint);
|
||||||
}
|
}
|
||||||
if (groupaddr) {
|
if (groupaddr) {
|
||||||
|
|
Loading…
Reference in New Issue