mirror of https://github.com/arendst/Tasmota.git
Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa
This commit is contained in:
parent
7d33480b7b
commit
d4a9ed41c9
|
@ -6,6 +6,7 @@
|
|||
- Change GPIO initialization solving possible Relay toggle on (OTA) restart
|
||||
- Fix Zigbee sending wrong Sat value with Hue emulation
|
||||
- Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2``
|
||||
- Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa
|
||||
|
||||
## Released
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ typedef struct Z_Device {
|
|||
uint8_t seqNumber;
|
||||
// Light information for Hue integration integration, last known values
|
||||
int8_t bulbtype; // number of channel for the bulb: 0-5, or 0xFF if no Hue integration
|
||||
uint8_t power; // power state (boolean)
|
||||
uint8_t power; // power state (boolean), MSB (0x80) stands for reachable
|
||||
uint8_t colormode; // 0x00: Hue/Sat, 0x01: XY, 0x02: CT
|
||||
uint8_t dimmer; // last Dimmer value: 0-254
|
||||
uint8_t sat; // last Sat: 0..254
|
||||
|
@ -66,12 +66,15 @@ typedef enum Z_Def_Category {
|
|||
Z_CAT_NONE = 0, // no category, it will happen anyways
|
||||
Z_CAT_READ_ATTR, // Attribute reporting, either READ_ATTRIBUTE or REPORT_ATTRIBUTE, we coalesce all attributes reported if we can
|
||||
Z_CAT_VIRTUAL_ATTR, // Creation of a virtual attribute, typically after a time-out. Ex: Aqara presence sensor
|
||||
Z_CAT_REACHABILITY, // timer set to measure reachability of device, i.e. if we don't get an answer after 1s, it is marked as unreachable (for Alexa)
|
||||
Z_CAT_READ_0006, // Read 0x0006 cluster
|
||||
Z_CAT_READ_0008, // Read 0x0008 cluster
|
||||
Z_CAT_READ_0102, // Read 0x0300 cluster
|
||||
Z_CAT_READ_0300, // Read 0x0300 cluster
|
||||
} Z_Def_Category;
|
||||
|
||||
const uint32_t Z_CAT_REACHABILITY_TIMEOUT = 1000; // 1000 ms or 1s
|
||||
|
||||
typedef struct Z_Deferred {
|
||||
// below are per device timers, used for example to query the new state of the device
|
||||
uint32_t timer; // millis() when to fire the timer, 0 if no timer
|
||||
|
@ -124,6 +127,7 @@ public:
|
|||
void setFriendlyName(uint16_t shortaddr, const char * str);
|
||||
const char * getFriendlyName(uint16_t shortaddr) const;
|
||||
const char * getModelId(uint16_t shortaddr) const;
|
||||
void setReachable(uint16_t shortaddr, bool reachable);
|
||||
|
||||
// get next sequence number for (increment at each all)
|
||||
uint8_t getNextSeqNumber(uint16_t shortaddr);
|
||||
|
@ -137,15 +141,17 @@ public:
|
|||
void setHueBulbtype(uint16_t shortaddr, int8_t bulbtype);
|
||||
int8_t getHueBulbtype(uint16_t shortaddr) const ;
|
||||
void updateHueState(uint16_t shortaddr,
|
||||
const uint8_t *power, const uint8_t *colormode,
|
||||
const bool *power, const uint8_t *colormode,
|
||||
const uint8_t *dimmer, const uint8_t *sat,
|
||||
const uint16_t *ct, const uint16_t *hue,
|
||||
const uint16_t *x, const uint16_t *y);
|
||||
const uint16_t *x, const uint16_t *y,
|
||||
const bool *reachable);
|
||||
bool getHueState(uint16_t shortaddr,
|
||||
uint8_t *power, uint8_t *colormode,
|
||||
bool *power, uint8_t *colormode,
|
||||
uint8_t *dimmer, uint8_t *sat,
|
||||
uint16_t *ct, uint16_t *hue,
|
||||
uint16_t *x, uint16_t *y) const ;
|
||||
uint16_t *x, uint16_t *y,
|
||||
bool *reachable) const ;
|
||||
|
||||
// Timers
|
||||
void resetTimersForDevice(uint16_t shortaddr, uint16_t groupaddr, uint8_t category);
|
||||
|
@ -262,7 +268,7 @@ Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) {
|
|||
0, // seqNumber
|
||||
// Hue support
|
||||
-1, // no Hue support
|
||||
0, // power
|
||||
0x80, // power off + reachable
|
||||
0, // colormode
|
||||
0, // dimmer
|
||||
0, // sat
|
||||
|
@ -583,6 +589,12 @@ const char * Z_Devices::getModelId(uint16_t shortaddr) const {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void Z_Devices::setReachable(uint16_t shortaddr, bool reachable) {
|
||||
Z_Device & device = getShortAddr(shortaddr);
|
||||
if (&device == nullptr) { return; } // don't crash if not found
|
||||
bitWrite(device.power, 7, reachable);
|
||||
}
|
||||
|
||||
// get the next sequance number for the device, or use the global seq number if device is unknown
|
||||
uint8_t Z_Devices::getNextSeqNumber(uint16_t shortaddr) {
|
||||
int32_t short_found = findShortAddr(shortaddr);
|
||||
|
@ -616,12 +628,13 @@ int8_t Z_Devices::getHueBulbtype(uint16_t shortaddr) const {
|
|||
|
||||
// Hue support
|
||||
void Z_Devices::updateHueState(uint16_t shortaddr,
|
||||
const uint8_t *power, const uint8_t *colormode,
|
||||
const bool *power, const uint8_t *colormode,
|
||||
const uint8_t *dimmer, const uint8_t *sat,
|
||||
const uint16_t *ct, const uint16_t *hue,
|
||||
const uint16_t *x, const uint16_t *y) {
|
||||
const uint16_t *x, const uint16_t *y,
|
||||
const bool *reachable) {
|
||||
Z_Device &device = getShortAddr(shortaddr);
|
||||
if (power) { device.power = *power; }
|
||||
if (power) { bitWrite(device.power, 0, *power); }
|
||||
if (colormode){ device.colormode = *colormode; }
|
||||
if (dimmer) { device.dimmer = *dimmer; }
|
||||
if (sat) { device.sat = *sat; }
|
||||
|
@ -629,18 +642,20 @@ void Z_Devices::updateHueState(uint16_t shortaddr,
|
|||
if (hue) { device.hue = *hue; }
|
||||
if (x) { device.x = *x; }
|
||||
if (y) { device.y = *y; }
|
||||
if (reachable){ bitWrite(device.power, 7, *reachable); }
|
||||
}
|
||||
|
||||
// return true if ok
|
||||
bool Z_Devices::getHueState(uint16_t shortaddr,
|
||||
uint8_t *power, uint8_t *colormode,
|
||||
bool *power, uint8_t *colormode,
|
||||
uint8_t *dimmer, uint8_t *sat,
|
||||
uint16_t *ct, uint16_t *hue,
|
||||
uint16_t *x, uint16_t *y) const {
|
||||
uint16_t *x, uint16_t *y,
|
||||
bool *reachable) const {
|
||||
int32_t found = findShortAddr(shortaddr);
|
||||
if (found >= 0) {
|
||||
const Z_Device &device = *(_devices[found]);
|
||||
if (power) { *power = device.power; }
|
||||
if (power) { *power = bitRead(device.power, 0); }
|
||||
if (colormode){ *colormode = device.colormode; }
|
||||
if (dimmer) { *dimmer = device.dimmer; }
|
||||
if (sat) { *sat = device.sat; }
|
||||
|
@ -648,6 +663,7 @@ bool Z_Devices::getHueState(uint16_t shortaddr,
|
|||
if (hue) { *hue = device.hue; }
|
||||
if (x) { *x = device.x; }
|
||||
if (y) { *y = device.y; }
|
||||
if (reachable){ *reachable = bitRead(device.power, 7); }
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -951,7 +967,8 @@ String Z_Devices::dumpLightState(uint16_t shortaddr) const {
|
|||
dev[F(D_JSON_ZIGBEE_LIGHT)] = device.bulbtype; // sign extend, 0xFF changed as -1
|
||||
if (0 <= device.bulbtype) {
|
||||
// bulbtype is defined
|
||||
dev[F("Power")] = device.power;
|
||||
dev[F("Power")] = bitRead(device.power, 0);
|
||||
dev[F("Reachable")] = bitRead(device.power, 7);
|
||||
if (1 <= device.bulbtype) {
|
||||
dev[F("Dimmer")] = device.dimmer;
|
||||
}
|
||||
|
|
|
@ -24,13 +24,19 @@
|
|||
|
||||
// idx: index in the list of zigbee_devices
|
||||
void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, String *response) {
|
||||
uint8_t power, colormode, bri, sat;
|
||||
static const char HUE_LIGHTS_STATUS_JSON1_SUFFIX_ZIGBEE[] PROGMEM =
|
||||
"%s\"alert\":\"none\","
|
||||
"\"effect\":\"none\","
|
||||
"\"reachable\":%s}";
|
||||
|
||||
bool power, reachable;
|
||||
uint8_t colormode, bri, sat;
|
||||
uint16_t ct, hue;
|
||||
uint16_t x, y;
|
||||
String light_status = "";
|
||||
uint32_t echo_gen = findEchoGeneration(); // 1 for 1st gen =+ Echo Dot 2nd gen, 2 for 2nd gen and above
|
||||
|
||||
zigbee_devices.getHueState(shortaddr, &power, &colormode, &bri, &sat, &ct, &hue, &x, &y);
|
||||
zigbee_devices.getHueState(shortaddr, &power, &colormode, &bri, &sat, &ct, &hue, &x, &y, &reachable);
|
||||
|
||||
if (bri > 254) bri = 254; // Philips Hue bri is between 1 and 254
|
||||
if (bri < 1) bri = 1;
|
||||
|
@ -40,7 +46,7 @@ void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, Stri
|
|||
const size_t buf_size = 256;
|
||||
char * buf = (char*) malloc(buf_size); // temp buffer for strings, avoid stack
|
||||
|
||||
snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), (power & 1) ? "true" : "false");
|
||||
snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), power ? "true" : "false");
|
||||
// Brightness for all devices with PWM
|
||||
if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { // force dimmer for 1st gen Echo
|
||||
snprintf_P(buf, buf_size, PSTR("%s\"bri\":%d,"), buf, bri);
|
||||
|
@ -61,7 +67,7 @@ void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, Stri
|
|||
if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { // white temp
|
||||
snprintf_P(buf, buf_size, PSTR("%s\"ct\":%d,"), buf, ct > 0 ? ct : 284);
|
||||
}
|
||||
snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON1_SUFFIX, buf);
|
||||
snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON1_SUFFIX_ZIGBEE, buf, reachable ? "true" : "false");
|
||||
|
||||
*response += buf;
|
||||
free(buf);
|
||||
|
@ -123,9 +129,9 @@ void ZigbeeHueGroups(String * lights) {
|
|||
|
||||
// Send commands
|
||||
// Power On/Off
|
||||
void ZigbeeHuePower(uint16_t shortaddr, uint8_t power) {
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0006, power, "");
|
||||
zigbee_devices.updateHueState(shortaddr, &power, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
void ZigbeeHuePower(uint16_t shortaddr, bool power) {
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0006, power ? 1 : 0, "");
|
||||
zigbee_devices.updateHueState(shortaddr, &power, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
// Dimmer
|
||||
|
@ -134,7 +140,7 @@ void ZigbeeHueDimmer(uint16_t shortaddr, uint8_t dimmer) {
|
|||
char param[8];
|
||||
snprintf_P(param, sizeof(param), PSTR("%02X0A00"), dimmer);
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0008, 0x04, param);
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, &dimmer, nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, &dimmer, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
// CT
|
||||
|
@ -145,7 +151,7 @@ void ZigbeeHueCT(uint16_t shortaddr, uint16_t ct) {
|
|||
snprintf_P(param, sizeof(param), PSTR("%02X%02X0A00"), ct & 0xFF, ct >> 8);
|
||||
uint8_t colormode = 2; // "ct"
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x0A, param);
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr, &ct, nullptr, nullptr, nullptr);
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr, &ct, nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
// XY
|
||||
|
@ -156,7 +162,7 @@ void ZigbeeHueXY(uint16_t shortaddr, uint16_t x, uint16_t y) {
|
|||
snprintf_P(param, sizeof(param), PSTR("%02X%02X%02X%02X0A00"), x & 0xFF, x >> 8, y & 0xFF, y >> 8);
|
||||
uint8_t colormode = 1; // "xy"
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x07, param);
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr, nullptr, nullptr, &x, &y);
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr, nullptr, nullptr, &x, &y, nullptr);
|
||||
}
|
||||
|
||||
// HueSat
|
||||
|
@ -167,7 +173,7 @@ void ZigbeeHueHS(uint16_t shortaddr, uint16_t hue, uint8_t sat) {
|
|||
snprintf_P(param, sizeof(param), PSTR("%02X%02X0000"), hue8, sat);
|
||||
uint8_t colormode = 0; // "hs"
|
||||
zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x06, param);
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, &sat, nullptr, &hue, nullptr, nullptr);
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, &sat, nullptr, &hue, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) {
|
||||
|
|
|
@ -1215,38 +1215,38 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) {
|
|||
|
||||
// see if we need to update the Hue bulb status
|
||||
if ((cluster == 0x0006) && ((attribute == 0x0000) || (attribute == 0x8000))) {
|
||||
uint8_t power = value;
|
||||
bool power = value;
|
||||
zigbee_devices.updateHueState(shortaddr, &power, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr);
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
} else if ((cluster == 0x0008) && (attribute == 0x0000)) {
|
||||
uint8_t dimmer = value;
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, &dimmer, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr);
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
} else if ((cluster == 0x0300) && (attribute == 0x0000)) {
|
||||
uint16_t hue8 = value;
|
||||
uint16_t hue = changeUIntScale(hue8, 0, 254, 0, 360); // change range from 0..254 to 0..360
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, &hue, nullptr, nullptr);
|
||||
nullptr, &hue, nullptr, nullptr, nullptr);
|
||||
} else if ((cluster == 0x0300) && (attribute == 0x0001)) {
|
||||
uint8_t sat = value;
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, nullptr, &sat,
|
||||
nullptr, nullptr, nullptr, nullptr);
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
} else if ((cluster == 0x0300) && (attribute == 0x0003)) {
|
||||
uint16_t x = value;
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, &x, nullptr);
|
||||
nullptr, nullptr, &x, nullptr, nullptr);
|
||||
} else if ((cluster == 0x0300) && (attribute == 0x0004)) {
|
||||
uint16_t y = value;
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, &y);
|
||||
nullptr, nullptr, nullptr, &y, nullptr), nullptr;
|
||||
} else if ((cluster == 0x0300) && (attribute == 0x0007)) {
|
||||
uint16_t ct = value;
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, nullptr, nullptr,
|
||||
&ct, nullptr, nullptr, nullptr);
|
||||
&ct, nullptr, nullptr, nullptr, nullptr);
|
||||
} else if ((cluster == 0x0300) && (attribute == 0x0008)) {
|
||||
uint8_t colormode = value;
|
||||
zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr);
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
// Iterate on filter
|
||||
|
|
|
@ -173,6 +173,14 @@ int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t clus
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// This callback is registered after a an attribute read command was made to a light, and fires if we don't get any response after 1000 ms
|
||||
int32_t Z_Unreachable(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) {
|
||||
if (shortaddr) {
|
||||
zigbee_devices.setReachable(shortaddr, false); // mark device as reachable
|
||||
}
|
||||
}
|
||||
|
||||
// set a timer to read back the value in the future
|
||||
void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint) {
|
||||
uint32_t wait_ms = 0;
|
||||
|
@ -192,6 +200,9 @@ void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t groupaddr, uint16_t clus
|
|||
}
|
||||
if (wait_ms) {
|
||||
zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback);
|
||||
if (shortaddr) { // reachability test is not possible for group addresses, since we don't know the list of devices in the group
|
||||
zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, cluster, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,6 +311,10 @@ void sendHueUpdate(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uin
|
|||
}
|
||||
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);
|
||||
if (shortaddr) { // reachability test is not possible for group addresses, since we don't know the list of devices in the group
|
||||
zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, cluster, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -308,6 +308,7 @@ int32_t Z_DataConfirm(int32_t res, const class SBuffer &buf) {
|
|||
|
||||
//
|
||||
// Handle Receive End Device Announce incoming message
|
||||
// This message is also received when a previously paired device is powered up
|
||||
// Send back Active Ep Req message
|
||||
//
|
||||
int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) {
|
||||
|
@ -328,6 +329,9 @@ int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) {
|
|||
(capabilities & 0x08) ? "true" : "false",
|
||||
(capabilities & 0x40) ? "true" : "false"
|
||||
);
|
||||
// query the state of the bulb (for Alexa)
|
||||
uint32_t wait_ms = 2000; // wait for 2s
|
||||
Z_Query_Bulb(nwkAddr, wait_ms);
|
||||
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED));
|
||||
XdrvRulesProcess();
|
||||
|
@ -513,6 +517,10 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) {
|
|||
// Add linkquality
|
||||
json[F(D_CMND_ZIGBEE_LINKQUALITY)] = linkquality;
|
||||
|
||||
// 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
|
||||
zigbee_devices.setReachable(srcaddr, true); // mark device as reachable
|
||||
|
||||
if (defer_attributes) {
|
||||
// Prepare for publish
|
||||
if (zigbee_devices.jsonIsConflict(srcaddr, json)) {
|
||||
|
@ -591,38 +599,36 @@ int32_t Z_Load_Devices(uint8_t value) {
|
|||
return 0; // continue
|
||||
}
|
||||
|
||||
//
|
||||
// Query the state of a bulb (light) if its type allows it
|
||||
//
|
||||
void Z_Query_Bulb(uint16_t shortaddr, uint32_t &wait_ms) {
|
||||
const uint32_t inter_message_ms = 100; // wait 100ms between messages
|
||||
|
||||
if (0 <= zigbee_devices.getHueBulbtype(shortaddr)) {
|
||||
uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr);
|
||||
|
||||
if (endpoint) { // send only if we know the endpoint
|
||||
zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0006, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback);
|
||||
wait_ms += inter_message_ms;
|
||||
zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0008, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback);
|
||||
wait_ms += inter_message_ms;
|
||||
zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0300, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback);
|
||||
wait_ms += inter_message_ms;
|
||||
zigbee_devices.setTimer(shortaddr, 0, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, 0, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Send messages to query the state of each Hue emulated light
|
||||
//
|
||||
int32_t Z_Query_Bulbs(uint8_t value) {
|
||||
// Scan all devices and send deferred requests to know the state of bulbs
|
||||
uint32_t wait_ms = 1000; // start with 1.0 s delay
|
||||
const uint32_t inter_message_ms = 100; // wait 100ms between messages
|
||||
for (uint32_t i = 0; i < zigbee_devices.devicesSize(); i++) {
|
||||
const Z_Device &device = zigbee_devices.devicesAt(i);
|
||||
|
||||
if (0 <= device.bulbtype) {
|
||||
uint16_t cluster;
|
||||
uint8_t endpoint = zigbee_devices.findFirstEndpoint(device.shortaddr);
|
||||
|
||||
cluster = 0x0006;
|
||||
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);
|
||||
wait_ms += inter_message_ms;
|
||||
}
|
||||
|
||||
cluster = 0x0008;
|
||||
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);
|
||||
wait_ms += inter_message_ms;
|
||||
}
|
||||
|
||||
cluster = 0x0300;
|
||||
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);
|
||||
wait_ms += inter_message_ms;
|
||||
}
|
||||
}
|
||||
Z_Query_Bulb(device.shortaddr, wait_ms);
|
||||
}
|
||||
return 0; // continue
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue