From abca6c512f77aabab68aede506ff9d304a4818e7 Mon Sep 17 00:00:00 2001 From: gene Date: Fri, 10 Jan 2025 01:36:47 +0100 Subject: [PATCH] v1.2.46 - `x10-transceiver` firmware: fix receiver initialization; - `x10-transceiver` firmware: added support for X10 security RF codes. --- examples/rf-transceiver/configuration.h | 4 +- examples/x10-transceiver/api/X10Handler.cpp | 74 ++++++--- examples/x10-transceiver/api/X10Handler.h | 4 +- examples/x10-transceiver/configuration.h | 4 +- examples/x10-transceiver/io/RFReceiver.h | 8 +- .../x10-transceiver/io/RFReceiverConfig.cpp | 2 +- examples/x10-transceiver/io/X10Message.cpp | 20 ++- examples/x10-transceiver/io/X10Message.h | 152 +++++++++++++++--- lib/homegenie-io/io/Logger.cpp | 2 +- platformio.ini | 12 +- src/net/MQTTClient.h | 14 +- src/version.h | 2 +- 12 files changed, 235 insertions(+), 63 deletions(-) diff --git a/examples/rf-transceiver/configuration.h b/examples/rf-transceiver/configuration.h index c14ae4a..097d870 100644 --- a/examples/rf-transceiver/configuration.h +++ b/examples/rf-transceiver/configuration.h @@ -1,3 +1,3 @@ -#define CONFIG_RCSwitchReceiverPin 5 -#define CONFIG_RCSwitchTransmitterPin 6 +#define CONFIG_RCSwitchReceiverPin 7 +#define CONFIG_RCSwitchTransmitterPin 5 #define CONFIG_RCSwitchRF_MODULE_ADDRESS "RF" diff --git a/examples/x10-transceiver/api/X10Handler.cpp b/examples/x10-transceiver/api/X10Handler.cpp index 41cb9e7..81adc1f 100644 --- a/examples/x10-transceiver/api/X10Handler.cpp +++ b/examples/x10-transceiver/api/X10Handler.cpp @@ -83,6 +83,9 @@ namespace Service { namespace API { } void X10Handler::init() { + if (transmitter != nullptr) { + transmitter->begin(); + } } @@ -101,9 +104,13 @@ namespace Service { namespace API { uint8_t data[commandString.length() / 2]; Utility::getBytes(commandString, data); - // only 0x20 standard type message are actually supported - receiver->disableMs(500); - transmitter->sendCommand(&data[1], sizeof(data)-1, sendRepeat); + // only 0x20 standard type message are currently supported + if (receiver != nullptr) { + receiver->disableMs(500); + } + if (transmitter != nullptr) { + transmitter->sendCommand(&data[1], sizeof(data) - 1, sendRepeat); + } responseCallback->writeAll(ApiHandlerResponseStatus::OK); return true; @@ -138,11 +145,11 @@ namespace Service { namespace API { float prevLevel = levelProperty->value.toFloat(); sendRepeat = abs((level - prevLevel) / X10_DIM_BRIGHT_STEP); if (level > prevLevel) { - x10Message.command = X10::Command::CMD_BRIGHT; + x10Message.command = X10::Command::CMD_LIGHTS_BRIGHT; levelProperty->value = String(prevLevel + (sendRepeat * X10_DIM_BRIGHT_STEP)); if (levelProperty->value.toFloat() > 1) levelProperty->value = "1"; } else if (level < prevLevel) { - x10Message.command = X10::Command::CMD_DIM; + x10Message.command = X10::Command::CMD_LIGHTS_DIM; levelProperty->value = String(prevLevel - (sendRepeat * X10_DIM_BRIGHT_STEP)); if (levelProperty->value.toFloat() < 0) levelProperty->value = "0"; } @@ -167,8 +174,12 @@ namespace Service { namespace API { if (!ignoreCommand) { X10::X10Message::encodeCommand(&x10Message, data); - receiver->disableMs(500); - transmitter->sendCommand(&data[1], sizeof(data)-1, sendRepeat); + if (receiver != nullptr) { + receiver->disableMs(500); + } + if (transmitter != nullptr) { + transmitter->sendCommand(&data[1], sizeof(data) - 1, sendRepeat); + } } responseCallback->writeAll(ApiHandlerResponseStatus::OK); @@ -220,21 +231,46 @@ namespace Service { namespace API { HomeGenie::getInstance()->getEventRouter().signalEvent(QueuedMessage(domain, CONFIG_X10RF_MODULE_ADDRESS, IOEventPaths::Receiver_RawData, rawDataString, nullptr, IOEventDataType::Undefined)); - if (type == 0x20) { // 0x20 = standard, 0x29 = security + // 0x20 = standard, 0x29 = security + switch (type) { + + case 0x20: { + + // Convert enums to string + String houseCode(house_code_to_char(decodedMessage->houseCode)); + String unitCode(unit_code_to_int(decodedMessage->unitCode)); + if (unitCode == "0") unitCode = ""; + const char* command = cmd_code_to_str(decodedMessage->command); + String commandString = (houseCode + unitCode + " " + command); + + Logger::trace(":%s %s", HOMEGENIEMINI_NS_PREFIX, commandString.c_str()); + + receiverCommand->setValue(commandString.c_str()); + HomeGenie::getInstance()->getEventRouter().signalEvent( + QueuedMessage(domain, CONFIG_X10RF_MODULE_ADDRESS, IOEventPaths::Receiver_Command, + commandString, + nullptr, IOEventDataType::Undefined)); + + } break; + + case 0x29: { + + int commandCode = (b2 << 8) + b3; + const char* command = cmd_code_to_str((Command)commandCode); + String commandString = (command); + String subtype = Utility::byteToHex((b0)) + Utility::byteToHex((b1)); + subtype.toUpperCase(); + + Logger::trace(":%s S-%s %s", HOMEGENIEMINI_NS_PREFIX, subtype.c_str(), commandString.c_str()); - // Convert enums to string - String houseCode(house_code_to_char(decodedMessage->houseCode)); - String unitCode(unit_code_to_int(decodedMessage->unitCode)); - const char* command = cmd_code_to_str(decodedMessage->command); - String commandString = (houseCode + unitCode + " " + command); + receiverCommand->setValue(commandString.c_str()); + HomeGenie::getInstance()->getEventRouter().signalEvent( + QueuedMessage(domain, CONFIG_X10RF_MODULE_ADDRESS, IOEventPaths::Receiver_Command, + commandString, + nullptr, IOEventDataType::Undefined)); - Logger::trace(":%s %s", HOMEGENIEMINI_NS_PREFIX, commandString.c_str()); + } break; - receiverCommand->setValue(commandString.c_str()); - HomeGenie::getInstance()->getEventRouter().signalEvent( - QueuedMessage(domain, CONFIG_X10RF_MODULE_ADDRESS, IOEventPaths::Receiver_Command, - commandString, - nullptr, IOEventDataType::Undefined)); } /* QueuedMessage m = QueuedMessage(domain, houseCode + unitCode, (IOEventPaths::Status_Level), ""); diff --git a/examples/x10-transceiver/api/X10Handler.h b/examples/x10-transceiver/api/X10Handler.h index c8ca65d..5b7938b 100644 --- a/examples/x10-transceiver/api/X10Handler.h +++ b/examples/x10-transceiver/api/X10Handler.h @@ -50,8 +50,8 @@ namespace Service { namespace API { Module* rfModule; ModuleParameter* receiverRawData; ModuleParameter* receiverCommand; - RFTransmitter* transmitter{}; - RFReceiver* receiver{}; + RFTransmitter* transmitter = nullptr; + RFReceiver* receiver = nullptr; public: X10Handler(); void setReceiver(RFReceiver* receiver); diff --git a/examples/x10-transceiver/configuration.h b/examples/x10-transceiver/configuration.h index 6c30aa9..99ed716 100644 --- a/examples/x10-transceiver/configuration.h +++ b/examples/x10-transceiver/configuration.h @@ -1,3 +1,3 @@ -#define CONFIG_X10RFReceiverPin 5 -#define CONFIG_X10RFTransmitterPin 6 +#define CONFIG_X10RFReceiverPin 7 +#define CONFIG_X10RFTransmitterPin 5 #define CONFIG_X10RF_MODULE_ADDRESS "RF" diff --git a/examples/x10-transceiver/io/RFReceiver.h b/examples/x10-transceiver/io/RFReceiver.h index 5f5b209..59eae1a 100644 --- a/examples/x10-transceiver/io/RFReceiver.h +++ b/examples/x10-transceiver/io/RFReceiver.h @@ -54,13 +54,13 @@ namespace IO { namespace X10 { // 32-bit RF message decoding volatile uint8_t messageType = 0x00; volatile uint8_t byteBuffer[4]; - volatile uint32_t riseUs; - volatile int8_t receivedCount; - volatile uint32_t receiveBuffer; + volatile uint32_t riseUs = 0; + volatile int8_t receivedCount = 0; + volatile uint32_t receiveBuffer = 0; // event data uint8_t eventData[5]; bool eventReady = false; - uint32_t disabledToMs; + uint32_t disabledToMs = 0; }; }} // ns diff --git a/examples/x10-transceiver/io/RFReceiverConfig.cpp b/examples/x10-transceiver/io/RFReceiverConfig.cpp index f73be3d..c93f89c 100644 --- a/examples/x10-transceiver/io/RFReceiverConfig.cpp +++ b/examples/x10-transceiver/io/RFReceiverConfig.cpp @@ -47,7 +47,7 @@ namespace IO { namespace X10 { } RFReceiverConfig::RFReceiverConfig(uint8_t pin) : RFReceiverConfig() { - this->pin = pin; + this->pin = this->interrupt = pin; } RFReceiverConfig::RFReceiverConfig( uint8_t interrupt, uint8_t pin diff --git a/examples/x10-transceiver/io/X10Message.cpp b/examples/x10-transceiver/io/X10Message.cpp index 308e285..125b0a3 100644 --- a/examples/x10-transceiver/io/X10Message.cpp +++ b/examples/x10-transceiver/io/X10Message.cpp @@ -108,9 +108,25 @@ namespace IO { decodedMessage->houseCode = (enum HouseCode) encodedMessage[3]; decodedMessage->unitCode = UNIT_1; } else { - decodedMessage->unitCode = (enum UnitCode) (((encodedMessage[1] & 0xF) << 8) | (encodedMessage[3] & ~CMD_OFF)); + decodedMessage->unitCode = UnitCode::UNIT_NONE; decodedMessage->houseCode = (enum HouseCode) (encodedMessage[1] & 0xF0); - decodedMessage->command = (enum Command) (encodedMessage[3] & CMD_OFF); + switch (encodedMessage[3]) { + case CMD_LIGHTS_ALL_OFF: + decodedMessage->command = CMD_LIGHTS_ALL_OFF; + break; + case CMD_LIGHTS_ALL_ON: + decodedMessage->command = CMD_LIGHTS_ALL_ON; + break; + case CMD_LIGHTS_DIM: + decodedMessage->command = CMD_LIGHTS_DIM; + break; + case CMD_LIGHTS_BRIGHT: + decodedMessage->command = CMD_LIGHTS_BRIGHT; + break; + default: + decodedMessage->unitCode = (enum UnitCode) (((encodedMessage[1] & 0xF) << 8) | (encodedMessage[3] & ~CMD_OFF)); + decodedMessage->command = (enum Command) (encodedMessage[3] & CMD_OFF); + } } return 0; diff --git a/examples/x10-transceiver/io/X10Message.h b/examples/x10-transceiver/io/X10Message.h index ce2a40a..81e885e 100644 --- a/examples/x10-transceiver/io/X10Message.h +++ b/examples/x10-transceiver/io/X10Message.h @@ -188,7 +188,8 @@ namespace IO { UNIT_1 = 0x000, UNIT_2 = 0x010, UNIT_3 = 0x008, UNIT_4 = 0x018, UNIT_5 = 0x040, UNIT_6 = 0x050, UNIT_7 = 0x048, UNIT_8 = 0x058, UNIT_9 = 0x400, UNIT_10 = 0x410, UNIT_11 = 0x408, UNIT_12 = 0x418, - UNIT_13 = 0x440, UNIT_14 = 0x450, UNIT_15 = 0x448, UNIT_16 = 0x458 + UNIT_13 = 0x440, UNIT_14 = 0x450, UNIT_15 = 0x448, UNIT_16 = 0x458, + UNIT_NONE = 0xFFF }; static enum UnitCode UnitCodeLut[(UNIT_MAX - UNIT_MIN) + 1] = { @@ -197,6 +198,7 @@ namespace IO { }; static int unit_code_to_int(enum UnitCode code) { + if (code == UnitCode::UNIT_NONE) return 0; int unit = ((code >> 7) & 0x8); unit |= ((code >> 4) & 0x4); unit |= ((code >> 2) & 0x2); @@ -211,13 +213,29 @@ namespace IO { /* Standard 5-byte commands: */ CMD_ON = 0x00, /* Turn on unitCode */ CMD_OFF = 0x20, /* Turn off unitCode */ - CMD_DIM = 0x98, /* Dim lamp */ - CMD_BRIGHT = 0x88, /* Brighten lamp */ + /* Lights */ + CMD_LIGHTS_ALL_OFF = 0x80, /* Turn off unitCode */ + CMD_LIGHTS_ALL_ON = 0x90, /* Turn off unitCode */ + CMD_LIGHTS_DIM = 0x98, /* Dim lamp */ + CMD_LIGHTS_BRIGHT = 0x88, /* Brighten lamp */ /* Pan'n'Tilt 4-byte commands: */ - CMD_UP = 0x762, - CMD_RIGHT = 0x661, - CMD_DOWN = 0x863, - CMD_LEFT = 0x560, + CMD_MOVE_UP = 0x762, + CMD_MOVE_RIGHT = 0x661, + CMD_MOVE_DOWN = 0x863, + CMD_MOVE_LEFT = 0x560, + /* Security codes */ + CMD_SEC_PANIC = 0x26D9, + CMD_SEC_ARM_HOME = 0x0EF1, + CMD_SEC_ARM_AWAY = 0x06F9, + CMD_SEC_DISARM = 0x8679, + CMD_SEC_LIGHT_OFF = 0xC639, + CMD_SEC_LIGHT_ON = 0x46B9, + CMD_SEC_MOTION_DETECTED = 0x0CF3, + CMD_SEC_MOTION_IDLE = 0x8C73, + CMD_SEC_MOTION_TAMPERED = 0x4CB3, + CMD_SEC_DOOR_OPEN = 0x04FB, + CMD_SEC_DOOR_CLOSED = 0x847B, + CMD_SEC_DOOR_TAMPERED = 0x44BB, /* Error flag */ CMD_INVALID = 0xFF }; @@ -228,18 +246,46 @@ namespace IO { return CMD_ON; case '-': return CMD_OFF; + case '.': + return CMD_LIGHTS_ALL_OFF; + case '*': + return CMD_LIGHTS_ALL_ON; + case '!': + return CMD_SEC_PANIC; + case '#': + return CMD_SEC_ARM_HOME; + case '%': + return CMD_SEC_ARM_AWAY; + case '=': + return CMD_SEC_DISARM; + case '/': + return CMD_SEC_LIGHT_OFF; + case 'x': + return CMD_SEC_LIGHT_ON; + case '$': + return CMD_SEC_MOTION_DETECTED; + case ':': + return CMD_SEC_MOTION_IDLE; + case '^': + return CMD_SEC_MOTION_TAMPERED; + case '_': + return CMD_SEC_DOOR_OPEN; + case 'H': + return CMD_SEC_DOOR_CLOSED; + case 'X': + return CMD_SEC_DOOR_TAMPERED; case 'u': - return CMD_UP; + return CMD_MOVE_UP; case 'd': - return CMD_DOWN; + return CMD_MOVE_DOWN; case 'l': - return CMD_LEFT; + return CMD_MOVE_LEFT; case 'r': - return CMD_RIGHT; + return CMD_MOVE_RIGHT; case 'b': - return CMD_BRIGHT; + return CMD_LIGHTS_BRIGHT; case 's': - return CMD_DIM; + return CMD_LIGHTS_DIM; default: //error("%s: Invalid command code: %c\n", __FUNCTION__, c); return CMD_INVALID; @@ -252,17 +298,45 @@ namespace IO { return '+'; case CMD_OFF: return '-'; - case CMD_DIM: + case CMD_LIGHTS_ALL_OFF: + return '.'; + case CMD_LIGHTS_ALL_ON: + return '*'; + case CMD_LIGHTS_DIM: return 's'; - case CMD_BRIGHT: + case CMD_LIGHTS_BRIGHT: return 'b'; - case CMD_UP: + case CMD_SEC_PANIC: + return '!'; + case CMD_SEC_ARM_HOME: + return '#'; + case CMD_SEC_ARM_AWAY: + return '%'; + case CMD_SEC_DISARM: + return '='; + case CMD_SEC_LIGHT_OFF: + return '/'; + case CMD_SEC_LIGHT_ON: + return 'x'; + case CMD_SEC_MOTION_DETECTED: + return '$'; + case CMD_SEC_MOTION_IDLE: + return ':'; + case CMD_SEC_MOTION_TAMPERED: + return '^'; + case CMD_SEC_DOOR_OPEN: + return '_'; + case CMD_SEC_DOOR_CLOSED: + return 'H'; + case CMD_SEC_DOOR_TAMPERED: + return 'X'; + case CMD_MOVE_UP: return 'u'; - case CMD_RIGHT: + case CMD_MOVE_RIGHT: return 'r'; - case CMD_DOWN: + case CMD_MOVE_DOWN: return 'd'; - case CMD_LEFT: + case CMD_MOVE_LEFT: return 'l'; default: return '?'; @@ -275,17 +349,45 @@ namespace IO { return "on"; case CMD_OFF: return "off"; - case CMD_DIM: + case CMD_LIGHTS_ALL_OFF: + return "all_off"; + case CMD_LIGHTS_ALL_ON: + return "all_on"; + case CMD_LIGHTS_DIM: return "dim"; - case CMD_BRIGHT: + case CMD_LIGHTS_BRIGHT: return "brighten"; - case CMD_UP: + case CMD_SEC_PANIC: + return "panic"; + case CMD_SEC_ARM_HOME: + return "arm_home"; + case CMD_SEC_ARM_AWAY: + return "arm_away"; + case CMD_SEC_DISARM: + return "disarm"; + case CMD_SEC_LIGHT_OFF: + return "lights_off"; + case CMD_SEC_LIGHT_ON: + return "lights_on"; + case CMD_SEC_MOTION_DETECTED: + return "motion_detected"; + case CMD_SEC_MOTION_IDLE: + return "motion_idle"; + case CMD_SEC_MOTION_TAMPERED: + return "motion_tampered"; + case CMD_SEC_DOOR_OPEN: + return "door_open"; + case CMD_SEC_DOOR_CLOSED: + return "door_closed"; + case CMD_SEC_DOOR_TAMPERED: + return "door_tampered"; + case CMD_MOVE_UP: return "up"; - case CMD_RIGHT: + case CMD_MOVE_RIGHT: return "right"; - case CMD_DOWN: + case CMD_MOVE_DOWN: return "down"; - case CMD_LEFT: + case CMD_MOVE_LEFT: return "left"; default: return "invalid"; diff --git a/lib/homegenie-io/io/Logger.cpp b/lib/homegenie-io/io/Logger.cpp index 588bf7e..73b060c 100644 --- a/lib/homegenie-io/io/Logger.cpp +++ b/lib/homegenie-io/io/Logger.cpp @@ -103,7 +103,7 @@ namespace IO { auto ms = millis() % 1000; auto tt = time(0); auto timeInfo = localtime(&tt); - strftime (buffer, 80, "%FT%T", timeInfo); + strftime(buffer, 80, "%FT%T", timeInfo); sprintf(buffer, "%s.%03dZ", buffer, (int)ms); Serial.printf("[%s] ", buffer); } diff --git a/platformio.ini b/platformio.ini index ed3a4af..abe84f0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -25,7 +25,7 @@ platform = espressif32@6.9.0 # # UNOFFICIAL Espressif32 and Arduino 3.x # should support also latest ESP32 boards (not verified) -#platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.07/platform-espressif32.zip +#platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.11/platform-espressif32.zip # build_src_filter = -<*> + build_flags = -D CRON_USE_LOCAL_TIME -D CRON_DISABLE_YEARS -Os -D BUILD_ENV_NAME=\"$PIOENV\" @@ -241,6 +241,16 @@ lib_deps = ${env:rf-transceiver.lib_deps} lib_ignore = LovyanGFX +[env:rf-transceiver-s3] +board = esp32-s3-fh4r2 +build_flags = ${env.build_flags} -I examples -I src -D ESP32_S3 -D DISABLE_UI + -D BOARD_HAS_PSRAM -D ARDUINO_USB_MODE=1 -D ARDUINO_USB_CDC_ON_BOOT=1 + -D BOARD_HAS_RGB_LED +build_src_filter = + - + +lib_deps = ${env:rf-transceiver.lib_deps} +lib_ignore = + LovyanGFX + [env:ir-transceiver] build_flags = ${env.build_flags} -I examples -I src -D DISABLE_UI diff --git a/src/net/MQTTClient.h b/src/net/MQTTClient.h index 9fb0bec..c62248f 100644 --- a/src/net/MQTTClient.h +++ b/src/net/MQTTClient.h @@ -115,12 +115,17 @@ namespace Net { uuid.seed(seed1, seed2); uuid.generate(); clientId = uuid.toCharArray(); - +#if ESP_IDF_VERSION_MAJOR >= 5 + mqtt_cfg.credentials.client_id = clientId.c_str(); + mqtt_cfg.broker.address.uri = brokerUrl.c_str(); + mqtt_cfg.credentials.username = username.c_str(); + mqtt_cfg.credentials.authentication.password = password.c_str(); +#else mqtt_cfg.client_id = clientId.c_str(); mqtt_cfg.uri = brokerUrl.c_str(); mqtt_cfg.username = username.c_str(); mqtt_cfg.password = password.c_str(); - +#endif stopRequested = true; } @@ -227,8 +232,11 @@ namespace Net { bool stopRequested = false; bool clientStarted = false; esp_mqtt_client_handle_t client = nullptr; +#if ESP_IDF_VERSION_MAJOR >= 5 + esp_mqtt_client_config_t mqtt_cfg {}; +#else esp_mqtt_client_config_t mqtt_cfg { .uri = "" }; - +#endif static void xorFilter(String* payload, String* clientKey = 0) { if (!clientKey->isEmpty()) { for (int c = 0; c < payload->length(); c++) { diff --git a/src/version.h b/src/version.h index 9b77921..8fc6378 100644 --- a/src/version.h +++ b/src/version.h @@ -29,7 +29,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 2 -#define VERSION_PATCH 45 +#define VERSION_PATCH 46 #define STRING_VALUE(...) STRING_VALUE__(__VA_ARGS__) #define STRING_VALUE__(...) #__VA_ARGS__