diff --git a/components/crow_alarm_panel/README.md b/components/crow_alarm_panel/README.md index 63369f3..667272c 100644 --- a/components/crow_alarm_panel/README.md +++ b/components/crow_alarm_panel/README.md @@ -202,7 +202,7 @@ button: ### `switch` -Output control or standalone bypass toggle. +Output control, standalone bypass toggle, or raw-frame log toggle. ```yaml switch: @@ -215,14 +215,24 @@ switch: type: bypass zone: 3 name: "Bypass Back Door" + + - platform: crow_alarm_panel + type: log_raw_frames + name: "Raw Frame Logging" ``` | Variable | Required | Description | |----------|----------|-------------| -| `type` | yes | `output` — panel output relay; `bypass` — zone bypass toggle | +| `type` | yes | `output` — panel output relay; `bypass` — zone bypass toggle; `log_raw_frames` — runtime raw-frame log toggle | | `output` | if `type: output` | Output number | | `zone` | if `type: bypass` | Zone number (1–16) | +The `log_raw_frames` switch is a pure software toggle — no bus traffic, no restored state +across reboots (always starts off). While on, it forces the raw-frame log line ("Received raw +frame [...]") to also log at `INFO` instead of requiring `VERBOSE`, so raw traffic can be +inspected at runtime without recompiling with a higher logger level. Defaults to the +`mdi:text-box-search-outline` icon; set `icon:` to override. + --- ## Logging diff --git a/components/crow_alarm_panel/crow_alarm_panel.cpp b/components/crow_alarm_panel/crow_alarm_panel.cpp index c4d3742..b501e5e 100644 --- a/components/crow_alarm_panel/crow_alarm_panel.cpp +++ b/components/crow_alarm_panel/crow_alarm_panel.cpp @@ -270,7 +270,11 @@ void CrowAlarmPanel::loop() { this->store_.data_length = 0; } - ESP_LOGV(TAG, "Received raw frame [%02x.%s]", type, format_hex_pretty(data).c_str()); + if (this->raw_frame_logging_enabled_) { + ESP_LOGI(TAG, "Received raw frame [%02x.%s]", type, format_hex_pretty(data).c_str()); + } else { + ESP_LOGV(TAG, "Received raw frame [%02x.%s]", type, format_hex_pretty(data).c_str()); + } switch (type) { case CONTROLLER_STATUS: { diff --git a/components/crow_alarm_panel/crow_alarm_panel.h b/components/crow_alarm_panel/crow_alarm_panel.h index b49ba14..ea417f4 100644 --- a/components/crow_alarm_panel/crow_alarm_panel.h +++ b/components/crow_alarm_panel/crow_alarm_panel.h @@ -248,6 +248,10 @@ class CrowAlarmPanel : public Component { void keypress(uint8_t key); + // Forces the raw-frame log line (normally VERBOSE-only) to also log at INFO, so it can + // be toggled at runtime without recompiling with a higher logger level. + void set_raw_frame_logging_enabled(bool enabled) { this->raw_frame_logging_enabled_ = enabled; } + protected: CrowAlarmPanelKeypad find_keypad_(uint8_t address); bool is_bus_idle_(); @@ -293,6 +297,8 @@ class CrowAlarmPanel : public Component { uint8_t arm_disarm_digit_ack_byte_{0}; bool arm_disarm_digit_ack_byte_set_{false}; + bool raw_frame_logging_enabled_{false}; + CrowAlarmPanelStore store_; InternalGPIOPin *clock_pin_{nullptr}; InternalGPIOPin *data_pin_{nullptr}; diff --git a/components/crow_alarm_panel/switch/__init__.py b/components/crow_alarm_panel/switch/__init__.py index 01f7736..dc11c4f 100644 --- a/components/crow_alarm_panel/switch/__init__.py +++ b/components/crow_alarm_panel/switch/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import switch -from esphome.const import CONF_ID, CONF_TYPE, CONF_OUTPUT +from esphome.const import CONF_ICON, CONF_ID, CONF_TYPE, CONF_OUTPUT from .. import ( crow_alarm_panel_ns, CrowAlarmPanel, @@ -13,6 +13,7 @@ DEPENDENCIES = ["crow_alarm_panel"] CONF_BYPASS = "bypass" +CONF_LOG_RAW_FRAMES = "log_raw_frames" CrowAlarmPanelSwitch = crow_alarm_panel_ns.class_( "CrowAlarmPanelSwitch", switch.Switch, cg.Component @@ -20,6 +21,9 @@ CrowAlarmPanelOutputSwitch = crow_alarm_panel_ns.class_( "CrowAlarmPanelOutputSwitch", CrowAlarmPanelSwitch ) +CrowAlarmPanelRawLogSwitch = crow_alarm_panel_ns.class_( + "CrowAlarmPanelRawLogSwitch", CrowAlarmPanelSwitch +) CROW_SWITCH_SCHEMA = switch.switch_schema(CrowAlarmPanelSwitch).extend( @@ -43,6 +47,12 @@ cv.Required(CONF_ZONE): cv.int_range(min=1, max=16), } ), + CONF_LOG_RAW_FRAMES: CROW_SWITCH_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(CrowAlarmPanelRawLogSwitch), + cv.Optional(CONF_ICON, default="mdi:text-box-search-outline"): cv.icon, + } + ), } ) @@ -59,6 +69,8 @@ async def to_code(config): cg.add(var.set_parent(paren)) cg.add(var.set_zone_number(config[CONF_ZONE])) cg.add(paren.register_zone_bypass_switch(var, config[CONF_ZONE])) + elif type == CONF_LOG_RAW_FRAMES: + cg.add(var.set_crow_alarm_panel_parent(paren)) await switch.register_switch(var, config) await cg.register_component(var, config) diff --git a/components/crow_alarm_panel/switch/crow_alarm_panel_switch.cpp b/components/crow_alarm_panel/switch/crow_alarm_panel_switch.cpp index 1f18f29..21c9440 100644 --- a/components/crow_alarm_panel/switch/crow_alarm_panel_switch.cpp +++ b/components/crow_alarm_panel/switch/crow_alarm_panel_switch.cpp @@ -24,5 +24,18 @@ void CrowAlarmPanelOutputSwitch::dump_config() { ESP_LOGCONFIG(TAG, " Output number %d", this->output_number_); } +void CrowAlarmPanelRawLogSwitch::write_state(bool state) { + if (this->parent_ == nullptr) { + ESP_LOGE(TAG, "Parent not set, ignoring raw log switch command"); + return; + } + this->parent_->set_raw_frame_logging_enabled(state); + this->publish_state(state); +} + +void CrowAlarmPanelRawLogSwitch::dump_config() { + LOG_SWITCH("", "Crow Alarm Panel Raw Log Switch", this); +} + } // namespace crow_alarm_panel } // namespace esphome diff --git a/components/crow_alarm_panel/switch/crow_alarm_panel_switch.h b/components/crow_alarm_panel/switch/crow_alarm_panel_switch.h index 4f03ff8..810a2ff 100644 --- a/components/crow_alarm_panel/switch/crow_alarm_panel_switch.h +++ b/components/crow_alarm_panel/switch/crow_alarm_panel_switch.h @@ -29,5 +29,15 @@ class CrowAlarmPanelOutputSwitch : public CrowAlarmPanelSwitch { uint8_t output_number_{0}; }; +// Pure software toggle: no bus traffic, just forces the parent's raw-frame log line to also +// log at INFO regardless of the configured logger level. State isn't restored on boot since +// it's a debug aid, not panel state. +class CrowAlarmPanelRawLogSwitch : public CrowAlarmPanelSwitch { + public: + void dump_config() override; + protected: + void write_state(bool state) override; +}; + } // namespace crow_alarm_panel } // namespace esphome diff --git a/crow_alarm_panel_test.yaml b/crow_alarm_panel_test.yaml index ff66ed2..0cb79b7 100644 --- a/crow_alarm_panel_test.yaml +++ b/crow_alarm_panel_test.yaml @@ -112,3 +112,7 @@ switch: type: bypass zone: 3 name: "Zone 3 Bypass" + # Toggles raw-frame logging to INFO at runtime, without a VERBOSE logger level. + - platform: crow_alarm_panel + type: log_raw_frames + name: "Raw Frame Logging"