From 7dbcb7b3d91c3d3b63e785d5e72d302142737397 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 23 Sep 2024 14:56:18 +0200 Subject: [PATCH] Implement Memory Commands --- components/tc_bus/__init__.py | 15 +++--- components/tc_bus/protocol.cpp | 93 ++++++++++++++++++++++++++-------- components/tc_bus/protocol.h | 8 +-- components/tc_bus/tc_bus.cpp | 77 +++++++++++++--------------- components/tc_bus/tc_bus.h | 12 ++--- 5 files changed, 126 insertions(+), 79 deletions(-) diff --git a/components/tc_bus/__init__.py b/components/tc_bus/__init__.py index bb9e92b..ce1e048 100644 --- a/components/tc_bus/__init__.py +++ b/components/tc_bus/__init__.py @@ -18,8 +18,8 @@ "TCBusProgrammingModeAction", automation.Action ) -TCBusReadEEPROMAction = tc_bus_ns.class_( - "TCBusReadEEPROMAction", automation.Action +TCBusReadMemoryAction = tc_bus_ns.class_( + "TCBusReadMemoryAction", automation.Action ) ReceivedCommandTrigger = tc_bus_ns.class_("ReceivedCommandTrigger", automation.Trigger.template()) @@ -50,8 +50,9 @@ "found_device": CommandType.COMMAND_TYPE_FOUND_DEVICE, "found_device_subsystem": CommandType.COMMAND_TYPE_FOUND_DEVICE_SUBSYSTEM, "programming_mode": CommandType.COMMAND_TYPE_PROGRAMMING_MODE, - "read_eeprom_block": CommandType.COMMAND_TYPE_READ_EEPROM_BLOCK, - "select_eeprom_page": CommandType.COMMAND_TYPE_SELECT_EEPROM_PAGE, + "read_memory_block": CommandType.COMMAND_TYPE_READ_MEMORY_BLOCK, + "select_memory_page": CommandType.COMMAND_TYPE_SELECT_MEMORY_PAGE, + "write_memory": CommandType.COMMAND_TYPE_WRITE_MEMORY, } CONF_TC_ID = "tc_bus" @@ -221,8 +222,8 @@ async def tc_bus_set_programming_mode_to_code(config, action_id, template_args, @automation.register_action( - "tc_bus.read_eeprom", - TCBusReadEEPROMAction, + "tc_bus.read_memory", + TCBusReadMemoryAction, automation.maybe_simple_id( { cv.GenerateID(): cv.use_id(TCBus), @@ -230,7 +231,7 @@ async def tc_bus_set_programming_mode_to_code(config, action_id, template_args, } ), ) -async def tc_bus_read_eeprom_to_code(config, action_id, template_args, args): +async def tc_bus_read_memory_to_code(config, action_id, template_args, args): parent = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_args, parent) diff --git a/components/tc_bus/protocol.cpp b/components/tc_bus/protocol.cpp index deb38b9..2529955 100644 --- a/components/tc_bus/protocol.cpp +++ b/components/tc_bus/protocol.cpp @@ -6,7 +6,7 @@ namespace esphome { namespace tc_bus { - uint32_t buildCommand(CommandType type, uint8_t address, uint32_t serial_number) + uint32_t buildCommand(CommandType type, uint8_t address, uint32_t payload = 0, uint32_t serial_number = 0) { uint32_t command = 0; @@ -77,37 +77,54 @@ namespace esphome case COMMAND_TYPE_LIGHT: command |= (1 << 12); // 1 command |= (2 << 8); // 2 - command |= (address & 0xFF); // 00 break; case COMMAND_TYPE_CONTROL_FUNCTION: command |= (6 << 28); // 6 command |= ((serial_number & 0xFFFFF) << 8); // C30BA - command |= (address & 0xFF); // 08 + command |= (payload & 0xFF); // 08 break; case COMMAND_TYPE_RESET: command |= (5 << 12); // 5 - command |= (1 << 8); // 10 - command |= (address & 0xFF); // 0 + command |= (1 << 8); // 100 break; case COMMAND_TYPE_SELECT_DEVICE_GROUP: command |= (5 << 12); // 5 command |= (8 << 8); // 80 - command |= (address & 0xFF); // 0 + command |= (payload & 0xFF); // 0 break; case COMMAND_TYPE_SELECT_DEVICE_GROUP_RESET: command |= (5 << 12); // 5 command |= (9 << 8); // 90 - command |= (address & 0xFF); // 0 + command |= (payload & 0xFF); // 0 break; case COMMAND_TYPE_SEARCH_DEVICES: command |= (5 << 12); // 5 command |= (2 << 8); // 20 - command |= (address & 0xFF); // 0 + break; + + case COMMAND_TYPE_PROGRAMMING_MODE: + command |= (5 << 12); // 5 + command |= (0 << 8); // 0 + command |= (4 << 4); // 4 + command |= (payload & 0xF); // 0 / 1 + break; + + case COMMAND_TYPE_READ_MEMORY_BLOCK: + command |= (8 << 12); // 8 + command |= (4 << 8); // 4 + command |= ((address * 4) & 0xFF); // 00 + break; + + case COMMAND_TYPE_WRITE_MEMORY: + command |= (8 << 28); // 8 + command |= (2 << 24); // 2 + command |= ((address * 4) & 0xFF) << 16; // start address + command |= payload & 0xFFFF; // ABCD payload break; default: @@ -122,7 +139,8 @@ namespace esphome CommandData data{}; data.command = command; data.type = COMMAND_TYPE_UNKNOWN; - data.address = command & 0xF; + data.address = 0; + data.payload = 0; // Convert to HEX and determine length data.command_hex = str_upper_case(format_hex(command)); @@ -136,22 +154,30 @@ namespace esphome { case 0: data.type = (command & (1 << 7)) ? COMMAND_TYPE_DOOR_CALL : COMMAND_TYPE_INTERNAL_CALL; + data.address = command & 0xF; break; case 1: if ((command & 0xFF) == 0x41) { data.type = COMMAND_TYPE_FLOOR_CALL; - data.address = 0; } else if (command & (1 << 7)) { data.type = COMMAND_TYPE_OPEN_DOOR; + data.address = command & 0xF; } break; case 3: data.type = (command & (1 << 7)) ? COMMAND_TYPE_START_TALKING_IA : COMMAND_TYPE_START_TALKING_DOOR_STATION; + data.address = command & 0xF; + + // Door Readiness + if(data.type == COMMAND_TYPE_START_TALKING_DOOR_STATION) + { + data.payload = (command & (1 << 8)) != 0; + } break; case 5: @@ -159,10 +185,12 @@ namespace esphome { case 1: data.type = COMMAND_TYPE_FOUND_DEVICE; + data.address = command & 0xF; break; case 4: data.type = COMMAND_TYPE_FOUND_DEVICE_SUBSYSTEM; + data.address = command & 0xF; break; case 8: @@ -186,20 +214,24 @@ namespace esphome case 6: data.type = COMMAND_TYPE_CONTROL_FUNCTION; - data.address = (command & 0xFF); // Function number + data.payload = (command & 0xFF); // Function number break; case 8: - // 81 0 00000 - // select eeprom page of serial number - switch ((command >> 24) & 0xF) { case 1: - data.type = COMMAND_TYPE_SELECT_EEPROM_PAGE; + case 9: + data.type = COMMAND_TYPE_SELECT_MEMORY_PAGE; data.address = (command >> 20) & 0xF; data.serial_number = command & 0xFFFFF; break; + + case 2: + data.type = COMMAND_TYPE_WRITE_MEMORY; + data.address = (command >> 16) & 0xFF; + data.payload = command & 0xFFFF; + break; } break; } @@ -213,9 +245,14 @@ namespace esphome if (first == 1) { if (second == 1) + { data.type = COMMAND_TYPE_OPEN_DOOR; + data.address = command & 0xF; + } else if (second == 2) + { data.type = COMMAND_TYPE_LIGHT; + } } else if (first == 2) { @@ -234,36 +271,46 @@ namespace esphome data.type = COMMAND_TYPE_INITIALIZE_DOOR_STATION; break; } + + data.address = command & 0xF; } else if (first == 3) { data.type = (command & (1 << 7)) ? COMMAND_TYPE_STOP_TALKING_IA : COMMAND_TYPE_STOP_TALKING_DOOR_STATION; + data.address = command & 0xF; } else if (first == 5) { switch(second) { case 0: - if (((command >> 6) & 0xFF) == 0x40 || ((command >> 6) & 0xFF) == 0x41) + switch((command >> 4) & 0xF) { - data.type = COMMAND_TYPE_PROGRAMMING_MODE; + case 4: + data.type = COMMAND_TYPE_PROGRAMMING_MODE; + data.payload = command & 0xF; + break; } break; case 1: data.type = COMMAND_TYPE_RESET; + data.address = command & 0xF; break; case 2: data.type = COMMAND_TYPE_SEARCH_DEVICES; + data.payload = command & 0xF; break; case 8: data.type = COMMAND_TYPE_SELECT_DEVICE_GROUP; + data.payload = command & 0xF; break; case 9: data.type = COMMAND_TYPE_SELECT_DEVICE_GROUP_RESET; + data.payload = command & 0xF; break; } } @@ -271,8 +318,13 @@ namespace esphome { switch(second) { + case 1: + data.type = COMMAND_TYPE_SELECT_MEMORY_PAGE; + data.address = (command & 0xFF); + break; + case 4: - data.type = COMMAND_TYPE_READ_EEPROM_BLOCK; + data.type = COMMAND_TYPE_READ_MEMORY_BLOCK; data.address = (command & 0xFF); break; } @@ -309,8 +361,9 @@ namespace esphome case COMMAND_TYPE_FOUND_DEVICE: return "FOUND_DEVICE"; case COMMAND_TYPE_FOUND_DEVICE_SUBSYSTEM: return "FOUND_DEVICE_SUBSYSTEM"; case COMMAND_TYPE_PROGRAMMING_MODE: return "PROGRAMMING_MODE"; - case COMMAND_TYPE_READ_EEPROM_BLOCK: return "READ_EEPROM_BLOCK"; - case COMMAND_TYPE_SELECT_EEPROM_PAGE: return "SELECT_EEPROM_PAGE"; + case COMMAND_TYPE_READ_MEMORY_BLOCK: return "READ_MEMORY_BLOCK"; + case COMMAND_TYPE_SELECT_MEMORY_PAGE: return "SELECT_MEMORY_PAGE"; + case COMMAND_TYPE_WRITE_MEMORY: return "WRITE_MEMORY"; default: return "UNKNOWN"; } } diff --git a/components/tc_bus/protocol.h b/components/tc_bus/protocol.h index 0ffb44c..183a6ab 100644 --- a/components/tc_bus/protocol.h +++ b/components/tc_bus/protocol.h @@ -30,8 +30,9 @@ namespace esphome COMMAND_TYPE_FOUND_DEVICE, COMMAND_TYPE_FOUND_DEVICE_SUBSYSTEM, COMMAND_TYPE_PROGRAMMING_MODE, - COMMAND_TYPE_READ_EEPROM_BLOCK, - COMMAND_TYPE_SELECT_EEPROM_PAGE + COMMAND_TYPE_READ_MEMORY_BLOCK, + COMMAND_TYPE_SELECT_MEMORY_PAGE, + COMMAND_TYPE_WRITE_MEMORY }; struct CommandData { @@ -40,10 +41,11 @@ namespace esphome CommandType type; uint8_t address; uint32_t serial_number; + uint32_t payload; uint8_t length; }; - uint32_t buildCommand(CommandType type, uint8_t address, uint32_t serial_number); + uint32_t buildCommand(CommandType type, uint8_t address, uint32_t payload = 0, uint32_t serial_number = 0); CommandData parseCommand(uint32_t command); const char* command_type_to_string(CommandType type); diff --git a/components/tc_bus/tc_bus.cpp b/components/tc_bus/tc_bus.cpp index 6d31ca4..78ee2f3 100644 --- a/components/tc_bus/tc_bus.cpp +++ b/components/tc_bus/tc_bus.cpp @@ -152,33 +152,34 @@ namespace esphome if(s.s_cmdReady) { - if(reading_eeprom_) + if(reading_memory_) { - ESP_LOGD(TAG, "Received 4 EEPROM Blocks starting at: %i", (reading_eeprom_count_ * 4)); + ESP_LOGD(TAG, "Received 4 memory Blocks starting at: %i", (reading_memory_count_ * 4)); - // Save Data to EEPROM Store - eeprom_buffer_.push_back((s.s_cmd >> 24) & 0xFF); - eeprom_buffer_.push_back((s.s_cmd >> 16) & 0xFF); - eeprom_buffer_.push_back((s.s_cmd >> 8) & 0xFF); - eeprom_buffer_.push_back(s.s_cmd & 0xFF); + // Save Data to memory Store + memory_buffer_.push_back((s.s_cmd >> 24) & 0xFF); + memory_buffer_.push_back((s.s_cmd >> 16) & 0xFF); + memory_buffer_.push_back((s.s_cmd >> 8) & 0xFF); + memory_buffer_.push_back(s.s_cmd & 0xFF); // Next 4 Data Blocks - reading_eeprom_count_++; + reading_memory_count_++; - if(reading_eeprom_count_ == 12) + if(reading_memory_count_ == 12) { // Turn off - reading_eeprom_ = false; + reading_memory_ = false; - std::string hexString = str_upper_case(format_hex(eeprom_buffer_)); - ESP_LOGD(TAG, "EEPROM Data: %s", hexString.c_str()); + std::string hexString = str_upper_case(format_hex(memory_buffer_)); + ESP_LOGD(TAG, "memory Data: %s", hexString.c_str()); } else { delay(50); // Request Data Blocks - request_eeprom_blocks(reading_eeprom_count_); + ESP_LOGD(TAG, "Read 4 memory addresses starting at %i", reading_memory_count_); + send_command(COMMAND_TYPE_READ_MEMORY_BLOCK, reading_memory_count_); } } else @@ -353,11 +354,11 @@ namespace esphome // Parse Command CommandData cmd_data = parseCommand(command); - ESP_LOGD(TAG, "[Parsed] Type: %s, Address: %i, Serial: %i", command_type_to_string(cmd_data.type), cmd_data.address, cmd_data.serial_number); + ESP_LOGD(TAG, "[Parsed] Type: %s, Address: %i, Payload: %x, Serial: %i", command_type_to_string(cmd_data.type), cmd_data.address, cmd_data.payload, cmd_data.serial_number); // Update Door Readiness Status if (cmd_data.type == COMMAND_TYPE_START_TALKING_DOOR_STATION) { - bool door_readiness_state = (command & (1 << 8)) != 0; + bool door_readiness_state = cmd_data.payload == 1; ESP_LOGD(TAG, "Door readiness: %s", YESNO(door_readiness_state)); if (this->door_readiness_ != nullptr) { this->door_readiness_->publish_state(door_readiness_state); @@ -368,8 +369,8 @@ namespace esphome this->door_readiness_->publish_state(false); } } else if (cmd_data.type == COMMAND_TYPE_PROGRAMMING_MODE) { - ESP_LOGD(TAG, "Programming Mode: %s", YESNO(cmd_data.address == 1)); - this->programming_mode_ = cmd_data.address == 1; + ESP_LOGD(TAG, "Programming Mode: %s", YESNO(cmd_data.payload == 1)); + this->programming_mode_ = cmd_data.payload == 1; } // Publish Command to Last Bus Command Sensor @@ -446,9 +447,9 @@ namespace esphome } } - void TCBusComponent::send_command_generate(CommandType type, uint8_t address, uint32_t serial_number) + void TCBusComponent::send_command(CommandType type, uint8_t address = 0, uint32_t payload = 0, uint32_t serial_number = 0) { - ESP_LOGD(TAG, "Generating command: Type: %s, Address: %i, Serial number: %i", command_type_to_string(type), address, serial_number); + ESP_LOGV(TAG, "Generating command: Type: %s, Address: %i, Payload: %X, Serial number: %i", command_type_to_string(type), address, payload, serial_number); // Get current TCS Serial Number uint32_t tcs_serial = this->serial_number_; @@ -461,11 +462,11 @@ namespace esphome if(serial_number == 0) { - ESP_LOGD(TAG, "Serial Number is 0, use intercom serial number: %i", tcs_serial); + ESP_LOGV(TAG, "Serial Number is 0, use intercom serial number: %i", tcs_serial); serial_number = tcs_serial; } - uint32_t command = buildCommand(type, address, serial_number); + uint32_t command = buildCommand(type, address, payload, serial_number); if(command == 0) { ESP_LOGW(TAG, "Sending commands of type %s is not supported!", command_type_to_string(type)); @@ -476,7 +477,6 @@ namespace esphome } } - void TCBusComponent::send_command(uint32_t command) { ESP_LOGD(TAG, "Sending command %08X", command); @@ -544,10 +544,10 @@ namespace esphome void TCBusComponent::set_programming_mode(bool enabled) { - send_command(enabled ? 0x5041 : 0x5040); + send_command(COMMAND_TYPE_PROGRAMMING_MODE, 0, enabled ? 1 : 0); } - void TCBusComponent::read_eeprom(uint32_t serial_number) + void TCBusComponent::read_memory(uint32_t serial_number) { if(serial_number == 0) { @@ -560,31 +560,22 @@ namespace esphome } } - eeprom_buffer_.clear(); - reading_eeprom_count_ = 0; - reading_eeprom_ = false; + memory_buffer_.clear(); + reading_memory_count_ = 0; + reading_memory_ = false; ESP_LOGD(TAG, "Select Indoor Stations"); - send_command(0x5800); //select indoor stations + send_command(COMMAND_TYPE_SELECT_DEVICE_GROUP, 0, 0); // payload 0 = indoor stations delay(50); - ESP_LOGD(TAG, "Select Serial Number: %i", serial_number); - uint32_t select_cmd = 0x81000000; // Select Page 0 of SN - select_cmd |= ((serial_number & 0xFFFFF) << 0); // C30BA - send_command(select_cmd); // select serial number + ESP_LOGD(TAG, "Select Memory Page %i of Serial Number %i", 0, serial_number); + send_command(COMMAND_TYPE_SELECT_MEMORY_PAGE, 0, 0, serial_number); delay(50); - reading_eeprom_ = true; - reading_eeprom_count_ = 0; - request_eeprom_blocks(reading_eeprom_count_); - } - - void TCBusComponent::request_eeprom_blocks(uint8_t start_address) - { - ESP_LOGD(TAG, "Request 4 EEPROM Bytes starting at: %i", (start_address * 4)); - - uint32_t cmd = 0x8400 | (start_address * 4); - send_command(cmd); + reading_memory_ = true; + reading_memory_count_ = 0; + ESP_LOGD(TAG, "Read 4 memory addresses starting at %i", reading_memory_count_); + send_command(COMMAND_TYPE_READ_MEMORY_BLOCK, reading_memory_count_); } } // namespace tc_bus diff --git a/components/tc_bus/tc_bus.h b/components/tc_bus/tc_bus.h index 92f59af..9c640bd 100644 --- a/components/tc_bus/tc_bus.h +++ b/components/tc_bus/tc_bus.h @@ -79,10 +79,10 @@ namespace esphome void set_door_readiness_sensor(binary_sensor::BinarySensor *door_readiness) { this->door_readiness_ = door_readiness; } void send_command(uint32_t command); - void send_command_generate(CommandType type, uint8_t address, uint32_t serial_number); + void send_command(CommandType type, uint8_t address = 0, uint32_t payload = 0, uint32_t serial_number = 0); void set_programming_mode(bool enabled); - void read_eeprom(uint32_t serial_number); - void request_eeprom_blocks(uint8_t start_address); + void read_memory(uint32_t serial_number); + void request_memory_blocks(uint8_t start_address); void publish_command(uint32_t command, bool fire_events); @@ -109,9 +109,9 @@ namespace esphome bool programming_mode_ = false; - bool reading_eeprom_ = false; - uint8_t reading_eeprom_count_ = 0; - std::vector eeprom_buffer_; + bool reading_memory_ = false; + uint8_t reading_memory_count_ = 0; + std::vector memory_buffer_; }; } // namespace tc_bus