From 92a31749193190f8e9b5fd382d2ea1e17bcf9aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haa=C3=9F?= Date: Thu, 22 Jan 2026 07:49:45 +0100 Subject: [PATCH 1/9] extract nspanel buttons to partial --- .../nspanelmanager/web/static/edit_nspanel.js | 153 +++------- .../web/templates/edit_nspanel.html | 281 +----------------- .../partial/edit_nspanel_buttons.html | 152 ++++++++++ docker/web/nspanelmanager/web/views.py | 107 +++---- 4 files changed, 241 insertions(+), 452 deletions(-) create mode 100644 docker/web/nspanelmanager/web/templates/partial/edit_nspanel_buttons.html diff --git a/docker/web/nspanelmanager/web/static/edit_nspanel.js b/docker/web/nspanelmanager/web/static/edit_nspanel.js index e75e41c8..ad82d3ce 100644 --- a/docker/web/nspanelmanager/web/static/edit_nspanel.js +++ b/docker/web/nspanelmanager/web/static/edit_nspanel.js @@ -39,138 +39,77 @@ function push_log_message_to_view(data) { $("#log_body").prepend(add_html); } -function update_shown_elements() { - $("#button1_detached_mode_controls").addClass("hidden"); - $("#button2_detached_mode_controls").addClass("hidden"); - $("#button1_detached_mode_light").addClass("hidden"); - $("#button2_detached_mode_light").addClass("hidden"); - $("#button1_mqtt_mode_controls").addClass("hidden"); - $("#button2_mqtt_mode_controls").addClass("hidden"); - $("#button1_thermostat_mode_controls").addClass("hidden"); - $("#button2_thermostat_mode_controls").addClass("hidden"); - $("#button1_detached_mode_light").prop("required", false); - $("#button2_detached_mode_light").prop("required", false); - $("#button1_relay_lower_temperature").prop("required", false); - $("#button1_relay_upper_temperature").prop("required", false); - $("#button2_relay_lower_temperature").prop("required", false); - $("#button2_relay_upper_temperature").prop("required", false); - - if ($("#button1_mode").val() == 0) { +function update_shown_elements(button) { + $(`#${button}_detached_mode_controls`).addClass("hidden"); + $(`#${button}_detached_mode_light`).addClass("hidden"); + $(`#${button}_mqtt_mode_controls`).addClass("hidden"); + $(`#${button}_thermostat_mode_controls`).addClass("hidden"); + $(`#${button}_detached_mode_light`).prop("required", false); + $(`#${button}_relay_lower_temperature`).prop("required", false); + $(`#${button}_relay_upper_temperature`).prop("required", false); + + if ($(`#${button}_mode`).val() == 0) { // Direct mode - } else if ($("#button1_mode").val() == 1) { + } else if ($(`#${button}_mode`).val() == 1) { // Detached mode - $("#button1_detached_mode_controls").removeClass("hidden"); - $("#button1_detached_mode_light").prop("required", true); - $("#button1_detached_mode_light").removeClass("hidden"); - } else if ($("#button1_mode").val() == 2) { + $(`#${button}_detached_mode_controls`).removeClass("hidden"); + $(`#${button}_detached_mode_light`).prop("required", true); + $(`#${button}_detached_mode_light`).removeClass("hidden"); + } else if ($(`#${button}_mode`).val() == 2) { // MQTT mode - $("#button1_mqtt_mode_controls").removeClass("hidden"); - } else if ($("#button1_mode").val() == 3) { + $(`#${button}_mqtt_mode_controls`).removeClass("hidden"); + } else if ($(`#${button}_mode`).val() == 3) { // Follow mode - } else if ($("#button1_mode").val() == 4 || $("#button1_mode").val() == 5) { + } else if ($(`#${button}_mode`).val() == 4 || $(`#${button}_mode`).val() == 5) { // Thermostat mode - $("#button1_thermostat_mode_controls").removeClass("hidden"); - $("#button1_relay_lower_temperature").prop("required", true); - $("#button1_relay_upper_temperature").prop("required", true); - } - - if ($("#button2_mode").val() == 0) { - // Direct mode - } else if ($("#button2_mode").val() == 1) { - // Detached mode - $("#button2_detached_mode_controls").removeClass("hidden"); - $("#button2_detached_mode_light").prop("required", true); - $("#button2_detached_mode_light").removeClass("hidden"); - } else if ($("#button2_mode").val() == 2) { - // MQTT mode - $("#button2_mqtt_mode_controls").removeClass("hidden"); - } else if ($("#button2_mode").val() == 3) { - // Follow mode - } else if ($("#button2_mode").val() == 4 || $("#button2_mode").val() == 5) { - // Thermostat mode - $("#button2_thermostat_mode_controls").removeClass("hidden"); - $("#button2_relay_lower_temperature").prop("required", true); - $("#button2_relay_upper_temperature").prop("required", true); + $(`#${button}_thermostat_mode_controls`).removeClass("hidden"); + $(`#${button}_relay_lower_temperature`).prop("required", true); + $(`#${button}_relay_upper_temperature`).prop("required", true); } // Update shown lights depending on selected room - var button1_selected_room_id = $("#button1_detached_mode_room").val(); + var selected_room_id = $(`#${button}_detached_mode_room`).val(); $( - ".button1_detached_mode_light_option[data-room-id='" + - button1_selected_room_id + + `.${button}_detached_mode_light_option[data-room-id='` + + selected_room_id + "']", ).show(); $( - ".button1_detached_mode_light_option[data-room-id!='" + - button1_selected_room_id + + `.${button}_detached_mode_light_option[data-room-id!='` + + selected_room_id + "']", ).hide(); // Check if selected button1_detached_mode_light option is visible, if not, select the first of the options. if ( $( - ".button1_detached_mode_light_option[data-room-id='" + - button1_selected_room_id + + `.${button}_detached_mode_light_option[data-room-id='` + + selected_room_id + "']:selected", ).length == 0 ) { - var button1_detached_light_first_value = $( - ".button1_detached_mode_light_option[data-room-id='" + - button1_selected_room_id + + var detached_light_first_value = $( + `.${button}_detached_mode_light_option[data-room-id='` + + selected_room_id + "']:first", ).val(); - if (button1_detached_light_first_value) { + if (detached_light_first_value) { console.log( - "Selected option for button1 detached light is no longer accessible in selected room, will select '", - button1_detached_light_first_value, + `Selected option for ${button} detached light is no longer accessible in selected room, will select '`, + detached_light_first_value, "' instead.", ); - $("#button1_detached_mode_light") - .val(button1_detached_light_first_value) + $(`#${button}_detached_mode_light`) + .val(detached_light_first_value) .change(); } else { - $("#button1_detached_mode_light").val("").change(); + $(`#${button}_detached_mode_light`).val("").change(); } } - var button2_selected_room_id = $("#button2_detached_mode_room").val(); - $( - ".button2_detached_mode_light_option[data-room-id='" + - button2_selected_room_id + - "']", - ).show(); - $( - ".button2_detached_mode_light_option[data-room-id!='" + - button2_selected_room_id + - "']", - ).hide(); +} - // Check if selected button2_detached_mode_light option is visible, if not, select the first of the options. - if ( - $( - ".button2_detached_mode_light_option[data-room-id='" + - button2_selected_room_id + - "']:selected", - ).length == 0 - ) { - var button2_detached_light_first_value = $( - ".button2_detached_mode_light_option[data-room-id='" + - button2_selected_room_id + - "']:first", - ).val(); - if (button2_detached_light_first_value) { - console.log( - "Selected option for button2 detached light is no longer accessible in selected room, will select '", - button2_detached_light_first_value, - "' instead.", - ); - $("#button2_detached_mode_light") - .val(button2_detached_light_first_value) - .change(); - } else { - $("#button2_detached_mode_light").val("").change(); - } - } +function update_screeensave_mode() { // Update if screensaver outside temperature setting is available or not. var screensaver_mode = $("#screensaver_mode").val(); @@ -226,13 +165,13 @@ $(document).ready(() => { } }); }); - update_shown_elements(); - - $("#button1_mode").change(update_shown_elements); - $("#button2_mode").change(update_shown_elements); - $("#screensaver_mode").change(update_shown_elements); - $("#button1_detached_mode_room").change(update_shown_elements); - $("#button2_detached_mode_room").change(update_shown_elements); + + for(let button of ["button1", "button2" ]) { + update_shown_elements(button); + $(`#${button}_mode`).change(() => update_shown_elements(button)); + $(`#${button}_detached_mode_room`).change(() => update_shown_elements(button)); + } + $("#screensaver_mode").change(update_screeensave_mode); $("#panel_type").on("change", update_nspanel_example_view); update_nspanel_example_view(); // Update once manually depending on selected choice. diff --git a/docker/web/nspanelmanager/web/templates/edit_nspanel.html b/docker/web/nspanelmanager/web/templates/edit_nspanel.html index 262448a0..47f2ce0d 100644 --- a/docker/web/nspanelmanager/web/templates/edit_nspanel.html +++ b/docker/web/nspanelmanager/web/templates/edit_nspanel.html @@ -340,285 +340,8 @@

MAC: {{ panel_info.data.ma
- -
- -
- - - - -
- - - - - - - - - - - -
- - -
- -
- - - - -
- - - - - - - - - - - -
+ {% include "partial/edit_nspanel_buttons.html" with button="button1" button_name="Left button" %} + {% include "partial/edit_nspanel_buttons.html" with button="button2" button_name="Right button" %}
diff --git a/docker/web/nspanelmanager/web/templates/partial/edit_nspanel_buttons.html b/docker/web/nspanelmanager/web/templates/partial/edit_nspanel_buttons.html new file mode 100644 index 00000000..7c0c62bc --- /dev/null +++ b/docker/web/nspanelmanager/web/templates/partial/edit_nspanel_buttons.html @@ -0,0 +1,152 @@ + +
+ +
+ + + + +
+ + + + + + + + + + +
diff --git a/docker/web/nspanelmanager/web/views.py b/docker/web/nspanelmanager/web/views.py index 5f4d49f1..4431e889 100755 --- a/docker/web/nspanelmanager/web/views.py +++ b/docker/web/nspanelmanager/web/views.py @@ -9,6 +9,7 @@ from django.shortcuts import Http404, HttpResponse, redirect, render from django.views.decorators.csrf import csrf_exempt from requests import delete +from django.template.defaulttags import register from web.openhab_api import get_all_openhab_items from web.settings_helper import ( @@ -381,33 +382,21 @@ def edit_nspanel(request, panel_id: int): "temperature_calibration": get_nspanel_setting_with_default( panel_id, "temperature_calibration", 0 ), - "button1_custom_mqtt_topic": get_nspanel_setting_with_default( - panel_id, "button1_mqtt_topic", "" - ), - "button1_custom_mqtt_payload": get_nspanel_setting_with_default( - panel_id, "button1_mqtt_payload", "" - ), - "button2_custom_mqtt_topic": get_nspanel_setting_with_default( - panel_id, "button2_mqtt_topic", "" - ), - "button2_custom_mqtt_payload": get_nspanel_setting_with_default( - panel_id, "button2_mqtt_payload", "" - ), - "button1_relay_lower_temperature": get_nspanel_setting_with_default( - panel_id, "button1_relay_lower_temperature", "" - ), - "button1_relay_upper_temperature": get_nspanel_setting_with_default( - panel_id, "button1_relay_upper_temperature", "" - ), - "button2_relay_lower_temperature": get_nspanel_setting_with_default( - panel_id, "button2_relay_lower_temperature", "" - ), - "button2_relay_upper_temperature": get_nspanel_setting_with_default( - panel_id, "button2_relay_upper_temperature", "" - ), "default_page": get_nspanel_setting_with_default(panel_id, "default_page", "0"), } - + for button in ["button1", "button2","button1_long", "button2_long"]: + key = f"{button}_custom_mqtt_topic" + settings[key] = get_nspanel_setting_with_default(panel_id, key, "") + + key = f"{button}_custom_mqtt_payload" + settings[key] = get_nspanel_setting_with_default(panel_id, key, "") + + key = f"{button}_relay_lower_temperature" + settings[key] = get_nspanel_setting_with_default(panel_id, key, "") + + key = f"{button}_relay_upper_temperature" + settings[key] = get_nspanel_setting_with_default(panel_id, key, "") + nspanel = NSPanel.objects.get(id=panel_id) panel_info = {} panel_info["data"] = nspanel @@ -426,52 +415,28 @@ def edit_nspanel(request, panel_id: int): return render(request, "edit_nspanel.html", data) -def save_panel_settings(request, panel_id: int): - panel = NSPanel.objects.get(id=panel_id) - panel.room = Room.objects.get(id=request.POST["room_id"]) - panel.friendly_name = request.POST["name"] - panel.button1_mode = request.POST["button1_mode"] - if request.POST["button1_mode"] == "1": # Detached mode - panel.button1_detached_mode_light = Entity.objects.get( - id=request.POST["button1_detached_mode_light"] - ) +def evaluate_button_state(button, panel_id, panel: NSPanel, request): + setattr(panel, f"{button}_mode", request.POST[f"{button}_mode"]) + if request.POST[f"{button}_mode"] == "1": # Detached mode + setattr(panel,f"{button}_detached_mode_light", Entity.objects.get(id=request.POST[f"{button}_detached_mode_light"])) else: - panel.button1_detached_mode_light = None + setattr(panel,f"{button}_detached_mode_light", None) - if request.POST["button1_mode"] == "2": # Custom MQTT Mode - set_nspanel_setting_value( - panel_id, "button1_mqtt_topic", request.POST["button1_custom_mqtt_topic"] - ) - set_nspanel_setting_value( - panel_id, - "button1_mqtt_payload", - request.POST["button1_custom_mqtt_payload"], - ) - else: - delete_nspanel_setting(panel_id, "button1_mqtt_topic") - delete_nspanel_setting(panel_id, "button1_mqtt_payload") - - panel.button2_mode = request.POST["button2_mode"] - if request.POST["button2_mode"] == "1": # Detached mode - panel.button2_detached_mode_light = Entity.objects.get( - id=request.POST["button2_detached_mode_light"] - ) + if request.POST[f"{button}_mode"] == "2": # Custom MQTT Mode + set_nspanel_setting_value(panel_id, f"{button}_custom_mqtt_topic", request.POST[f"{button}_custom_mqtt_topic"]) + set_nspanel_setting_value(panel_id,f"{button}_custom_mqtt_payload",request.POST[f"{button}_custom_mqtt_payload"]) else: - panel.button2_detached_mode_light = None + delete_nspanel_setting(panel_id, f"{button}_custom_mqtt_topic") + delete_nspanel_setting(panel_id, f"{button}_custom_mqtt_payload") + - if request.POST["button2_mode"] == "2": # Custom MQTT Mode - set_nspanel_setting_value( - panel_id, "button2_mqtt_topic", request.POST["button2_custom_mqtt_topic"] - ) - set_nspanel_setting_value( - panel_id, - "button2_mqtt_payload", - request.POST["button2_custom_mqtt_payload"], - ) - else: - delete_nspanel_setting(panel_id, "button2_mqtt_topic") - delete_nspanel_setting(panel_id, "button2_mqtt_payload") +def save_panel_settings(request, panel_id: int): + panel = NSPanel.objects.get(id=panel_id) + panel.room = Room.objects.get(id=request.POST["room_id"]) + panel.friendly_name = request.POST["name"] + for button in ["button1", "button2"]: + evaluate_button_state (button, panel_id, panel, request) if request.POST["screen_dim_level"].strip(): set_nspanel_setting_value( panel_id, "screen_dim_level", request.POST["screen_dim_level"] @@ -810,6 +775,16 @@ def save_new_merged_flash(request): # TODO: Make exempt only when Debug = true +# register template custom filter which allows dict access +@register.filter +def get_item(dictionary, key): + try: + return dictionary.get(key) + except Exception as e: + if type(e) != AttributeError: + raise e + return getattr(dictionary,key) + def get_client_ip(request): x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR") From 9d8cc9e31f11ec38a9ac10ad541c88f548e31e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haa=C3=9F?= Date: Thu, 22 Jan 2026 21:48:10 +0100 Subject: [PATCH 2/9] show firmware version in status --- .../MQTTManager/include/nspanel/nspanel.cpp | 5 + .../MQTTManager/include/nspanel/nspanel.hpp | 1 + .../include/protobuf/protobuf_nspanel.pb.cc | 243 ++++++++++-------- .../include/protobuf/protobuf_nspanel.pb.h | 72 +++++- docker/protobuf/protobuf_nspanel.proto | 1 + .../nspanel_status_firmware_version.py | 34 +++ ..._status_firmware_version_edit_nspanel.html | 54 ++++ ...nspanel_status_firmware_version_index.html | 49 ++++ .../web/templates/edit_nspanel.html | 3 + .../partial/nspanel_index_view_htmx.html | 6 + protobuf_firmware/protobuf_nspanel.pb-c.c | 19 +- protobuf_firmware/protobuf_nspanel.pb-c.h | 3 +- 12 files changed, 379 insertions(+), 111 deletions(-) create mode 100644 docker/web/nspanelmanager/web/components/nspanel_status_firmware_version/nspanel_status_firmware_version.py create mode 100644 docker/web/nspanelmanager/web/components/nspanel_status_firmware_version/nspanel_status_firmware_version_edit_nspanel.html create mode 100644 docker/web/nspanelmanager/web/components/nspanel_status_firmware_version/nspanel_status_firmware_version_index.html diff --git a/docker/MQTTManager/include/nspanel/nspanel.cpp b/docker/MQTTManager/include/nspanel/nspanel.cpp index 54aefc23..cb086a74 100644 --- a/docker/MQTTManager/include/nspanel/nspanel.cpp +++ b/docker/MQTTManager/include/nspanel/nspanel.cpp @@ -579,6 +579,7 @@ void NSPanel::mqtt_callback(std::string topic, std::string payload) { this->_rssi = report.rssi(); this->_heap_used_pct = report.heap_used_pct(); this->_temperature = report.temperature(); + this->_version = report.version(); this->_current_firmware_md5_checksum = report.md5_firmware(); this->_current_littlefs_md5_checksum = report.md5_littlefs(); this->_current_tft_md5_checksum = report.md5_tft_gui(); @@ -796,6 +797,8 @@ void NSPanel::send_websocket_status_update() { nlohmann::json status_data = { {"id", this->_id}, {"name", this->_name}, + {"version", this->_version}, + {"firmware_md5", this->_current_firmware_md5_checksum}, {"ip_address", this->_ip_address}, {"rssi", this->_rssi}, {"temperature", this->_temperature}, @@ -1040,6 +1043,7 @@ nlohmann::json NSPanel::get_websocket_json_representation() { data["nspanel_id"] = this->_id; } data["name"] = this->_name; + data["version"] = this->_version; data["rssi"] = this->_rssi; data["heap_used_pct"] = this->_heap_used_pct; data["mac_address"] = send_mac; @@ -1171,6 +1175,7 @@ void NSPanel::register_to_home_assistant() { base_json["device"]["manufacturer"] = "Sonoff"; base_json["device"]["model"] = "NSPanel"; base_json["device"]["name"] = this->_name; + base_json["device"]["version"] = this->_version; base_json["availability"] = nlohmann::json(); base_json["availability"]["topic"] = this->_mqtt_status_topic; base_json["availability"]["value_template"] = "{{ value_json.state }}"; diff --git a/docker/MQTTManager/include/nspanel/nspanel.hpp b/docker/MQTTManager/include/nspanel/nspanel.hpp index 3c9cb183..f726a405 100644 --- a/docker/MQTTManager/include/nspanel/nspanel.hpp +++ b/docker/MQTTManager/include/nspanel/nspanel.hpp @@ -179,6 +179,7 @@ class NSPanel { std::mutex _settings_mutex; // Mutex to only allow access to _settings for one thread at the time std::string _mac; std::string _name; + std::string _version; bool _is_us_panel; enum US_PANEL_ORIENTATION { LANDSCAPE_LEFT, diff --git a/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.cc b/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.cc index cf9e21ed..d8e735a3 100644 --- a/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.cc +++ b/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.cc @@ -432,6 +432,9 @@ inline constexpr NSPanelStatusReport::Impl_::Impl_( md5_tft_gui_( &::google::protobuf::internal::fixed_address_empty_string, ::_pbi::ConstantInitialized()), + version_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), nspanel_state_{static_cast< ::NSPanelStatusReport_state >(0)}, update_progress_{0}, rssi_{0}, @@ -648,6 +651,7 @@ const ::uint32_t PROTOBUF_FIELD_OFFSET(::NSPanelStatusReport, _impl_.md5_firmware_), PROTOBUF_FIELD_OFFSET(::NSPanelStatusReport, _impl_.md5_littlefs_), PROTOBUF_FIELD_OFFSET(::NSPanelStatusReport, _impl_.md5_tft_gui_), + PROTOBUF_FIELD_OFFSET(::NSPanelStatusReport, _impl_.version_), ~0u, // no _has_bits_ PROTOBUF_FIELD_OFFSET(::NSPanelLightStatus, _internal_metadata_), ~0u, // no _extensions_ @@ -861,21 +865,21 @@ static const ::_pbi::MigrationSchema {11, -1, -1, sizeof(::NSPanelConfig)}, {55, -1, -1, sizeof(::NSPanelWarning)}, {65, -1, -1, sizeof(::NSPanelStatusReport)}, - {84, -1, -1, sizeof(::NSPanelLightStatus)}, - {102, -1, -1, sizeof(::NSPanelRoomEntitiesPage_EntitySlot)}, - {117, -1, -1, sizeof(::NSPanelRoomEntitiesPage)}, - {129, -1, -1, sizeof(::NSPanelRoomStatus)}, - {150, -1, -1, sizeof(::NSPanelWeatherUpdate_ForecastItem)}, - {163, -1, -1, sizeof(::NSPanelWeatherUpdate)}, - {179, -1, -1, sizeof(::NSPanelMQTTManagerCommand_FirstPageTurnLightOn)}, - {194, -1, -1, sizeof(::NSPanelMQTTManagerCommand_FirstPageTurnLightOff)}, - {204, -1, -1, sizeof(::NSPanelMQTTManagerCommand_LightCommand)}, - {221, -1, -1, sizeof(::NSPanelMQTTManagerCommand_ToggleEntityFromEntitiesPage)}, - {231, -1, -1, sizeof(::NSPanelMQTTManagerCommand_SaveSceneCommand)}, - {241, -1, -1, sizeof(::NSPanelMQTTManagerCommand_ButtonPressed)}, - {250, -1, -1, sizeof(::NSPanelMQTTManagerCommand_ThermostatTemperatureCommand)}, - {260, -1, -1, sizeof(::NSPanelMQTTManagerCommand_ThermostatCommand)}, - {271, -1, -1, sizeof(::NSPanelMQTTManagerCommand)}, + {85, -1, -1, sizeof(::NSPanelLightStatus)}, + {103, -1, -1, sizeof(::NSPanelRoomEntitiesPage_EntitySlot)}, + {118, -1, -1, sizeof(::NSPanelRoomEntitiesPage)}, + {130, -1, -1, sizeof(::NSPanelRoomStatus)}, + {151, -1, -1, sizeof(::NSPanelWeatherUpdate_ForecastItem)}, + {164, -1, -1, sizeof(::NSPanelWeatherUpdate)}, + {180, -1, -1, sizeof(::NSPanelMQTTManagerCommand_FirstPageTurnLightOn)}, + {195, -1, -1, sizeof(::NSPanelMQTTManagerCommand_FirstPageTurnLightOff)}, + {205, -1, -1, sizeof(::NSPanelMQTTManagerCommand_LightCommand)}, + {222, -1, -1, sizeof(::NSPanelMQTTManagerCommand_ToggleEntityFromEntitiesPage)}, + {232, -1, -1, sizeof(::NSPanelMQTTManagerCommand_SaveSceneCommand)}, + {242, -1, -1, sizeof(::NSPanelMQTTManagerCommand_ButtonPressed)}, + {251, -1, -1, sizeof(::NSPanelMQTTManagerCommand_ThermostatTemperatureCommand)}, + {261, -1, -1, sizeof(::NSPanelMQTTManagerCommand_ThermostatCommand)}, + {272, -1, -1, sizeof(::NSPanelMQTTManagerCommand)}, }; static const ::_pb::Message* const file_default_instances[] = { &::_NSPanelConfig_RoomInfo_default_instance_._instance, @@ -944,101 +948,102 @@ const char descriptor_table_protodef_protobuf_5fnspanel_2eproto[] ABSL_ATTRIBUTE "W\020\001\022\022\n\016NOTIFY_MANAGER\020\002\022\023\n\017THERMOSTAT_HE" "AT\020\003\022\023\n\017THERMOSTAT_COOL\020\004\"C\n\016NSPanelWarn" "ing\022#\n\005level\030\001 \001(\0162\024.NSPanelWarningLevel" - "\022\014\n\004text\030\002 \001(\t\"\212\003\n\023NSPanelStatusReport\0221" + "\022\014\n\004text\030\002 \001(\t\"\233\003\n\023NSPanelStatusReport\0221" "\n\rnspanel_state\030\001 \001(\0162\032.NSPanelStatusRep" "ort.state\022\027\n\017update_progress\030\002 \001(\005\022\014\n\004rs" "si\030\003 \001(\005\022\025\n\rheap_used_pct\030\004 \001(\005\022\023\n\013mac_a" "ddress\030\005 \001(\t\022\023\n\013temperature\030\006 \001(\002\022\022\n\nip_" "address\030\007 \001(\t\022!\n\010warnings\030\010 \003(\0132\017.NSPane" "lWarning\022\024\n\014md5_firmware\030\t \001(\t\022\024\n\014md5_li" - "ttlefs\030\n \001(\t\022\023\n\013md5_tft_gui\030\013 \001(\t\"`\n\005sta" - "te\022\n\n\006ONLINE\020\000\022\013\n\007OFFLINE\020\001\022\020\n\014UPDATING_" - "TFT\020\002\022\025\n\021UPDATING_FIRMWARE\020\003\022\025\n\021UPDATING" - "_LITTLEFS\020\004\"\325\001\n\022NSPanelLightStatus\022\n\n\002id" - "\030\001 \001(\005\022\014\n\004name\030\002 \001(\t\022\017\n\007can_dim\030\003 \001(\010\022\035\n" - "\025can_color_temperature\030\004 \001(\010\022\017\n\007can_rgb\030" - "\005 \001(\010\022\023\n\013light_level\030\006 \001(\005\022\022\n\ncolor_temp" - "\030\007 \001(\005\022\013\n\003hue\030\010 \001(\005\022\022\n\nsaturation\030\t \001(\005\022" - "\032\n\022room_view_position\030\n \001(\005\"\230\002\n\027NSPanelR" - "oomEntitiesPage\022\n\n\002id\030\001 \001(\005\022\021\n\tpage_type" - "\030\002 \001(\005\022\023\n\013header_text\030\003 \001(\t\0225\n\010entities\030" - "\004 \003(\0132#.NSPanelRoomEntitiesPage.EntitySl" - "ot\032\221\001\n\nEntitySlot\022\032\n\022room_view_position\030" - "\001 \001(\005\022\014\n\004name\030\002 \001(\t\022\014\n\004icon\030\003 \001(\t\022\013\n\003pco" - "\030\004 \001(\005\022\014\n\004pco2\030\005 \001(\005\022\026\n\016can_save_scene\030\006" - " \001(\010\022\030\n\020mqtt_state_topic\030\007 \001(\t\"\226\003\n\021NSPan" - "elRoomStatus\022\n\n\002id\030\001 \001(\005\022\014\n\004name\030\002 \001(\t\022\031" - "\n\021average_dim_level\030\003 \001(\005\022 \n\030ceiling_lig" - "hts_dim_level\030\004 \001(\005\022\036\n\026table_lights_dim_" - "level\030\005 \001(\005\022!\n\031average_color_temperature" - "\030\006 \001(\005\022.\n&ceiling_lights_color_temperatu" - "re_value\030\007 \001(\005\022,\n$table_lights_color_tem" - "perature_value\030\010 \001(\005\022\032\n\022num_ceiling_ligh" - "ts\030\t \001(\005\022\030\n\020num_table_lights\030\n \001(\005\022\035\n\025nu" - "m_ceiling_lights_on\030\013 \001(\005\022\033\n\023num_table_l" - "ights_on\030\014 \001(\005\022\027\n\017entity_page_ids\030\r \003(\005\"" - "\277\003\n\024NSPanelWeatherUpdate\022:\n\016forecast_ite" - "ms\030\001 \003(\0132\".NSPanelWeatherUpdate.Forecast" - "Item\022\034\n\024current_weather_icon\030\002 \001(\t\022\"\n\032cu" - "rrent_temperature_string\030\003 \001(\t\022\"\n\032curren" - "t_maxmin_temperature\030\004 \001(\t\022\033\n\023current_wi" - "nd_string\030\005 \001(\t\022\026\n\016sunrise_string\030\006 \001(\t\022" - "\025\n\rsunset_string\030\007 \001(\t\022$\n\034current_precip" - "itation_string\030\010 \001(\t\032\222\001\n\014ForecastItem\022\024\n" - "\014weather_icon\030\001 \001(\t\022\034\n\024precipitation_str" - "ing\030\002 \001(\t\022!\n\031temperature_maxmin_string\030\003" - " \001(\t\022\023\n\013wind_string\030\004 \001(\t\022\026\n\016display_str" - "ing\030\005 \001(\t\"\227\r\n\031NSPanelMQTTManagerCommand\022" - "M\n\022first_page_turn_on\030\001 \001(\0132/.NSPanelMQT" - "TManagerCommand.FirstPageTurnLightOnH\000\022O" - "\n\023first_page_turn_off\030\002 \001(\01320.NSPanelMQT" - "TManagerCommand.FirstPageTurnLightOffH\000\022" - "@\n\rlight_command\030\003 \001(\0132\'.NSPanelMQTTMana" - "gerCommand.LightCommandH\000\022c\n toggle_enti" - "ty_from_entities_page\030\004 \001(\01327.NSPanelMQT" - "TManagerCommand.ToggleEntityFromEntities" - "PageH\000\022I\n\022save_scene_command\030\005 \001(\0132+.NSP" - "anelMQTTManagerCommand.SaveSceneCommandH" - "\000\022B\n\016button_pressed\030\006 \001(\0132(.NSPanelMQTTM" - "anagerCommand.ButtonPressedH\000\022a\n\036thermos" - "tat_temperature_command\030\007 \001(\01327.NSPanelM" - "QTTManagerCommand.ThermostatTemperatureC" - "ommandH\000\022J\n\022thermostat_command\030\010 \001(\0132,.N" - "SPanelMQTTManagerCommand.ThermostatComma" - "ndH\000\022\022\n\nnspanel_id\030d \001(\005\032\372\001\n\024FirstPageTu" - "rnLightOn\022E\n\raffect_lights\030\001 \001(\0162..NSPan" - "elMQTTManagerCommand.AffectLightsOptions" - "\022\037\n\027brightness_slider_value\030\002 \001(\005\022\033\n\023kel" - "vin_slider_value\030\003 \001(\005\022\025\n\rselected_room\030" - "\004 \001(\005\022\016\n\006global\030\005 \001(\010\022\034\n\024has_brightness_" - "value\030\006 \001(\010\022\030\n\020has_kelvin_value\030\007 \001(\010\032n\n" - "\025FirstPageTurnLightOff\022E\n\raffect_lights\030" - "\001 \001(\0162..NSPanelMQTTManagerCommand.Affect" - "LightsOptions\022\016\n\006global\030\002 \001(\010\032\321\001\n\014LightC" - "ommand\022\021\n\tlight_ids\030\001 \003(\005\022\026\n\016has_brightn" - "ess\030\002 \001(\010\022\022\n\nbrightness\030\003 \001(\005\022\035\n\025has_col" - "or_temperature\030\004 \001(\010\022\031\n\021color_temperatur" - "e\030\005 \001(\005\022\017\n\007has_hue\030\006 \001(\010\022\013\n\003hue\030\007 \001(\005\022\026\n" - "\016has_saturation\030\010 \001(\010\022\022\n\nsaturation\030\t \001(" - "\005\032K\n\034ToggleEntityFromEntitiesPage\022\026\n\016ent" - "ity_page_id\030\001 \001(\005\022\023\n\013entity_slot\030\002 \001(\005\032\?" - "\n\020SaveSceneCommand\022\026\n\016entity_page_id\030\001 \001" - "(\005\022\023\n\013entity_slot\030\002 \001(\005\032\"\n\rButtonPressed" - "\022\021\n\tbutton_id\030\002 \001(\005\032J\n\034ThermostatTempera" - "tureCommand\022\025\n\rthermostat_id\030\001 \001(\005\022\023\n\013te" - "mperature\030\002 \001(\002\032M\n\021ThermostatCommand\022\025\n\r" - "thermostat_id\030\001 \001(\005\022\016\n\006option\030\002 \001(\t\022\021\n\tn" - "ew_value\030\003 \001(\t\"D\n\023AffectLightsOptions\022\007\n" - "\003ALL\020\000\022\020\n\014TABLE_LIGHTS\020\001\022\022\n\016CEILING_LIGH" - "TS\020\002B\r\n\013CommandData*[\n\023NSPanelWarningLev" - "el\022\014\n\010CRITICAL\020\000\022\t\n\005ERROR\020\001\022\013\n\007WARNING\020\002" - "\022\010\n\004INFO\020\003\022\t\n\005DEBUG\020\004\022\t\n\005TRACE\020\005b\006proto3" + "ttlefs\030\n \001(\t\022\023\n\013md5_tft_gui\030\013 \001(\t\022\017\n\007ver" + "sion\030\014 \001(\t\"`\n\005state\022\n\n\006ONLINE\020\000\022\013\n\007OFFLI" + "NE\020\001\022\020\n\014UPDATING_TFT\020\002\022\025\n\021UPDATING_FIRMW" + "ARE\020\003\022\025\n\021UPDATING_LITTLEFS\020\004\"\325\001\n\022NSPanel" + "LightStatus\022\n\n\002id\030\001 \001(\005\022\014\n\004name\030\002 \001(\t\022\017\n" + "\007can_dim\030\003 \001(\010\022\035\n\025can_color_temperature\030" + "\004 \001(\010\022\017\n\007can_rgb\030\005 \001(\010\022\023\n\013light_level\030\006 " + "\001(\005\022\022\n\ncolor_temp\030\007 \001(\005\022\013\n\003hue\030\010 \001(\005\022\022\n\n" + "saturation\030\t \001(\005\022\032\n\022room_view_position\030\n" + " \001(\005\"\230\002\n\027NSPanelRoomEntitiesPage\022\n\n\002id\030\001" + " \001(\005\022\021\n\tpage_type\030\002 \001(\005\022\023\n\013header_text\030\003" + " \001(\t\0225\n\010entities\030\004 \003(\0132#.NSPanelRoomEnti" + "tiesPage.EntitySlot\032\221\001\n\nEntitySlot\022\032\n\022ro" + "om_view_position\030\001 \001(\005\022\014\n\004name\030\002 \001(\t\022\014\n\004" + "icon\030\003 \001(\t\022\013\n\003pco\030\004 \001(\005\022\014\n\004pco2\030\005 \001(\005\022\026\n" + "\016can_save_scene\030\006 \001(\010\022\030\n\020mqtt_state_topi" + "c\030\007 \001(\t\"\226\003\n\021NSPanelRoomStatus\022\n\n\002id\030\001 \001(" + "\005\022\014\n\004name\030\002 \001(\t\022\031\n\021average_dim_level\030\003 \001" + "(\005\022 \n\030ceiling_lights_dim_level\030\004 \001(\005\022\036\n\026" + "table_lights_dim_level\030\005 \001(\005\022!\n\031average_" + "color_temperature\030\006 \001(\005\022.\n&ceiling_light" + "s_color_temperature_value\030\007 \001(\005\022,\n$table" + "_lights_color_temperature_value\030\010 \001(\005\022\032\n" + "\022num_ceiling_lights\030\t \001(\005\022\030\n\020num_table_l" + "ights\030\n \001(\005\022\035\n\025num_ceiling_lights_on\030\013 \001" + "(\005\022\033\n\023num_table_lights_on\030\014 \001(\005\022\027\n\017entit" + "y_page_ids\030\r \003(\005\"\277\003\n\024NSPanelWeatherUpdat" + "e\022:\n\016forecast_items\030\001 \003(\0132\".NSPanelWeath" + "erUpdate.ForecastItem\022\034\n\024current_weather" + "_icon\030\002 \001(\t\022\"\n\032current_temperature_strin" + "g\030\003 \001(\t\022\"\n\032current_maxmin_temperature\030\004 " + "\001(\t\022\033\n\023current_wind_string\030\005 \001(\t\022\026\n\016sunr" + "ise_string\030\006 \001(\t\022\025\n\rsunset_string\030\007 \001(\t\022" + "$\n\034current_precipitation_string\030\010 \001(\t\032\222\001" + "\n\014ForecastItem\022\024\n\014weather_icon\030\001 \001(\t\022\034\n\024" + "precipitation_string\030\002 \001(\t\022!\n\031temperatur" + "e_maxmin_string\030\003 \001(\t\022\023\n\013wind_string\030\004 \001" + "(\t\022\026\n\016display_string\030\005 \001(\t\"\227\r\n\031NSPanelMQ" + "TTManagerCommand\022M\n\022first_page_turn_on\030\001" + " \001(\0132/.NSPanelMQTTManagerCommand.FirstPa" + "geTurnLightOnH\000\022O\n\023first_page_turn_off\030\002" + " \001(\01320.NSPanelMQTTManagerCommand.FirstPa" + "geTurnLightOffH\000\022@\n\rlight_command\030\003 \001(\0132" + "\'.NSPanelMQTTManagerCommand.LightCommand" + "H\000\022c\n toggle_entity_from_entities_page\030\004" + " \001(\01327.NSPanelMQTTManagerCommand.ToggleE" + "ntityFromEntitiesPageH\000\022I\n\022save_scene_co" + "mmand\030\005 \001(\0132+.NSPanelMQTTManagerCommand." + "SaveSceneCommandH\000\022B\n\016button_pressed\030\006 \001" + "(\0132(.NSPanelMQTTManagerCommand.ButtonPre" + "ssedH\000\022a\n\036thermostat_temperature_command" + "\030\007 \001(\01327.NSPanelMQTTManagerCommand.Therm" + "ostatTemperatureCommandH\000\022J\n\022thermostat_" + "command\030\010 \001(\0132,.NSPanelMQTTManagerComman" + "d.ThermostatCommandH\000\022\022\n\nnspanel_id\030d \001(" + "\005\032\372\001\n\024FirstPageTurnLightOn\022E\n\raffect_lig" + "hts\030\001 \001(\0162..NSPanelMQTTManagerCommand.Af" + "fectLightsOptions\022\037\n\027brightness_slider_v" + "alue\030\002 \001(\005\022\033\n\023kelvin_slider_value\030\003 \001(\005\022" + "\025\n\rselected_room\030\004 \001(\005\022\016\n\006global\030\005 \001(\010\022\034" + "\n\024has_brightness_value\030\006 \001(\010\022\030\n\020has_kelv" + "in_value\030\007 \001(\010\032n\n\025FirstPageTurnLightOff\022" + "E\n\raffect_lights\030\001 \001(\0162..NSPanelMQTTMana" + "gerCommand.AffectLightsOptions\022\016\n\006global" + "\030\002 \001(\010\032\321\001\n\014LightCommand\022\021\n\tlight_ids\030\001 \003" + "(\005\022\026\n\016has_brightness\030\002 \001(\010\022\022\n\nbrightness" + "\030\003 \001(\005\022\035\n\025has_color_temperature\030\004 \001(\010\022\031\n" + "\021color_temperature\030\005 \001(\005\022\017\n\007has_hue\030\006 \001(" + "\010\022\013\n\003hue\030\007 \001(\005\022\026\n\016has_saturation\030\010 \001(\010\022\022" + "\n\nsaturation\030\t \001(\005\032K\n\034ToggleEntityFromEn" + "titiesPage\022\026\n\016entity_page_id\030\001 \001(\005\022\023\n\013en" + "tity_slot\030\002 \001(\005\032\?\n\020SaveSceneCommand\022\026\n\016e" + "ntity_page_id\030\001 \001(\005\022\023\n\013entity_slot\030\002 \001(\005" + "\032\"\n\rButtonPressed\022\021\n\tbutton_id\030\002 \001(\005\032J\n\034" + "ThermostatTemperatureCommand\022\025\n\rthermost" + "at_id\030\001 \001(\005\022\023\n\013temperature\030\002 \001(\002\032M\n\021Ther" + "mostatCommand\022\025\n\rthermostat_id\030\001 \001(\005\022\016\n\006" + "option\030\002 \001(\t\022\021\n\tnew_value\030\003 \001(\t\"D\n\023Affec" + "tLightsOptions\022\007\n\003ALL\020\000\022\020\n\014TABLE_LIGHTS\020" + "\001\022\022\n\016CEILING_LIGHTS\020\002B\r\n\013CommandData*[\n\023" + "NSPanelWarningLevel\022\014\n\010CRITICAL\020\000\022\t\n\005ERR" + "OR\020\001\022\013\n\007WARNING\020\002\022\010\n\004INFO\020\003\022\t\n\005DEBUG\020\004\022\t" + "\n\005TRACE\020\005b\006proto3" }; static ::absl::once_flag descriptor_table_protobuf_5fnspanel_2eproto_once; PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_protobuf_5fnspanel_2eproto = { false, false, - 5320, + 5337, descriptor_table_protodef_protobuf_5fnspanel_2eproto, "protobuf_nspanel.proto", &descriptor_table_protobuf_5fnspanel_2eproto_once, @@ -2680,6 +2685,7 @@ inline PROTOBUF_NDEBUG_INLINE NSPanelStatusReport::Impl_::Impl_( md5_firmware_(arena, from.md5_firmware_), md5_littlefs_(arena, from.md5_littlefs_), md5_tft_gui_(arena, from.md5_tft_gui_), + version_(arena, from.version_), _cached_size_{0} {} NSPanelStatusReport::NSPanelStatusReport( @@ -2710,6 +2716,7 @@ inline PROTOBUF_NDEBUG_INLINE NSPanelStatusReport::Impl_::Impl_( md5_firmware_(arena), md5_littlefs_(arena), md5_tft_gui_(arena), + version_(arena), _cached_size_{0} {} inline void NSPanelStatusReport::SharedCtor(::_pb::Arena* arena) { @@ -2733,6 +2740,7 @@ inline void NSPanelStatusReport::SharedDtor() { _impl_.md5_firmware_.Destroy(); _impl_.md5_littlefs_.Destroy(); _impl_.md5_tft_gui_.Destroy(); + _impl_.version_.Destroy(); _impl_.~Impl_(); } @@ -2757,15 +2765,15 @@ NSPanelStatusReport::GetClassData() const { return _data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 -const ::_pbi::TcParseTable<4, 11, 1, 92, 2> NSPanelStatusReport::_table_ = { +const ::_pbi::TcParseTable<4, 12, 1, 99, 2> NSPanelStatusReport::_table_ = { { 0, // no _has_bits_ 0, // no _extensions_ - 11, 120, // max_field_number, fast_idx_mask + 12, 120, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), - 4294965248, // skipmap + 4294963200, // skipmap offsetof(decltype(_table_), field_entries), - 11, // num_field_entries + 12, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), &_NSPanelStatusReport_default_instance_._instance, @@ -2809,7 +2817,9 @@ const ::_pbi::TcParseTable<4, 11, 1, 92, 2> NSPanelStatusReport::_table_ = { // string md5_tft_gui = 11; {::_pbi::TcParser::FastUS1, {90, 63, 0, PROTOBUF_FIELD_OFFSET(NSPanelStatusReport, _impl_.md5_tft_gui_)}}, - {::_pbi::TcParser::MiniParse, {}}, + // string version = 12; + {::_pbi::TcParser::FastUS1, + {98, 63, 0, PROTOBUF_FIELD_OFFSET(NSPanelStatusReport, _impl_.version_)}}, {::_pbi::TcParser::MiniParse, {}}, {::_pbi::TcParser::MiniParse, {}}, {::_pbi::TcParser::MiniParse, {}}, @@ -2849,16 +2859,20 @@ const ::_pbi::TcParseTable<4, 11, 1, 92, 2> NSPanelStatusReport::_table_ = { // string md5_tft_gui = 11; {PROTOBUF_FIELD_OFFSET(NSPanelStatusReport, _impl_.md5_tft_gui_), 0, 0, (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string version = 12; + {PROTOBUF_FIELD_OFFSET(NSPanelStatusReport, _impl_.version_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, }}, {{ {::_pbi::TcParser::GetTable<::NSPanelWarning>()}, }}, {{ - "\23\0\0\0\0\13\0\12\0\14\14\13\0\0\0\0" + "\23\0\0\0\0\13\0\12\0\14\14\13\7\0\0\0" "NSPanelStatusReport" "mac_address" "ip_address" "md5_firmware" "md5_littlefs" "md5_tft_gui" + "version" }}, }; @@ -2875,6 +2889,7 @@ PROTOBUF_NOINLINE void NSPanelStatusReport::Clear() { _impl_.md5_firmware_.ClearToEmpty(); _impl_.md5_littlefs_.ClearToEmpty(); _impl_.md5_tft_gui_.ClearToEmpty(); + _impl_.version_.ClearToEmpty(); ::memset(&_impl_.nspanel_state_, 0, static_cast<::size_t>( reinterpret_cast(&_impl_.temperature_) - reinterpret_cast(&_impl_.nspanel_state_)) + sizeof(_impl_.temperature_)); @@ -2979,6 +2994,14 @@ ::uint8_t* NSPanelStatusReport::_InternalSerialize( target = stream->WriteStringMaybeAliased(11, _s, target); } + // string version = 12; + if (!this->_internal_version().empty()) { + const std::string& _s = this->_internal_version(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "NSPanelStatusReport.version"); + target = stream->WriteStringMaybeAliased(12, _s, target); + } + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( @@ -3032,6 +3055,12 @@ ::size_t NSPanelStatusReport::ByteSizeLong() const { this->_internal_md5_tft_gui()); } + // string version = 12; + if (!this->_internal_version().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_version()); + } + // .NSPanelStatusReport.state nspanel_state = 1; if (this->_internal_nspanel_state() != 0) { total_size += 1 + @@ -3095,6 +3124,9 @@ void NSPanelStatusReport::MergeImpl(::google::protobuf::MessageLite& to_msg, con if (!from._internal_md5_tft_gui().empty()) { _this->_internal_set_md5_tft_gui(from._internal_md5_tft_gui()); } + if (!from._internal_version().empty()) { + _this->_internal_set_version(from._internal_version()); + } if (from._internal_nspanel_state() != 0) { _this->_impl_.nspanel_state_ = from._impl_.nspanel_state_; } @@ -3137,6 +3169,7 @@ void NSPanelStatusReport::InternalSwap(NSPanelStatusReport* PROTOBUF_RESTRICT ot ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.md5_firmware_, &other->_impl_.md5_firmware_, arena); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.md5_littlefs_, &other->_impl_.md5_littlefs_, arena); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.md5_tft_gui_, &other->_impl_.md5_tft_gui_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.version_, &other->_impl_.version_, arena); ::google::protobuf::internal::memswap< PROTOBUF_FIELD_OFFSET(NSPanelStatusReport, _impl_.temperature_) + sizeof(NSPanelStatusReport::_impl_.temperature_) diff --git a/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.h b/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.h index b9680467..f3b43adf 100644 --- a/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.h +++ b/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.h @@ -3944,6 +3944,7 @@ class NSPanelStatusReport final : public ::google::protobuf::Message kMd5FirmwareFieldNumber = 9, kMd5LittlefsFieldNumber = 10, kMd5TftGuiFieldNumber = 11, + kVersionFieldNumber = 12, kNspanelStateFieldNumber = 1, kUpdateProgressFieldNumber = 2, kRssiFieldNumber = 3, @@ -4046,6 +4047,22 @@ class NSPanelStatusReport final : public ::google::protobuf::Message const std::string& value); std::string* _internal_mutable_md5_tft_gui(); + public: + // string version = 12; + void clear_version() ; + const std::string& version() const; + template + void set_version(Arg_&& arg, Args_... args); + std::string* mutable_version(); + PROTOBUF_NODISCARD std::string* release_version(); + void set_allocated_version(std::string* value); + + private: + const std::string& _internal_version() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_version( + const std::string& value); + std::string* _internal_mutable_version(); + public: // .NSPanelStatusReport.state nspanel_state = 1; void clear_nspanel_state() ; @@ -4102,8 +4119,8 @@ class NSPanelStatusReport final : public ::google::protobuf::Message class _Internal; friend class ::google::protobuf::internal::TcParser; static const ::google::protobuf::internal::TcParseTable< - 4, 11, 1, - 92, 2> + 4, 12, 1, + 99, 2> _table_; static constexpr const void* _raw_default_instance_ = @@ -4129,6 +4146,7 @@ class NSPanelStatusReport final : public ::google::protobuf::Message ::google::protobuf::internal::ArenaStringPtr md5_firmware_; ::google::protobuf::internal::ArenaStringPtr md5_littlefs_; ::google::protobuf::internal::ArenaStringPtr md5_tft_gui_; + ::google::protobuf::internal::ArenaStringPtr version_; int nspanel_state_; ::int32_t update_progress_; ::int32_t rssi_; @@ -7024,6 +7042,56 @@ inline void NSPanelStatusReport::set_allocated_md5_tft_gui(std::string* value) { // @@protoc_insertion_point(field_set_allocated:NSPanelStatusReport.md5_tft_gui) } +// string version = 12; +inline void NSPanelStatusReport::clear_version() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.version_.ClearToEmpty(); +} +inline const std::string& NSPanelStatusReport::version() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:NSPanelStatusReport.version) + return _internal_version(); +} +template +inline PROTOBUF_ALWAYS_INLINE void NSPanelStatusReport::set_version(Arg_&& arg, + Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.version_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:NSPanelStatusReport.version) +} +inline std::string* NSPanelStatusReport::mutable_version() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_version(); + // @@protoc_insertion_point(field_mutable:NSPanelStatusReport.version) + return _s; +} +inline const std::string& NSPanelStatusReport::_internal_version() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.version_.Get(); +} +inline void NSPanelStatusReport::_internal_set_version(const std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.version_.Set(value, GetArena()); +} +inline std::string* NSPanelStatusReport::_internal_mutable_version() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.version_.Mutable( GetArena()); +} +inline std::string* NSPanelStatusReport::release_version() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:NSPanelStatusReport.version) + return _impl_.version_.Release(); +} +inline void NSPanelStatusReport::set_allocated_version(std::string* value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.version_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.version_.IsDefault()) { + _impl_.version_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:NSPanelStatusReport.version) +} + // ------------------------------------------------------------------- // NSPanelLightStatus diff --git a/docker/protobuf/protobuf_nspanel.proto b/docker/protobuf/protobuf_nspanel.proto index 69b587ba..1f12b692 100644 --- a/docker/protobuf/protobuf_nspanel.proto +++ b/docker/protobuf/protobuf_nspanel.proto @@ -113,6 +113,7 @@ message NSPanelStatusReport { string md5_firmware = 9; string md5_littlefs = 10; string md5_tft_gui = 11; + string version = 12; } message NSPanelLightStatus { diff --git a/docker/web/nspanelmanager/web/components/nspanel_status_firmware_version/nspanel_status_firmware_version.py b/docker/web/nspanelmanager/web/components/nspanel_status_firmware_version/nspanel_status_firmware_version.py new file mode 100644 index 00000000..8f69cd45 --- /dev/null +++ b/docker/web/nspanelmanager/web/components/nspanel_status_firmware_version/nspanel_status_firmware_version.py @@ -0,0 +1,34 @@ +from django_components import component +from django.template.context import Context + +from web.models import NSPanel + +@component.register("nspanel_status_firmware_version") +class NSPanelStatusFirmwareVersion(component.Component): + template_view = None + + def get_context_data(self, id): + nspanel = NSPanel.objects.get(id=id) + return { + "nspanel": nspanel, + } + + def get_template_name(self, context: Context): + if self.template_view: + url_name = self.template_view + else: + url_name = context.request.resolver_match.url_name + if url_name == "htmx_partial_index_nspanels_section" or url_name == "index": + return "nspanel_status_firmware_version/nspanel_status_firmware_version_index.html" + elif url_name == "edit_nspanel": + return "nspanel_status_firmware_version/nspanel_status_firmware_version_edit_nspanel.html" + + def get(self, request, view, nspanel_id): + self.template_view = view + args = { + "id": nspanel_id, + } + return self.render_to_response(kwargs=args) + + class Media: + css = "css/main.css" diff --git a/docker/web/nspanelmanager/web/components/nspanel_status_firmware_version/nspanel_status_firmware_version_edit_nspanel.html b/docker/web/nspanelmanager/web/components/nspanel_status_firmware_version/nspanel_status_firmware_version_edit_nspanel.html new file mode 100644 index 00000000..88111b8c --- /dev/null +++ b/docker/web/nspanelmanager/web/components/nspanel_status_firmware_version/nspanel_status_firmware_version_edit_nspanel.html @@ -0,0 +1,54 @@ + + + diff --git a/docker/web/nspanelmanager/web/components/nspanel_status_firmware_version/nspanel_status_firmware_version_index.html b/docker/web/nspanelmanager/web/components/nspanel_status_firmware_version/nspanel_status_firmware_version_index.html new file mode 100644 index 00000000..a1bc0de0 --- /dev/null +++ b/docker/web/nspanelmanager/web/components/nspanel_status_firmware_version/nspanel_status_firmware_version_index.html @@ -0,0 +1,49 @@ + + + diff --git a/docker/web/nspanelmanager/web/templates/edit_nspanel.html b/docker/web/nspanelmanager/web/templates/edit_nspanel.html index 47f2ce0d..d68e0f9d 100644 --- a/docker/web/nspanelmanager/web/templates/edit_nspanel.html +++ b/docker/web/nspanelmanager/web/templates/edit_nspanel.html @@ -624,6 +624,9 @@

Screensaver outside temperature

{% component "nspanel_status_ram_usage" id=panel_info.data.id %}{% endcomponent %}
+
+ {% component "nspanel_status_firmware_version" id=panel_info.data.id %}{% endcomponent %} +
{% component "nspanel_status_temperature" id=panel_info.data.id %}{% endcomponent %}
diff --git a/docker/web/nspanelmanager/web/templates/partial/nspanel_index_view_htmx.html b/docker/web/nspanelmanager/web/templates/partial/nspanel_index_view_htmx.html index bdafc8b5..1beee583 100644 --- a/docker/web/nspanelmanager/web/templates/partial/nspanel_index_view_htmx.html +++ b/docker/web/nspanelmanager/web/templates/partial/nspanel_index_view_htmx.html @@ -71,6 +71,12 @@ {% component "nspanel_status_ram_usage" id=nspanel.data.id %}{% endcomponent %} +
+ +
+ {% component "nspanel_status_firmware_version" id=nspanel.data.id %}{% endcomponent %} +
+
+
+ {% include "partial/edit_nspanel_buttons.html" with button="button1_long" button_name="Left button long press" %} + {% include "partial/edit_nspanel_buttons.html" with button="button2_long" button_name="Right button long press" %} +
diff --git a/docker/web/nspanelmanager/web/views.py b/docker/web/nspanelmanager/web/views.py index 4431e889..d49b6c2d 100755 --- a/docker/web/nspanelmanager/web/views.py +++ b/docker/web/nspanelmanager/web/views.py @@ -384,19 +384,19 @@ def edit_nspanel(request, panel_id: int): ), "default_page": get_nspanel_setting_with_default(panel_id, "default_page", "0"), } - for button in ["button1", "button2","button1_long", "button2_long"]: + for button in ["button1", "button2", "button1_long", "button2_long"]: key = f"{button}_custom_mqtt_topic" settings[key] = get_nspanel_setting_with_default(panel_id, key, "") - + key = f"{button}_custom_mqtt_payload" settings[key] = get_nspanel_setting_with_default(panel_id, key, "") - + key = f"{button}_relay_lower_temperature" settings[key] = get_nspanel_setting_with_default(panel_id, key, "") - + key = f"{button}_relay_upper_temperature" settings[key] = get_nspanel_setting_with_default(panel_id, key, "") - + nspanel = NSPanel.objects.get(id=panel_id) panel_info = {} panel_info["data"] = nspanel @@ -418,9 +418,9 @@ def edit_nspanel(request, panel_id: int): def evaluate_button_state(button, panel_id, panel: NSPanel, request): setattr(panel, f"{button}_mode", request.POST[f"{button}_mode"]) if request.POST[f"{button}_mode"] == "1": # Detached mode - setattr(panel,f"{button}_detached_mode_light", Entity.objects.get(id=request.POST[f"{button}_detached_mode_light"])) + setattr(panel, f"{button}_detached_mode_light", Entity.objects.get(id=request.POST[f"{button}_detached_mode_light"])) else: - setattr(panel,f"{button}_detached_mode_light", None) + setattr(panel, f"{button}_detached_mode_light", None) if request.POST[f"{button}_mode"] == "2": # Custom MQTT Mode set_nspanel_setting_value(panel_id, f"{button}_custom_mqtt_topic", request.POST[f"{button}_custom_mqtt_topic"]) @@ -428,15 +428,15 @@ def evaluate_button_state(button, panel_id, panel: NSPanel, request): else: delete_nspanel_setting(panel_id, f"{button}_custom_mqtt_topic") delete_nspanel_setting(panel_id, f"{button}_custom_mqtt_payload") - def save_panel_settings(request, panel_id: int): panel = NSPanel.objects.get(id=panel_id) panel.room = Room.objects.get(id=request.POST["room_id"]) panel.friendly_name = request.POST["name"] - for button in ["button1", "button2"]: - evaluate_button_state (button, panel_id, panel, request) + for button in ["button1", "button2", "button1_long", "button2_long"]: + evaluate_button_state(button, panel_id, panel, request) + if request.POST["screen_dim_level"].strip(): set_nspanel_setting_value( panel_id, "screen_dim_level", request.POST["screen_dim_level"] @@ -783,7 +783,7 @@ def get_item(dictionary, key): except Exception as e: if type(e) != AttributeError: raise e - return getattr(dictionary,key) + return getattr(dictionary, key) def get_client_ip(request): diff --git a/protobuf_firmware/protobuf_nspanel.pb-c.c b/protobuf_firmware/protobuf_nspanel.pb-c.c index 356cd443..74f7f8f0 100644 --- a/protobuf_firmware/protobuf_nspanel.pb-c.c +++ b/protobuf_firmware/protobuf_nspanel.pb-c.c @@ -376,6 +376,12 @@ void nspanel_mqttmanager_command__button_pressed__init static const NSPanelMQTTManagerCommand__ButtonPressed init_value = NSPANEL_MQTTMANAGER_COMMAND__BUTTON_PRESSED__INIT; *message = init_value; } +void nspanel_mqttmanager_command__button_long_pressed__init + (NSPanelMQTTManagerCommand__ButtonLongPressed *message) +{ + static const NSPanelMQTTManagerCommand__ButtonLongPressed init_value = NSPANEL_MQTTMANAGER_COMMAND__BUTTON_LONG_PRESSED__INIT; + *message = init_value; +} void nspanel_mqttmanager_command__thermostat_temperature_command__init (NSPanelMQTTManagerCommand__ThermostatTemperatureCommand *message) { @@ -595,7 +601,7 @@ const ProtobufCEnumDescriptor nspanel_config__nspanel_button_mode__descriptor = nspanel_config__nspanel_button_mode__value_ranges, NULL,NULL,NULL,NULL /* reserved[1234] */ }; -static const ProtobufCFieldDescriptor nspanel_config__field_descriptors[36] = +static const ProtobufCFieldDescriptor nspanel_config__field_descriptors[38] = { { "name", @@ -873,6 +879,30 @@ static const ProtobufCFieldDescriptor nspanel_config__field_descriptors[36] = 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "button1_long_mode", + 27, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(NSPanelConfig, button1_long_mode), + &nspanel_config__nspanel_button_mode__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "button2_long_mode", + 29, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(NSPanelConfig, button2_long_mode), + &nspanel_config__nspanel_button_mode__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, { "global_scene_entity_page_ids", 30, @@ -1031,30 +1061,32 @@ static const ProtobufCFieldDescriptor nspanel_config__field_descriptors[36] = }, }; static const unsigned nspanel_config__field_indices_by_name[] = { - 32, /* field[32] = button1_lower_temperature */ + 23, /* field[23] = button1_long_mode */ + 34, /* field[34] = button1_lower_temperature */ 21, /* field[21] = button1_mode */ - 33, /* field[33] = button1_upper_temperature */ - 34, /* field[34] = button2_lower_temperature */ + 35, /* field[35] = button1_upper_temperature */ + 24, /* field[24] = button2_long_mode */ + 36, /* field[36] = button2_lower_temperature */ 22, /* field[22] = button2_mode */ - 35, /* field[35] = button2_upper_temperature */ + 37, /* field[37] = button2_upper_temperature */ 5, /* field[5] = button_long_press_time */ 13, /* field[13] = clock_us_style */ - 29, /* field[29] = default_light_brightess */ + 31, /* field[31] = default_light_brightess */ 2, /* field[2] = default_page */ 1, /* field[1] = default_room */ - 23, /* field[23] = global_scene_entity_page_ids */ - 31, /* field[31] = inside_temperature_sensor_mqtt_topic */ + 25, /* field[25] = global_scene_entity_page_ids */ + 33, /* field[33] = inside_temperature_sensor_mqtt_topic */ 15, /* field[15] = is_us_panel */ - 30, /* field[30] = locked_to_default_room */ + 32, /* field[32] = locked_to_default_room */ 4, /* field[4] = min_button_push_time */ 0, /* field[0] = name */ - 26, /* field[26] = nspanel_id */ - 24, /* field[24] = optimistic_mode */ - 25, /* field[25] = raise_light_level_to_100_above */ + 28, /* field[28] = nspanel_id */ + 26, /* field[26] = optimistic_mode */ + 27, /* field[27] = raise_light_level_to_100_above */ 18, /* field[18] = relay1_default_mode */ - 27, /* field[27] = relay1_relay_group */ + 29, /* field[29] = relay1_relay_group */ 19, /* field[19] = relay2_default_mode */ - 28, /* field[28] = relay2_relay_group */ + 30, /* field[30] = relay2_relay_group */ 17, /* field[17] = reverse_relays */ 16, /* field[16] = room_infos */ 8, /* field[8] = screen_dim_level */ @@ -1068,14 +1100,15 @@ static const unsigned nspanel_config__field_indices_by_name[] = { 20, /* field[20] = temperature_calibration */ 14, /* field[14] = use_fahrenheit */ }; -static const ProtobufCIntRange nspanel_config__number_ranges[5 + 1] = +static const ProtobufCIntRange nspanel_config__number_ranges[6 + 1] = { { 1, 0 }, { 25, 22 }, - { 30, 23 }, - { 35, 27 }, - { 37, 28 }, - { 0, 36 } + { 27, 23 }, + { 29, 24 }, + { 35, 29 }, + { 37, 30 }, + { 0, 38 } }; const ProtobufCMessageDescriptor nspanel_config__descriptor = { @@ -1085,10 +1118,10 @@ const ProtobufCMessageDescriptor nspanel_config__descriptor = "NSPanelConfig", "", sizeof(NSPanelConfig), - 36, + 38, nspanel_config__field_descriptors, nspanel_config__field_indices_by_name, - 5, nspanel_config__number_ranges, + 6, nspanel_config__number_ranges, (ProtobufCMessageInit) nspanel_config__init, NULL,NULL,NULL /* reserved[123] */ }; @@ -2568,6 +2601,44 @@ const ProtobufCMessageDescriptor nspanel_mqttmanager_command__button_pressed__de (ProtobufCMessageInit) nspanel_mqttmanager_command__button_pressed__init, NULL,NULL,NULL /* reserved[123] */ }; +static const ProtobufCFieldDescriptor nspanel_mqttmanager_command__button_long_pressed__field_descriptors[1] = +{ + { + "button_id", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(NSPanelMQTTManagerCommand__ButtonLongPressed, button_id), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned nspanel_mqttmanager_command__button_long_pressed__field_indices_by_name[] = { + 0, /* field[0] = button_id */ +}; +static const ProtobufCIntRange nspanel_mqttmanager_command__button_long_pressed__number_ranges[1 + 1] = +{ + { 2, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor nspanel_mqttmanager_command__button_long_pressed__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "NSPanelMQTTManagerCommand.ButtonLongPressed", + "ButtonLongPressed", + "NSPanelMQTTManagerCommand__ButtonLongPressed", + "", + sizeof(NSPanelMQTTManagerCommand__ButtonLongPressed), + 1, + nspanel_mqttmanager_command__button_long_pressed__field_descriptors, + nspanel_mqttmanager_command__button_long_pressed__field_indices_by_name, + 1, nspanel_mqttmanager_command__button_long_pressed__number_ranges, + (ProtobufCMessageInit) nspanel_mqttmanager_command__button_long_pressed__init, + NULL,NULL,NULL /* reserved[123] */ +}; static const ProtobufCFieldDescriptor nspanel_mqttmanager_command__thermostat_temperature_command__field_descriptors[2] = { { @@ -2713,7 +2784,7 @@ const ProtobufCEnumDescriptor nspanel_mqttmanager_command__affect_lights_options nspanel_mqttmanager_command__affect_lights_options__value_ranges, NULL,NULL,NULL,NULL /* reserved[1234] */ }; -static const ProtobufCFieldDescriptor nspanel_mqttmanager_command__field_descriptors[9] = +static const ProtobufCFieldDescriptor nspanel_mqttmanager_command__field_descriptors[10] = { { "first_page_turn_on", @@ -2788,11 +2859,23 @@ static const ProtobufCFieldDescriptor nspanel_mqttmanager_command__field_descrip 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "thermostat_temperature_command", + "button_longpressed", 7, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_MESSAGE, offsetof(NSPanelMQTTManagerCommand, command_data_case), + offsetof(NSPanelMQTTManagerCommand, button_longpressed), + &nspanel_mqttmanager_command__button_long_pressed__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "thermostat_temperature_command", + 8, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NSPanelMQTTManagerCommand, command_data_case), offsetof(NSPanelMQTTManagerCommand, thermostat_temperature_command), &nspanel_mqttmanager_command__thermostat_temperature_command__descriptor, NULL, @@ -2801,7 +2884,7 @@ static const ProtobufCFieldDescriptor nspanel_mqttmanager_command__field_descrip }, { "thermostat_command", - 8, + 9, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_MESSAGE, offsetof(NSPanelMQTTManagerCommand, command_data_case), @@ -2825,21 +2908,22 @@ static const ProtobufCFieldDescriptor nspanel_mqttmanager_command__field_descrip }, }; static const unsigned nspanel_mqttmanager_command__field_indices_by_name[] = { + 6, /* field[6] = button_longpressed */ 5, /* field[5] = button_pressed */ 1, /* field[1] = first_page_turn_off */ 0, /* field[0] = first_page_turn_on */ 2, /* field[2] = light_command */ - 8, /* field[8] = nspanel_id */ + 9, /* field[9] = nspanel_id */ 4, /* field[4] = save_scene_command */ - 7, /* field[7] = thermostat_command */ - 6, /* field[6] = thermostat_temperature_command */ + 8, /* field[8] = thermostat_command */ + 7, /* field[7] = thermostat_temperature_command */ 3, /* field[3] = toggle_entity_from_entities_page */ }; static const ProtobufCIntRange nspanel_mqttmanager_command__number_ranges[2 + 1] = { { 1, 0 }, - { 100, 8 }, - { 0, 9 } + { 100, 9 }, + { 0, 10 } }; const ProtobufCMessageDescriptor nspanel_mqttmanager_command__descriptor = { @@ -2849,7 +2933,7 @@ const ProtobufCMessageDescriptor nspanel_mqttmanager_command__descriptor = "NSPanelMQTTManagerCommand", "", sizeof(NSPanelMQTTManagerCommand), - 9, + 10, nspanel_mqttmanager_command__field_descriptors, nspanel_mqttmanager_command__field_indices_by_name, 2, nspanel_mqttmanager_command__number_ranges, diff --git a/protobuf_firmware/protobuf_nspanel.pb-c.h b/protobuf_firmware/protobuf_nspanel.pb-c.h index 7a468a50..367a4f03 100644 --- a/protobuf_firmware/protobuf_nspanel.pb-c.h +++ b/protobuf_firmware/protobuf_nspanel.pb-c.h @@ -32,6 +32,7 @@ typedef struct NSPanelMQTTManagerCommand__LightCommand NSPanelMQTTManagerCommand typedef struct NSPanelMQTTManagerCommand__ToggleEntityFromEntitiesPage NSPanelMQTTManagerCommand__ToggleEntityFromEntitiesPage; typedef struct NSPanelMQTTManagerCommand__SaveSceneCommand NSPanelMQTTManagerCommand__SaveSceneCommand; typedef struct NSPanelMQTTManagerCommand__ButtonPressed NSPanelMQTTManagerCommand__ButtonPressed; +typedef struct NSPanelMQTTManagerCommand__ButtonLongPressed NSPanelMQTTManagerCommand__ButtonLongPressed; typedef struct NSPanelMQTTManagerCommand__ThermostatTemperatureCommand NSPanelMQTTManagerCommand__ThermostatTemperatureCommand; typedef struct NSPanelMQTTManagerCommand__ThermostatCommand NSPanelMQTTManagerCommand__ThermostatCommand; @@ -137,6 +138,8 @@ struct NSPanelConfig int32_t temperature_calibration; NSPanelConfig__NSPanelButtonMode button1_mode; NSPanelConfig__NSPanelButtonMode button2_mode; + NSPanelConfig__NSPanelButtonMode button1_long_mode; + NSPanelConfig__NSPanelButtonMode button2_long_mode; size_t n_global_scene_entity_page_ids; int32_t *global_scene_entity_page_ids; protobuf_c_boolean optimistic_mode; @@ -174,7 +177,7 @@ struct NSPanelConfig }; #define NSPANEL_CONFIG__INIT \ { PROTOBUF_C_MESSAGE_INIT (&nspanel_config__descriptor) \ - , (char *)protobuf_c_empty_string, 0, NSPANEL_CONFIG__NSPANEL_DEFAULT_PAGE__HOME, 0, 0, 0, 0, 0, 0, 0, NSPANEL_CONFIG__NSPANEL_SCREENSAVER_MODE__WEATHER_WITH_BACKGROUND, 0, 0, 0, 0, 0, 0,NULL, 0, 0, 0, 0, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, 0,NULL, 0, 0, 0, 0,NULL, 0,NULL, 0, 0, (char *)protobuf_c_empty_string, 0, 0, 0, 0 } + , (char *)protobuf_c_empty_string, 0, NSPANEL_CONFIG__NSPANEL_DEFAULT_PAGE__HOME, 0, 0, 0, 0, 0, 0, 0, NSPANEL_CONFIG__NSPANEL_SCREENSAVER_MODE__WEATHER_WITH_BACKGROUND, 0, 0, 0, 0, 0, 0,NULL, 0, 0, 0, 0, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, 0,NULL, 0, 0, 0, 0,NULL, 0,NULL, 0, 0, (char *)protobuf_c_empty_string, 0, 0, 0, 0 } struct NSPanelWarning @@ -416,6 +419,16 @@ struct NSPanelMQTTManagerCommand__ButtonPressed , 0 } +struct NSPanelMQTTManagerCommand__ButtonLongPressed +{ + ProtobufCMessage base; + int32_t button_id; +}; +#define NSPANEL_MQTTMANAGER_COMMAND__BUTTON_LONG_PRESSED__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&nspanel_mqttmanager_command__button_long_pressed__descriptor) \ + , 0 } + + struct NSPanelMQTTManagerCommand__ThermostatTemperatureCommand { ProtobufCMessage base; @@ -447,8 +460,9 @@ typedef enum { NSPANEL_MQTTMANAGER_COMMAND__COMMAND_DATA_TOGGLE_ENTITY_FROM_ENTITIES_PAGE = 4, NSPANEL_MQTTMANAGER_COMMAND__COMMAND_DATA_SAVE_SCENE_COMMAND = 5, NSPANEL_MQTTMANAGER_COMMAND__COMMAND_DATA_BUTTON_PRESSED = 6, - NSPANEL_MQTTMANAGER_COMMAND__COMMAND_DATA_THERMOSTAT_TEMPERATURE_COMMAND = 7, - NSPANEL_MQTTMANAGER_COMMAND__COMMAND_DATA_THERMOSTAT_COMMAND = 8 + NSPANEL_MQTTMANAGER_COMMAND__COMMAND_DATA_BUTTON_LONGPRESSED = 7, + NSPANEL_MQTTMANAGER_COMMAND__COMMAND_DATA_THERMOSTAT_TEMPERATURE_COMMAND = 8, + NSPANEL_MQTTMANAGER_COMMAND__COMMAND_DATA_THERMOSTAT_COMMAND = 9 PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(NSPANEL_MQTTMANAGER_COMMAND__COMMAND_DATA__CASE) } NSPanelMQTTManagerCommand__CommandDataCase; @@ -467,6 +481,7 @@ struct NSPanelMQTTManagerCommand NSPanelMQTTManagerCommand__ToggleEntityFromEntitiesPage *toggle_entity_from_entities_page; NSPanelMQTTManagerCommand__SaveSceneCommand *save_scene_command; NSPanelMQTTManagerCommand__ButtonPressed *button_pressed; + NSPanelMQTTManagerCommand__ButtonLongPressed *button_longpressed; NSPanelMQTTManagerCommand__ThermostatTemperatureCommand *thermostat_temperature_command; NSPanelMQTTManagerCommand__ThermostatCommand *thermostat_command; }; @@ -636,6 +651,9 @@ void nspanel_mqttmanager_command__save_scene_command__init /* NSPanelMQTTManagerCommand__ButtonPressed methods */ void nspanel_mqttmanager_command__button_pressed__init (NSPanelMQTTManagerCommand__ButtonPressed *message); +/* NSPanelMQTTManagerCommand__ButtonLongPressed methods */ +void nspanel_mqttmanager_command__button_long_pressed__init + (NSPanelMQTTManagerCommand__ButtonLongPressed *message); /* NSPanelMQTTManagerCommand__ThermostatTemperatureCommand methods */ void nspanel_mqttmanager_command__thermostat_temperature_command__init (NSPanelMQTTManagerCommand__ThermostatTemperatureCommand *message); @@ -711,6 +729,9 @@ typedef void (*NSPanelMQTTManagerCommand__SaveSceneCommand_Closure) typedef void (*NSPanelMQTTManagerCommand__ButtonPressed_Closure) (const NSPanelMQTTManagerCommand__ButtonPressed *message, void *closure_data); +typedef void (*NSPanelMQTTManagerCommand__ButtonLongPressed_Closure) + (const NSPanelMQTTManagerCommand__ButtonLongPressed *message, + void *closure_data); typedef void (*NSPanelMQTTManagerCommand__ThermostatTemperatureCommand_Closure) (const NSPanelMQTTManagerCommand__ThermostatTemperatureCommand *message, void *closure_data); @@ -748,6 +769,7 @@ extern const ProtobufCMessageDescriptor nspanel_mqttmanager_command__light_comma extern const ProtobufCMessageDescriptor nspanel_mqttmanager_command__toggle_entity_from_entities_page__descriptor; extern const ProtobufCMessageDescriptor nspanel_mqttmanager_command__save_scene_command__descriptor; extern const ProtobufCMessageDescriptor nspanel_mqttmanager_command__button_pressed__descriptor; +extern const ProtobufCMessageDescriptor nspanel_mqttmanager_command__button_long_pressed__descriptor; extern const ProtobufCMessageDescriptor nspanel_mqttmanager_command__thermostat_temperature_command__descriptor; extern const ProtobufCMessageDescriptor nspanel_mqttmanager_command__thermostat_command__descriptor; extern const ProtobufCEnumDescriptor nspanel_mqttmanager_command__affect_lights_options__descriptor; From d50b33a5053f66cc148b3673e909fcbc6943781c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haa=C3=9F?= Date: Mon, 26 Jan 2026 08:29:41 +0100 Subject: [PATCH 4/9] extract firmware and HMI path into macro --- .../mqtt_manager_config.cpp | 28 +++++++++---------- .../mqtt_manager_config.hpp | 2 ++ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/docker/MQTTManager/include/mqtt_manager_config/mqtt_manager_config.cpp b/docker/MQTTManager/include/mqtt_manager_config/mqtt_manager_config.cpp index 4139693b..c01b5b32 100644 --- a/docker/MQTTManager/include/mqtt_manager_config/mqtt_manager_config.cpp +++ b/docker/MQTTManager/include/mqtt_manager_config/mqtt_manager_config.cpp @@ -166,7 +166,7 @@ void MqttManagerConfig::update_firmware_checksum() { std::lock_guard lock_guard(MqttManagerConfig::_md5_checksum_files_mutex); SPDLOG_INFO("Updating/calculating MD5 checksums for all firmware files."); - auto firmware_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/firmware.bin"); + auto firmware_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/firmware.bin")); if (firmware_checksum.has_value()) { MqttManagerConfig::_md5_checksum_firmware = firmware_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for firmware was not able to be calculated."); @@ -176,7 +176,7 @@ void MqttManagerConfig::update_firmware_checksum() { SPDLOG_ERROR("Failed to calculate checksum for firmware!"); } - auto littlefs_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/data_file.bin"); + auto littlefs_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/data_file.bin")); if (littlefs_checksum.has_value()) { MqttManagerConfig::_md5_checksum_littlefs = littlefs_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for littlefs/data file was not able to be calculated."); @@ -191,7 +191,7 @@ void MqttManagerConfig::update_tft_checksums() { std::lock_guard lock_guard(MqttManagerConfig::_md5_checksum_files_mutex); SPDLOG_INFO("Updating/calculating MD5 checksums for all .tft GUI files."); - auto eu_tft1_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/HMI_files/tft_automation/eu/output_tft1/gui.tft"); + auto eu_tft1_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/HMI_files/tft_automation/eu/output_tft1/gui.tft")); if (eu_tft1_checksum.has_value()) { MqttManagerConfig::_md5_checksum_eu_tft1 = eu_tft1_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for EU tft1 was not able to be calculated."); @@ -201,7 +201,7 @@ void MqttManagerConfig::update_tft_checksums() { SPDLOG_ERROR("Failed to calculate checksum for EU TFT1 Nextion GUI file!"); } - auto eu_tft2_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/HMI_files/tft_automation/eu/output_tft2/gui.tft"); + auto eu_tft2_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/HMI_files/tft_automation/eu/output_tft2/gui.tft")); if (eu_tft2_checksum.has_value()) { MqttManagerConfig::_md5_checksum_eu_tft2 = eu_tft2_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for EU tft2 was not able to be calculated."); @@ -211,7 +211,7 @@ void MqttManagerConfig::update_tft_checksums() { SPDLOG_ERROR("Failed to calculate checksum for EU TFT2 Nextion GUI file!"); } - auto eu_tft3_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/HMI_files/tft_automation/eu/output_tft3/gui.tft"); + auto eu_tft3_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/HMI_files/tft_automation/eu/output_tft3/gui.tft")); if (eu_tft3_checksum.has_value()) { MqttManagerConfig::_md5_checksum_eu_tft3 = eu_tft3_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for EU tft3 was not able to be calculated."); @@ -221,7 +221,7 @@ void MqttManagerConfig::update_tft_checksums() { SPDLOG_ERROR("Failed to calculate checksum for EU TFT3 Nextion GUI file!"); } - auto eu_tft4_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/HMI_files/tft_automation/eu/output_tft4/gui.tft"); + auto eu_tft4_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/HMI_files/tft_automation/eu/output_tft4/gui.tft")); if (eu_tft4_checksum.has_value()) { MqttManagerConfig::_md5_checksum_eu_tft4 = eu_tft4_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for EU tft4 was not able to be calculated."); @@ -231,7 +231,7 @@ void MqttManagerConfig::update_tft_checksums() { SPDLOG_ERROR("Failed to calculate checksum for EU TFT4 Nextion GUI file!"); } - auto us_tft1_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/HMI_files/tft_automation/us/output_tft1/gui.tft"); + auto us_tft1_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/HMI_files/tft_automation/us/output_tft1/gui.tft")); if (us_tft1_checksum.has_value()) { MqttManagerConfig::_md5_checksum_us_tft1 = us_tft1_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for US tft1 was not able to be calculated."); @@ -241,7 +241,7 @@ void MqttManagerConfig::update_tft_checksums() { SPDLOG_ERROR("Failed to calculate checksum for US TFT1 Nextion GUI file!"); } - auto us_tft2_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/HMI_files/tft_automation/us/output_tft2/gui.tft"); + auto us_tft2_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/HMI_files/tft_automation/us/output_tft2/gui.tft")); if (us_tft2_checksum.has_value()) { MqttManagerConfig::_md5_checksum_us_tft2 = us_tft2_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for US tft2 was not able to be calculated."); @@ -251,7 +251,7 @@ void MqttManagerConfig::update_tft_checksums() { SPDLOG_ERROR("Failed to calculate checksum for US TFT2 Nextion GUI file!"); } - auto us_tft3_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/HMI_files/tft_automation/us/output_tft3/gui.tft"); + auto us_tft3_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/HMI_files/tft_automation/us/output_tft3/gui.tft")); if (us_tft3_checksum.has_value()) { MqttManagerConfig::_md5_checksum_us_tft3 = us_tft3_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for US tft3 was not able to be calculated."); @@ -261,7 +261,7 @@ void MqttManagerConfig::update_tft_checksums() { SPDLOG_ERROR("Failed to calculate checksum for US TFT3 Nextion GUI file!"); } - auto us_tft4_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/HMI_files/tft_automation/us/output_tft4/gui.tft"); + auto us_tft4_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/HMI_files/tft_automation/us/output_tft4/gui.tft")); if (us_tft4_checksum.has_value()) { MqttManagerConfig::_md5_checksum_us_tft4 = us_tft4_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for US tft4 was not able to be calculated."); @@ -271,7 +271,7 @@ void MqttManagerConfig::update_tft_checksums() { SPDLOG_ERROR("Failed to calculate checksum for US TFT4 Nextion GUI file!"); } - auto us_tft1_horizontal_mirrored_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/HMI_files/tft_automation/us_horizontal_mirrored/output_tft1/gui.tft"); + auto us_tft1_horizontal_mirrored_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/HMI_files/tft_automation/us_horizontal_mirrored/output_tft1/gui.tft")); if (us_tft1_horizontal_mirrored_checksum.has_value()) { MqttManagerConfig::_md5_checksum_us_horizontal_mirrored_tft1 = us_tft1_horizontal_mirrored_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for US tft1 (mirrored) was not able to be calculated."); @@ -281,7 +281,7 @@ void MqttManagerConfig::update_tft_checksums() { SPDLOG_ERROR("Failed to calculate checksum for US landscape mirrored TFT1 Nextion GUI file!"); } - auto us_tft2_horizontal_mirrored_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/HMI_files/tft_automation/us_horizontal_mirrored/output_tft2/gui.tft"); + auto us_tft2_horizontal_mirrored_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/HMI_files/tft_automation/us_horizontal_mirrored/output_tft2/gui.tft")); if (us_tft2_horizontal_mirrored_checksum.has_value()) { MqttManagerConfig::_md5_checksum_us_horizontal_mirrored_tft2 = us_tft2_horizontal_mirrored_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for US tft2 (mirrored) was not able to be calculated."); @@ -291,7 +291,7 @@ void MqttManagerConfig::update_tft_checksums() { SPDLOG_ERROR("Failed to calculate checksum for US landscape mirrored TFT2 Nextion GUI file!"); } - auto us_tft3_horizontal_mirrored_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/HMI_files/tft_automation/us_horizontal_mirrored/output_tft3/gui.tft"); + auto us_tft3_horizontal_mirrored_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/HMI_files/tft_automation/us_horizontal_mirrored/output_tft3/gui.tft")); if (us_tft3_horizontal_mirrored_checksum.has_value()) { MqttManagerConfig::_md5_checksum_us_horizontal_mirrored_tft3 = us_tft3_horizontal_mirrored_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for US tft3 (mirrored) was not able to be calculated."); @@ -301,7 +301,7 @@ void MqttManagerConfig::update_tft_checksums() { SPDLOG_ERROR("Failed to calculate checksum for US landscape mirrored TFT3 Nextion GUI file!"); } - auto us_tft4_horizontal_mirrored_checksum = MqttManagerConfig::_get_file_md5_checksum("/usr/src/app/nspanelmanager/HMI_files/tft_automation/us_horizontal_mirrored/output_tft4/gui.tft"); + auto us_tft4_horizontal_mirrored_checksum = MqttManagerConfig::_get_file_md5_checksum(PREPEND_HMI_LOCATION("/HMI_files/tft_automation/us_horizontal_mirrored/output_tft4/gui.tft")); if (us_tft4_horizontal_mirrored_checksum.has_value()) { MqttManagerConfig::_md5_checksum_us_horizontal_mirrored_tft4 = us_tft4_horizontal_mirrored_checksum.value(); WebsocketServer::remove_warning("MD5 checksum for US tft4 (mirrored) was not able to be calculated."); diff --git a/docker/MQTTManager/include/mqtt_manager_config/mqtt_manager_config.hpp b/docker/MQTTManager/include/mqtt_manager_config/mqtt_manager_config.hpp index 22819b45..5a42faee 100644 --- a/docker/MQTTManager/include/mqtt_manager_config/mqtt_manager_config.hpp +++ b/docker/MQTTManager/include/mqtt_manager_config/mqtt_manager_config.hpp @@ -18,6 +18,8 @@ #include #endif +#define PREPEND_HMI_LOCATION(file) "/usr/src/app/nspanelmanager" file + enum LightTurnOnBehaviour { COLOR_TEMPERATURE, RESTORE_PREVIOUS, From 69dbf56be0ab4ad72e619084d9921c122fea4d2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haa=C3=9F?= Date: Wed, 28 Jan 2026 14:14:40 +0100 Subject: [PATCH 5/9] UI improvement: add group box around button config --- .../web/templates/partial/edit_nspanel_buttons.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docker/web/nspanelmanager/web/templates/partial/edit_nspanel_buttons.html b/docker/web/nspanelmanager/web/templates/partial/edit_nspanel_buttons.html index 7c0c62bc..1786be93 100644 --- a/docker/web/nspanelmanager/web/templates/partial/edit_nspanel_buttons.html +++ b/docker/web/nspanelmanager/web/templates/partial/edit_nspanel_buttons.html @@ -1,5 +1,5 @@ - -
+ +
- {% with button_mode=button|add:"_mode" %}asdf + {% with button_mode=button|add:"_mode" %} @@ -149,4 +149,37 @@
+ +
diff --git a/docker/web/nspanelmanager/web/views.py b/docker/web/nspanelmanager/web/views.py index d49b6c2d..e79b0896 100755 --- a/docker/web/nspanelmanager/web/views.py +++ b/docker/web/nspanelmanager/web/views.py @@ -397,6 +397,10 @@ def edit_nspanel(request, panel_id: int): key = f"{button}_relay_upper_temperature" settings[key] = get_nspanel_setting_with_default(panel_id, key, "") + key = f"{button}_fallback_mode" + settings[key] = get_nspanel_setting_with_default(panel_id, key, "0") + + nspanel = NSPanel.objects.get(id=panel_id) panel_info = {} panel_info["data"] = nspanel @@ -428,6 +432,8 @@ def evaluate_button_state(button, panel_id, panel: NSPanel, request): else: delete_nspanel_setting(panel_id, f"{button}_custom_mqtt_topic") delete_nspanel_setting(panel_id, f"{button}_custom_mqtt_payload") + set_nspanel_setting_value(panel_id, f"{button}_fallback_mode", request.POST[f"{button}_fallback_mode"]) + def save_panel_settings(request, panel_id: int): diff --git a/protobuf_firmware/protobuf_nspanel.pb-c.c b/protobuf_firmware/protobuf_nspanel.pb-c.c index 74f7f8f0..51c338b6 100644 --- a/protobuf_firmware/protobuf_nspanel.pb-c.c +++ b/protobuf_firmware/protobuf_nspanel.pb-c.c @@ -601,7 +601,37 @@ const ProtobufCEnumDescriptor nspanel_config__nspanel_button_mode__descriptor = nspanel_config__nspanel_button_mode__value_ranges, NULL,NULL,NULL,NULL /* reserved[1234] */ }; -static const ProtobufCFieldDescriptor nspanel_config__field_descriptors[38] = +static const ProtobufCEnumValue nspanel_config__nspanel_button_fallback_mode__enum_values_by_number[3] = +{ + { "DISABLED", "NSPANEL_CONFIG__NSPANEL_BUTTON_FALLBACK_MODE__DISABLED", 0 }, + { "TOGGLE_RELAY1", "NSPANEL_CONFIG__NSPANEL_BUTTON_FALLBACK_MODE__TOGGLE_RELAY1", 1 }, + { "TOGLLE_RELAY2", "NSPANEL_CONFIG__NSPANEL_BUTTON_FALLBACK_MODE__TOGLLE_RELAY2", 2 }, +}; +static const ProtobufCIntRange nspanel_config__nspanel_button_fallback_mode__value_ranges[] = { +{0, 0},{0, 3} +}; +static const ProtobufCEnumValueIndex nspanel_config__nspanel_button_fallback_mode__enum_values_by_name[3] = +{ + { "DISABLED", 0 }, + { "TOGGLE_RELAY1", 1 }, + { "TOGLLE_RELAY2", 2 }, +}; +const ProtobufCEnumDescriptor nspanel_config__nspanel_button_fallback_mode__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "NSPanelConfig.NSPanelButtonFallbackMode", + "NSPanelButtonFallbackMode", + "NSPanelConfig__NSPanelButtonFallbackMode", + "", + 3, + nspanel_config__nspanel_button_fallback_mode__enum_values_by_number, + 3, + nspanel_config__nspanel_button_fallback_mode__enum_values_by_name, + 1, + nspanel_config__nspanel_button_fallback_mode__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCFieldDescriptor nspanel_config__field_descriptors[42] = { { "name", @@ -867,9 +897,21 @@ static const ProtobufCFieldDescriptor nspanel_config__field_descriptors[38] = 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "button1_fallback_mode", + 23, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(NSPanelConfig, button1_fallback_mode), + &nspanel_config__nspanel_button_fallback_mode__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, { "button2_mode", - 25, + 24, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_ENUM, 0, /* quantifier_offset */ @@ -879,9 +921,21 @@ static const ProtobufCFieldDescriptor nspanel_config__field_descriptors[38] = 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "button2_fallback_mode", + 25, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(NSPanelConfig, button2_fallback_mode), + &nspanel_config__nspanel_button_fallback_mode__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, { "button1_long_mode", - 27, + 26, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_ENUM, 0, /* quantifier_offset */ @@ -891,9 +945,21 @@ static const ProtobufCFieldDescriptor nspanel_config__field_descriptors[38] = 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "button1_long_fallback_mode", + 27, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(NSPanelConfig, button1_long_fallback_mode), + &nspanel_config__nspanel_button_fallback_mode__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, { "button2_long_mode", - 29, + 28, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_ENUM, 0, /* quantifier_offset */ @@ -903,6 +969,18 @@ static const ProtobufCFieldDescriptor nspanel_config__field_descriptors[38] = 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "button2_long_fallback_mode", + 29, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(NSPanelConfig, button2_long_fallback_mode), + &nspanel_config__nspanel_button_fallback_mode__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, { "global_scene_entity_page_ids", 30, @@ -1061,32 +1139,36 @@ static const ProtobufCFieldDescriptor nspanel_config__field_descriptors[38] = }, }; static const unsigned nspanel_config__field_indices_by_name[] = { - 23, /* field[23] = button1_long_mode */ - 34, /* field[34] = button1_lower_temperature */ + 22, /* field[22] = button1_fallback_mode */ + 26, /* field[26] = button1_long_fallback_mode */ + 25, /* field[25] = button1_long_mode */ + 38, /* field[38] = button1_lower_temperature */ 21, /* field[21] = button1_mode */ - 35, /* field[35] = button1_upper_temperature */ - 24, /* field[24] = button2_long_mode */ - 36, /* field[36] = button2_lower_temperature */ - 22, /* field[22] = button2_mode */ - 37, /* field[37] = button2_upper_temperature */ + 39, /* field[39] = button1_upper_temperature */ + 24, /* field[24] = button2_fallback_mode */ + 28, /* field[28] = button2_long_fallback_mode */ + 27, /* field[27] = button2_long_mode */ + 40, /* field[40] = button2_lower_temperature */ + 23, /* field[23] = button2_mode */ + 41, /* field[41] = button2_upper_temperature */ 5, /* field[5] = button_long_press_time */ 13, /* field[13] = clock_us_style */ - 31, /* field[31] = default_light_brightess */ + 35, /* field[35] = default_light_brightess */ 2, /* field[2] = default_page */ 1, /* field[1] = default_room */ - 25, /* field[25] = global_scene_entity_page_ids */ - 33, /* field[33] = inside_temperature_sensor_mqtt_topic */ + 29, /* field[29] = global_scene_entity_page_ids */ + 37, /* field[37] = inside_temperature_sensor_mqtt_topic */ 15, /* field[15] = is_us_panel */ - 32, /* field[32] = locked_to_default_room */ + 36, /* field[36] = locked_to_default_room */ 4, /* field[4] = min_button_push_time */ 0, /* field[0] = name */ - 28, /* field[28] = nspanel_id */ - 26, /* field[26] = optimistic_mode */ - 27, /* field[27] = raise_light_level_to_100_above */ + 32, /* field[32] = nspanel_id */ + 30, /* field[30] = optimistic_mode */ + 31, /* field[31] = raise_light_level_to_100_above */ 18, /* field[18] = relay1_default_mode */ - 29, /* field[29] = relay1_relay_group */ + 33, /* field[33] = relay1_relay_group */ 19, /* field[19] = relay2_default_mode */ - 30, /* field[30] = relay2_relay_group */ + 34, /* field[34] = relay2_relay_group */ 17, /* field[17] = reverse_relays */ 16, /* field[16] = room_infos */ 8, /* field[8] = screen_dim_level */ @@ -1100,15 +1182,12 @@ static const unsigned nspanel_config__field_indices_by_name[] = { 20, /* field[20] = temperature_calibration */ 14, /* field[14] = use_fahrenheit */ }; -static const ProtobufCIntRange nspanel_config__number_ranges[6 + 1] = +static const ProtobufCIntRange nspanel_config__number_ranges[3 + 1] = { { 1, 0 }, - { 25, 22 }, - { 27, 23 }, - { 29, 24 }, - { 35, 29 }, - { 37, 30 }, - { 0, 38 } + { 35, 33 }, + { 37, 34 }, + { 0, 42 } }; const ProtobufCMessageDescriptor nspanel_config__descriptor = { @@ -1118,10 +1197,10 @@ const ProtobufCMessageDescriptor nspanel_config__descriptor = "NSPanelConfig", "", sizeof(NSPanelConfig), - 38, + 42, nspanel_config__field_descriptors, nspanel_config__field_indices_by_name, - 6, nspanel_config__number_ranges, + 3, nspanel_config__number_ranges, (ProtobufCMessageInit) nspanel_config__init, NULL,NULL,NULL /* reserved[123] */ }; diff --git a/protobuf_firmware/protobuf_nspanel.pb-c.h b/protobuf_firmware/protobuf_nspanel.pb-c.h index 367a4f03..2f5c15cb 100644 --- a/protobuf_firmware/protobuf_nspanel.pb-c.h +++ b/protobuf_firmware/protobuf_nspanel.pb-c.h @@ -68,6 +68,12 @@ typedef enum _NSPanelConfig__NSPanelButtonMode { NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__THERMOSTAT_COOL = 4 PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(NSPANEL_CONFIG__NSPANEL_BUTTON_MODE) } NSPanelConfig__NSPanelButtonMode; +typedef enum _NSPanelConfig__NSPanelButtonFallbackMode { + NSPANEL_CONFIG__NSPANEL_BUTTON_FALLBACK_MODE__DISABLED = 0, + NSPANEL_CONFIG__NSPANEL_BUTTON_FALLBACK_MODE__TOGGLE_RELAY1 = 1, + NSPANEL_CONFIG__NSPANEL_BUTTON_FALLBACK_MODE__TOGLLE_RELAY2 = 2 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(NSPANEL_CONFIG__NSPANEL_BUTTON_FALLBACK_MODE) +} NSPanelConfig__NSPanelButtonFallbackMode; typedef enum _NSPanelStatusReport__State { NSPANEL_STATUS_REPORT__STATE__ONLINE = 0, NSPANEL_STATUS_REPORT__STATE__OFFLINE = 1, @@ -137,9 +143,13 @@ struct NSPanelConfig protobuf_c_boolean relay2_default_mode; int32_t temperature_calibration; NSPanelConfig__NSPanelButtonMode button1_mode; + NSPanelConfig__NSPanelButtonFallbackMode button1_fallback_mode; NSPanelConfig__NSPanelButtonMode button2_mode; + NSPanelConfig__NSPanelButtonFallbackMode button2_fallback_mode; NSPanelConfig__NSPanelButtonMode button1_long_mode; + NSPanelConfig__NSPanelButtonFallbackMode button1_long_fallback_mode; NSPanelConfig__NSPanelButtonMode button2_long_mode; + NSPanelConfig__NSPanelButtonFallbackMode button2_long_fallback_mode; size_t n_global_scene_entity_page_ids; int32_t *global_scene_entity_page_ids; protobuf_c_boolean optimistic_mode; @@ -177,7 +187,7 @@ struct NSPanelConfig }; #define NSPANEL_CONFIG__INIT \ { PROTOBUF_C_MESSAGE_INIT (&nspanel_config__descriptor) \ - , (char *)protobuf_c_empty_string, 0, NSPANEL_CONFIG__NSPANEL_DEFAULT_PAGE__HOME, 0, 0, 0, 0, 0, 0, 0, NSPANEL_CONFIG__NSPANEL_SCREENSAVER_MODE__WEATHER_WITH_BACKGROUND, 0, 0, 0, 0, 0, 0,NULL, 0, 0, 0, 0, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, 0,NULL, 0, 0, 0, 0,NULL, 0,NULL, 0, 0, (char *)protobuf_c_empty_string, 0, 0, 0, 0 } + , (char *)protobuf_c_empty_string, 0, NSPANEL_CONFIG__NSPANEL_DEFAULT_PAGE__HOME, 0, 0, 0, 0, 0, 0, 0, NSPANEL_CONFIG__NSPANEL_SCREENSAVER_MODE__WEATHER_WITH_BACKGROUND, 0, 0, 0, 0, 0, 0,NULL, 0, 0, 0, 0, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, NSPANEL_CONFIG__NSPANEL_BUTTON_FALLBACK_MODE__DISABLED, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, NSPANEL_CONFIG__NSPANEL_BUTTON_FALLBACK_MODE__DISABLED, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, NSPANEL_CONFIG__NSPANEL_BUTTON_FALLBACK_MODE__DISABLED, NSPANEL_CONFIG__NSPANEL_BUTTON_MODE__DIRECT, NSPANEL_CONFIG__NSPANEL_BUTTON_FALLBACK_MODE__DISABLED, 0,NULL, 0, 0, 0, 0,NULL, 0,NULL, 0, 0, (char *)protobuf_c_empty_string, 0, 0, 0, 0 } struct NSPanelWarning @@ -753,6 +763,7 @@ extern const ProtobufCMessageDescriptor nspanel_config__room_info__descriptor; extern const ProtobufCEnumDescriptor nspanel_config__nspanel_default_page__descriptor; extern const ProtobufCEnumDescriptor nspanel_config__nspanel_screensaver_mode__descriptor; extern const ProtobufCEnumDescriptor nspanel_config__nspanel_button_mode__descriptor; +extern const ProtobufCEnumDescriptor nspanel_config__nspanel_button_fallback_mode__descriptor; extern const ProtobufCMessageDescriptor nspanel_warning__descriptor; extern const ProtobufCMessageDescriptor nspanel_status_report__descriptor; extern const ProtobufCEnumDescriptor nspanel_status_report__state__descriptor; From 0652e2f03a6904b0b1071700cb10ca4c9752e2ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haa=C3=9F?= Date: Wed, 28 Jan 2026 21:26:22 +0100 Subject: [PATCH 7/9] fix bug: mqttmanager cannot find configured entity bc. type filter was wrong --- docker/MQTTManager/include/entity_manager/entity_manager.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/MQTTManager/include/entity_manager/entity_manager.hpp b/docker/MQTTManager/include/entity_manager/entity_manager.hpp index bf80f7b5..af6a4ef5 100644 --- a/docker/MQTTManager/include/entity_manager/entity_manager.hpp +++ b/docker/MQTTManager/include/entity_manager/entity_manager.hpp @@ -137,7 +137,7 @@ class EntityManager { std::lock_guard mutex_guard(EntityManager::_entities_mutex); auto rit = EntityManager::_entities.cbegin(); while (rit != EntityManager::_entities.cend()) { - if ((type != MQTT_MANAGER_ENTITY_TYPE::ANY && (*rit)->get_type() == type) && (*rit)->get_id() == id) { + if ((type == MQTT_MANAGER_ENTITY_TYPE::ANY || (*rit)->get_type() == type) && (*rit)->get_id() == id) { return std::static_pointer_cast(*rit); } else { ++rit; From a896eab6c5c5547ecac3a8e3be7befaef2588a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haa=C3=9F?= Date: Wed, 28 Jan 2026 21:27:18 +0100 Subject: [PATCH 8/9] renamed detached_mode_light to detached_mode_entity in frontend, to match expected backend name --- docker/web/nspanelmanager/web/api.py | 10 ++--- .../nspanelmanager/web/static/edit_nspanel.js | 40 ++++++++++--------- .../partial/edit_nspanel_buttons.html | 16 ++++---- docker/web/nspanelmanager/web/views.py | 4 +- 4 files changed, 37 insertions(+), 33 deletions(-) diff --git a/docker/web/nspanelmanager/web/api.py b/docker/web/nspanelmanager/web/api.py index a1fe3ce9..f20815db 100644 --- a/docker/web/nspanelmanager/web/api.py +++ b/docker/web/nspanelmanager/web/api.py @@ -324,13 +324,13 @@ def get_nspanel_config(request): nspanel.id, "button2_mqtt_payload", "" ) - if nspanel.button1_detached_mode_light: - base["button1_detached_light"] = nspanel.button1_detached_mode_light.id + if nspanel.button1_detached_mode_entity: + base["button1_detached_light"] = nspanel.button1_detached_mode_entity.id else: - base["button1_detached_mode_light"] = -1 + base["button1_detached_mode_entity"] = -1 - if nspanel.button2_detached_mode_light: - base["button2_detached_light"] = nspanel.button2_detached_mode_light.id + if nspanel.button2_detached_mode_entity: + base["button2_detached_light"] = nspanel.button2_detached_mode_entity.id else: base["button2_detached_light"] = -1 base["rooms"] = [] diff --git a/docker/web/nspanelmanager/web/static/edit_nspanel.js b/docker/web/nspanelmanager/web/static/edit_nspanel.js index 30a7600f..776ba3d1 100644 --- a/docker/web/nspanelmanager/web/static/edit_nspanel.js +++ b/docker/web/nspanelmanager/web/static/edit_nspanel.js @@ -41,10 +41,10 @@ function push_log_message_to_view(data) { function update_shown_elements(button) { $(`#${button}_detached_mode_controls`).addClass("hidden"); - $(`#${button}_detached_mode_light`).addClass("hidden"); + $(`#${button}_detached_mode_entity`).addClass("hidden"); $(`#${button}_mqtt_mode_controls`).addClass("hidden"); $(`#${button}_thermostat_mode_controls`).addClass("hidden"); - $(`#${button}_detached_mode_light`).prop("required", false); + $(`#${button}_detached_mode_entity`).prop("required", false); $(`#${button}_relay_lower_temperature`).prop("required", false); $(`#${button}_relay_upper_temperature`).prop("required", false); @@ -53,8 +53,8 @@ function update_shown_elements(button) { } else if ($(`#${button}_mode`).val() == 1) { // Detached mode $(`#${button}_detached_mode_controls`).removeClass("hidden"); - $(`#${button}_detached_mode_light`).prop("required", true); - $(`#${button}_detached_mode_light`).removeClass("hidden"); + $(`#${button}_detached_mode_entity`).prop("required", true); + $(`#${button}_detached_mode_entity`).removeClass("hidden"); } else if ($(`#${button}_mode`).val() == 2) { // MQTT mode $(`#${button}_mqtt_mode_controls`).removeClass("hidden"); @@ -78,28 +78,28 @@ function update_shown_elements(button) { // Update shown lights depending on selected room var selected_room_id = $(`#${button}_detached_mode_room`).val(); $( - `.${button}_detached_mode_light_option[data-room-id='` + - selected_room_id + - "']", + `.${button}_detached_mode_entity_option[data-room-id='` + + selected_room_id + + "']", ).show(); $( - `.${button}_detached_mode_light_option[data-room-id!='` + - selected_room_id + - "']", + `.${button}_detached_mode_entity_option[data-room-id!='` + + selected_room_id + + "']", ).hide(); - // Check if selected button1_detached_mode_light option is visible, if not, select the first of the options. + // Check if selected button1_detached_mode_entity option is visible, if not, select the first of the options. if ( $( - `.${button}_detached_mode_light_option[data-room-id='` + - selected_room_id + - "']:selected", + `.${button}_detached_mode_entity_option[data-room-id='` + + selected_room_id + + "']:selected", ).length == 0 ) { var detached_light_first_value = $( - `.${button}_detached_mode_light_option[data-room-id='` + - selected_room_id + - "']:first", + `.${button}_detached_mode_entity_option[data-room-id='` + + selected_room_id + + "']:first", ).val(); if (detached_light_first_value) { console.log( @@ -107,14 +107,16 @@ function update_shown_elements(button) { detached_light_first_value, "' instead.", ); - $(`#${button}_detached_mode_light`) + $(`#${button}_detached_mode_entity`) .val(detached_light_first_value) .change(); } else { - $(`#${button}_detached_mode_light`).val("").change(); + $(`#${button}_detached_mode_entity`).val("").change(); } } + + } function update_screeensave_mode() { diff --git a/docker/web/nspanelmanager/web/templates/partial/edit_nspanel_buttons.html b/docker/web/nspanelmanager/web/templates/partial/edit_nspanel_buttons.html index b57e5e57..e89dbb8b 100644 --- a/docker/web/nspanelmanager/web/templates/partial/edit_nspanel_buttons.html +++ b/docker/web/nspanelmanager/web/templates/partial/edit_nspanel_buttons.html @@ -24,11 +24,11 @@