Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ struct NSPanel {
int button1_mode = 0;
std::optional<uint64_t> button2_detached_mode_entity_id = 0;
int button2_mode = 0;
std::optional<uint64_t> button1_long_detached_mode_entity_id = 0;
int button1_long_mode = 0;
std::optional<uint64_t> button2_long_detached_mode_entity_id = 0;
int button2_long_mode = 0;
std::string md5_data_file;
std::string md5_firmware;
std::string md5_tft_file;
Expand Down Expand Up @@ -132,6 +136,10 @@ static inline auto database = sqlite_orm::make_storage("/data/nspanelmanager_db.
sqlite_orm::make_column("button1_mode", &NSPanel::button1_mode),
sqlite_orm::make_column("button2_detached_mode_entity_id", &NSPanel::button2_detached_mode_entity_id),
sqlite_orm::make_column("button2_mode", &NSPanel::button2_mode),
sqlite_orm::make_column("button1_long_detached_mode_entity_id", &NSPanel::button1_long_detached_mode_entity_id),
sqlite_orm::make_column("button1_long_mode", &NSPanel::button1_long_mode),
sqlite_orm::make_column("button2_long_detached_mode_entity_id", &NSPanel::button2_long_detached_mode_entity_id),
sqlite_orm::make_column("button2_long_mode", &NSPanel::button2_long_mode),
sqlite_orm::make_column("md5_data_file", &NSPanel::md5_data_file),
sqlite_orm::make_column("md5_firmware", &NSPanel::md5_firmware),
sqlite_orm::make_column("md5_tft_file", &NSPanel::md5_tft_file),
Expand Down
98 changes: 62 additions & 36 deletions docker/MQTTManager/include/nspanel/nspanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ std::shared_ptr<NSPanel> NSPanel::create_from_discovery_request(nlohmann::json r
panel_data.button1_mode = 0;
panel_data.button2_detached_mode_entity_id = std::nullopt;
panel_data.button2_mode = 0;
panel_data.button1_long_detached_mode_entity_id = std::nullopt;
panel_data.button1_long_mode = 0;
panel_data.button2_long_detached_mode_entity_id = std::nullopt;
panel_data.button2_long_mode = 0;
panel_data.md5_data_file = request_data.at("md5_data_file").get<std::string>();
panel_data.md5_firmware = request_data.at("md5_firmware").get<std::string>();
panel_data.md5_tft_file = request_data.at("md5_tft_file").get<std::string>();
Expand Down Expand Up @@ -306,6 +310,32 @@ void NSPanel::send_config() {
config.set_button2_mode(NSPanelConfig_NSPanelButtonMode_NOTIFY_MANAGER);
}

ButtonMode b1_long_mode = static_cast<ButtonMode>(this->_settings.button1_long_mode);
if (b1_long_mode == ButtonMode::DIRECT) {
config.set_button1_long_mode(NSPanelConfig_NSPanelButtonMode_DIRECT);
} else if (b1_long_mode == ButtonMode::FOLLOW) {
config.set_button1_long_mode(NSPanelConfig_NSPanelButtonMode_FOLLOW);
} else if (b1_long_mode == ButtonMode::THERMOSTAT_HEATING) {
config.set_button1_long_mode(NSPanelConfig_NSPanelButtonMode_THERMOSTAT_HEAT);
} else if (b1_long_mode == ButtonMode::THERMOSTAT_COOLING) {
config.set_button1_long_mode(NSPanelConfig_NSPanelButtonMode_THERMOSTAT_COOL);
} else {
config.set_button1_long_mode(NSPanelConfig_NSPanelButtonMode_NOTIFY_MANAGER);
}

ButtonMode b2_long_mode = static_cast<ButtonMode>(this->_settings.button2_long_mode);
if (b2_long_mode == ButtonMode::DIRECT) {
config.set_button2_long_mode(NSPanelConfig_NSPanelButtonMode_DIRECT);
} else if (b2_long_mode == ButtonMode::FOLLOW) {
config.set_button2_long_mode(NSPanelConfig_NSPanelButtonMode_FOLLOW);
} else if (b2_long_mode == ButtonMode::THERMOSTAT_HEATING) {
config.set_button2_long_mode(NSPanelConfig_NSPanelButtonMode_THERMOSTAT_HEAT);
} else if (b2_long_mode == ButtonMode::THERMOSTAT_COOLING) {
config.set_button2_long_mode(NSPanelConfig_NSPanelButtonMode_THERMOSTAT_COOL);
} else {
config.set_button2_long_mode(NSPanelConfig_NSPanelButtonMode_NOTIFY_MANAGER);
}

config.set_optimistic_mode(MqttManagerConfig::get_setting_with_default<bool>(MQTT_MANAGER_SETTING::OPTIMISTIC_MODE));
config.set_raise_light_level_to_100_above(MqttManagerConfig::get_setting_with_default<uint32_t>(MQTT_MANAGER_SETTING::RAISE_TO_100_LIGHT_LEVEL));

Expand Down Expand Up @@ -579,6 +609,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();
Expand Down Expand Up @@ -796,6 +827,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},
Expand Down Expand Up @@ -1040,6 +1073,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;
Expand Down Expand Up @@ -1171,6 +1205,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 }}";
Expand Down Expand Up @@ -1325,40 +1360,36 @@ void NSPanel::command_callback(NSPanelMQTTManagerCommand &command) {
SPDLOG_DEBUG("NSPanel {}::{} got button {} press,", this->_id, this->_name, command.button_pressed().button_id());

if (command.button_pressed().button_id() == 1) {
ButtonMode button_mode = static_cast<ButtonMode>(this->_settings.button1_mode);
switch (button_mode) {
case ButtonMode::DETACHED: {
if (this->_settings.button1_detached_mode_entity_id.has_value()) {
auto entity = EntityManager::get_entity_by_id<MqttManagerEntity>(MQTT_MANAGER_ENTITY_TYPE::ANY, this->_settings.button1_detached_mode_entity_id.value());
if (entity) {
if ((*entity)->can_toggle()) {
(*entity)->toggle();
}
} else
SPDLOG_ERROR("Tried to toggle detached light via panel but no light was was found with configured ID.");
} else {
SPDLOG_ERROR("Tried to toggle detached light via panel but no light was configured for button.");
}
break;
}

case ButtonMode::MQTT_PAYLOAD: {
std::string topic = this->_get_nspanel_setting_with_default("button1_mqtt_topic", "");
std::string payload = this->_get_nspanel_setting_with_default("button1_mqtt_payload", "");
MQTT_Manager::publish(topic, payload);
break;
}

default:
SPDLOG_WARN("Unknown button mode triggered from panel.");
break;
}
handle_button_pressed_command_callback( static_cast<ButtonMode>(this->_settings.button1_mode), this->_settings.button1_detached_mode_entity_id,
this->_get_nspanel_setting_with_default("button1_mqtt_topic", ""), this->_get_nspanel_setting_with_default("button1_mqtt_payload", ""));
} else if (command.button_pressed().button_id() == 2) {
ButtonMode button_mode = static_cast<ButtonMode>(this->_settings.button2_mode);
handle_button_pressed_command_callback( static_cast<ButtonMode>(this->_settings.button2_mode), this->_settings.button2_detached_mode_entity_id,
this->_get_nspanel_setting_with_default("button2_mqtt_topic", ""), this->_get_nspanel_setting_with_default("button2_mqtt_payload", ""));

}
}
}
if (command.has_button_longpressed()) {
if (command.nspanel_id() == this->_id) {
SPDLOG_DEBUG("NSPanel {}::{} got button {} longpress,", this->_id, this->_name, command.button_longpressed().button_id());

if (command.button_longpressed().button_id() == 1) {
handle_button_pressed_command_callback( static_cast<ButtonMode>(this->_settings.button1_long_mode), this->_settings.button1_long_detached_mode_entity_id,
this->_get_nspanel_setting_with_default("button1_long_mqtt_topic", ""), this->_get_nspanel_setting_with_default("button1_long_mqtt_payload", ""));
} else if (command.button_longpressed().button_id() == 2) {
handle_button_pressed_command_callback( static_cast<ButtonMode>(this->_settings.button2_long_mode), this->_settings.button2_long_detached_mode_entity_id,
this->_get_nspanel_setting_with_default("button2_long_mqtt_topic", ""), this->_get_nspanel_setting_with_default("button2_long_mqtt_payload", ""));

}
}
}
}

void NSPanel::handle_button_pressed_command_callback(ButtonMode button_mode, std::optional<uint64_t> entity_id, std::string topic,std::string payload ) {
switch (button_mode) {
case ButtonMode::DETACHED: {
if (this->_settings.button2_detached_mode_entity_id.has_value()) {
auto entity = EntityManager::get_entity_by_id<MqttManagerEntity>(MQTT_MANAGER_ENTITY_TYPE::ANY, this->_settings.button2_detached_mode_entity_id.value());
if (entity_id.has_value()) {
auto entity = EntityManager::get_entity_by_id<MqttManagerEntity>(MQTT_MANAGER_ENTITY_TYPE::ANY, entity_id.value());
if (entity) {
if ((*entity)->can_toggle()) {
(*entity)->toggle();
Expand All @@ -1372,8 +1403,6 @@ void NSPanel::command_callback(NSPanelMQTTManagerCommand &command) {
}

case ButtonMode::MQTT_PAYLOAD: {
std::string topic = this->_get_nspanel_setting_with_default("button2_mqtt_topic", "");
std::string payload = this->_get_nspanel_setting_with_default("button2_mqtt_payload", "");
MQTT_Manager::publish(topic, payload);
break;
}
Expand All @@ -1383,9 +1412,6 @@ void NSPanel::command_callback(NSPanelMQTTManagerCommand &command) {
break;
}
}
}
}
}

void NSPanel::handle_stomp_command_callback(StompFrame frame) {
if (frame.body.compare("reboot") == 0) {
Expand Down
28 changes: 20 additions & 8 deletions docker/MQTTManager/include/nspanel/nspanel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,22 @@ struct NSPanelWarningWebsocketRepresentation {
std::string text;
};


class NSPanel {

public:
NSPanel(uint32_t panel_id);


enum ButtonMode {
DIRECT,
DETACHED,
MQTT_PAYLOAD,
FOLLOW,
THERMOSTAT_HEATING,
THERMOSTAT_COOLING,
};

/*
* Build a new NSPanel object from a discovery request and add it to the database as pending.
* Returns a shared_ptr to the new NSPanel object if successful, otherwill nullptr.
Expand Down Expand Up @@ -155,6 +167,12 @@ class NSPanel {
*/
void command_callback(NSPanelMQTTManagerCommand &command);


/*
* handle button presses
*/
void handle_button_pressed_command_callback(ButtonMode button_mode, std::optional<uint64_t> entity_id, std::string topic,std::string payload );

/**
* When an IPC request for NSPanel status comes in handle it and send the response back
*/
Expand All @@ -179,6 +197,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,
Expand All @@ -201,14 +220,7 @@ class NSPanel {
std::string _current_littlefs_md5_checksum;
std::string _current_tft_md5_checksum;

enum ButtonMode {
DIRECT,
DETACHED,
MQTT_PAYLOAD,
FOLLOW,
THERMOSTAT_HEATING,
THERMOSTAT_COOLING,
};


// MQTT Stuff:
// Wether or not relay1 should be registered to Home Assistant as a switch or light.
Expand Down
Loading