Zigbee command ``ZbScan`` to do an energy scan on each radio channel

This commit is contained in:
Stephan Hadinger 2021-02-03 20:37:44 +01:00
parent de13b8168a
commit 9d14587e20
6 changed files with 101 additions and 7 deletions

View File

@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file.
- Command ``L1MusicSync <0|Off>|<1|On>|<2|Toggle>, 1..10, 1..100>`` to control Sonoff L1 Music Sync mode sensitivity and speed (#10722)
- Command ``Speed2`` to control a once off fade (#10741)
- Zigbee command ``SetOption120 1`` or ``ZbEndpointTopic 1`` to add the endpoint as suffix in topic when using ``SetOption89 1``
- Zigbee command ``ZbScan`` to do an energy scan on each radio channel
### Changed
- Maximum chars in ``AddLog_P`` logging restored from 128 to 700 (MAX_LOGSZ) to solve broken error messages

View File

@ -615,6 +615,8 @@
#define D_CMND_ZIGBEE_CONFIG "Config"
#define D_JSON_ZIGBEE_CONFIG "Config"
#define D_CMND_ZIGBEE_DATA "Data"
#define D_CMND_ZIGBEE_SCAN "Scan"
#define D_JSON_ZIGBEE_SCAN "ZbScan"
// Commands xdrv_25_A4988_Stepper.ino
#define D_CMND_MOTOR "MOTOR"

View File

@ -23,6 +23,11 @@
#include "Eeprom24C512.h"
#endif // USE_ZIGBEE_EZSP
// channels numbers for Zigbee radio energy scan
#define USE_ZIGBEE_CHANNEL_MIN 11
#define USE_ZIGBEE_CHANNEL_MAX 26
#define USE_ZIGBEE_CHANNEL_COUNT (USE_ZIGBEE_CHANNEL_MAX - USE_ZIGBEE_CHANNEL_MIN + 1)
// contains some definitions for functions used before their declarations
//
@ -123,6 +128,9 @@ public:
ZB_RecvMsgFunc recv_func = nullptr; // function to call when message is expected
ZB_RecvMsgFunc recv_unexpected = nullptr; // function called when unexpected message is received
// Energy scan
int8_t energy[USE_ZIGBEE_CHANNEL_COUNT];
#ifdef USE_ZIGBEE_EZSP
uint32_t permit_end_time = 0; // timestamp when permit join ends
uint16_t ezsp_version = 0;

View File

@ -160,6 +160,60 @@ int32_t EZ_RouteError(int32_t res, const SBuffer &buf) {
return -1;
}
//
// Handle EZSP Energy Scan result
//
int32_t EZSP_EnergyScanResult(int32_t res, const SBuffer &buf) {
uint8_t channel = buf.get8(2);
int8_t energy = buf.get8(3);
if ((channel >= USE_ZIGBEE_CHANNEL_MIN) && (channel <= USE_ZIGBEE_CHANNEL_MAX)) {
zigbee.energy[channel - USE_ZIGBEE_CHANNEL_MIN] = energy;
}
return -1;
}
//
// Handle EZSP Energy Scan complete
//
int32_t EZSP_EnergyScanComplete(int32_t res, const SBuffer &buf) {
// uint8_t channel = buf.get8(2);
uint8_t status = buf.get8(3);
if (0 == status) {
EnergyScanResults();
}
return -1;
}
//
// Dump energu scan results
//
void EnergyScanResults(void) {
Response_P(PSTR("{\"" D_JSON_ZIGBEE_SCAN "\":["));
for (uint32_t i = 0; i < USE_ZIGBEE_CHANNEL_COUNT; i++) {
int8_t energy = zigbee.energy[i];
if (i > 0) { ResponseAppend_P(PSTR(",")); }
ResponseAppend_P(PSTR("\"%d\":%d"), i + USE_ZIGBEE_CHANNEL_MIN, energy);
// display as log
static const int32_t bar_min = -87;
static const int32_t bar_max = 10;
static const uint32_t bar_count = 60;
char bar_str[bar_count + 1];
uint32_t energy_unsigned = energy + 0x80;
uint32_t bars = changeUIntScale(energy_unsigned, bar_min + 0x80, bar_max + 0x80, 0, bar_count);
for (uint32_t j = 0; j < bars; j++) { bar_str[j] = '#'; }
bar_str[bars] = 0;
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Channel %2d: %s"), i + USE_ZIGBEE_CHANNEL_MIN, bar_str);
}
ResponseAppend_P(PSTR("]}"));
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE));
}
//
// Handle a "permitJoining" incoming message
//
@ -1817,19 +1871,18 @@ int32_t EZ_Recv_Default(int32_t res, const SBuffer &buf) {
switch (ezsp_command_index) {
case EZSP_incomingMessageHandler:
return EZ_IncomingMessage(res, buf);
break;
case EZSP_trustCenterJoinHandler:
return EZ_ReceiveTCJoinHandler(res, buf);
break;
case EZSP_incomingRouteErrorHandler:
return EZ_RouteError(res, buf);
break;
case EZSP_permitJoining:
return EZ_PermitJoinRsp(res, buf);
break;
case EZSP_messageSentHandler:
return EZ_MessageSent(res, buf);
break;
case EZSP_energyScanResultHandler:
return EZSP_EnergyScanResult(res, buf);
case EZSP_scanCompleteHandler:
return EZSP_EnergyScanComplete(res, buf);
}
return -1;
}

View File

@ -570,6 +570,8 @@ void ZigbeeProcessInputEZSP(SBuffer &buf) {
case EZSP_setConcentrator: // 1000
case EZSP_networkInit: // 1700
case EZSP_stackStatusHandler: // 1900
case EZSP_startScan: // 1A00
case EZSP_scanCompleteHandler: // 1C00
case EZSP_formNetwork: // 1E00
case EZSP_permitJoining: // 2200
case EZSP_getEui64: // 2600
@ -580,6 +582,7 @@ void ZigbeeProcessInputEZSP(SBuffer &buf) {
case EZSP_sendMulticast: // 3800
case EZSP_messageSentHandler: // 3F00
case EZSP_incomingMessageHandler: // 4500
case EZSP_energyScanResultHandler: // 4800
case EZSP_setConfigurationValue: // 5300
case EZSP_setPolicy: // 5500
case 0x0059: // 5900 - supposedly removed by still happening

View File

@ -39,7 +39,7 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix
D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_UNBIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID "|"
D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_OCCUPANCY "|"
D_CMND_ZIGBEE_RESTORE "|" D_CMND_ZIGBEE_BIND_STATE "|" D_CMND_ZIGBEE_MAP "|" D_CMND_ZIGBEE_LEAVE "|"
D_CMND_ZIGBEE_CONFIG "|" D_CMND_ZIGBEE_DATA
D_CMND_ZIGBEE_CONFIG "|" D_CMND_ZIGBEE_DATA "|" D_CMND_ZIGBEE_SCAN
;
SO_SYNONYMS(kZbSynonyms,
@ -60,7 +60,7 @@ void (* const ZigbeeCommand[])(void) PROGMEM = {
&CmndZbBind, &CmndZbUnbind, &CmndZbPing, &CmndZbModelId,
&CmndZbLight, &CmndZbOccupancy,
&CmndZbRestore, &CmndZbBindState, &CmndZbMap, CmndZbLeave,
&CmndZbConfig, CmndZbData,
&CmndZbConfig, &CmndZbData, &CmndZbScan,
};
/********************************************************************************************/
@ -1311,6 +1311,33 @@ void CmndZbSave(void) {
ResponseCmndDone();
}
//
// Command `ZbScan`
// Run an energy scan
//
void CmndZbScan(void) {
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
for (uint32_t i = 0; i < USE_ZIGBEE_CHANNEL_COUNT; i++) {
zigbee.energy[i] = -0x80;
}
#ifdef USE_ZIGBEE_ZNP
ResponseCmndChar_P(PSTR("Unsupported command on ZNP"));
return;
#endif // USE_ZIGBEE_ZNP
#ifdef USE_ZIGBEE_EZSP
SBuffer buf(8);
buf.add16(EZSP_startScan);
buf.add8(0x00); // EZSP_ENERGY_SCAN
buf.add32(0x07FFF800); // standard channels 11-26
buf.add8(0x04); // duration 2 ^ 4
ZigbeeEZSPSendCmd(buf.getBuffer(), buf.len());
#endif // USE_ZIGBEE_EZSP
ResponseCmndDone();
}
// Restore a device configuration previously exported via `ZbStatus2``
// Format: