Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle UI Update Issues - Improved Value Change Handling in Samsung AC Integration #169

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
3d1887a
Handle value changes and prevent old values from being displayed
omerfaruk-aran Aug 25, 2024
79b5e0f
Handle value changes and prevent old values from being displayed
omerfaruk-aran Aug 25, 2024
dcf5c7c
Handle value changes and prevent old values from being displayed
omerfaruk-aran Aug 25, 2024
4abee34
Handle value changes and prevent old values from being displayed
omerfaruk-aran Aug 25, 2024
489d582
Handle value changes and prevent old values from being displayed
omerfaruk-aran Aug 25, 2024
19df6d5
Handle value changes and prevent old values from being displayed
omerfaruk-aran Aug 26, 2024
0027cb3
Fix build on ESP-IDF: Change logging message type interpolation #166
omerfaruk-aran Aug 26, 2024
9623be7
Fix 1
omerfaruk-aran Aug 26, 2024
d06023f
Fix 2
omerfaruk-aran Aug 26, 2024
c1e7343
outdoor_operation_mode add
omerfaruk-aran Aug 26, 2024
be2d233
outdoor_operation_mode add.
omerfaruk-aran Aug 26, 2024
8a9d045
outdoor_operation_mode delete :).
omerfaruk-aran Aug 26, 2024
d33db7b
outdoor_operation_mode delete :).
omerfaruk-aran Aug 26, 2024
73a2ea8
Optimize to_code function and remove unnecessary code
omerfaruk-aran Aug 27, 2024
49accb6
Optimize conversions.cpp and reduce redundant code
omerfaruk-aran Aug 27, 2024
1b251cc
Optimize debug_mqtt.cpp and remove redundant code
omerfaruk-aran Aug 27, 2024
b4a0809
Optimize protocol_nasa.cpp and protocol_nasa.h by removing unused inc…
omerfaruk-aran Aug 27, 2024
a2ed350
Optimize protocol_non_nasa.cpp and protocol_non_nasa.h by removing un…
omerfaruk-aran Aug 27, 2024
564e3fe
Optimize samsung_ac, protocol, and device code for better performance…
omerfaruk-aran Aug 27, 2024
c19dea0
Optimized util.cpp and util.h functions for better performance and se…
omerfaruk-aran Aug 27, 2024
c767402
Add Blueprint feature for Samsung AC error code monitoring and notifi…
omerfaruk-aran Aug 27, 2024
626fffd
Fix MessageTarget
omerfaruk-aran Aug 30, 2024
325ac49
Fix mode_to_string to mode_to_str conversions.cpp
omerfaruk-aran Aug 30, 2024
3b57f06
Refactor: Implement DeviceStateTracker for State Management
omerfaruk-aran Aug 30, 2024
f3bfdcd
Fix device_state_tracker.h
omerfaruk-aran Aug 30, 2024
ad8dd7b
Fix device_state_tracker.h
omerfaruk-aran Aug 30, 2024
6cce684
Fix device_state_tracker.h
omerfaruk-aran Aug 30, 2024
1f04375
Fix device_state_tracker.h
omerfaruk-aran Aug 30, 2024
49840b4
Fix device_state_tracker.h
omerfaruk-aran Aug 30, 2024
a5cb293
Fix log.h ESP_LOGI rebuild
omerfaruk-aran Aug 30, 2024
0b3a5be
Fix log.h ESP_LOGI rebuild
omerfaruk-aran Aug 30, 2024
5c27196
debug printf
omerfaruk-aran Aug 30, 2024
28f22b9
debug printf
omerfaruk-aran Aug 30, 2024
d9b4a62
debug printf
omerfaruk-aran Aug 30, 2024
1d95839
debug printf
omerfaruk-aran Aug 30, 2024
0db0c6b
debug printf
omerfaruk-aran Aug 30, 2024
56e756e
debug printf
omerfaruk-aran Aug 30, 2024
21f8ca0
debug printf
omerfaruk-aran Aug 30, 2024
d858ba9
Fix device_state_tracker.h and device_state_tracker.cpp file create
omerfaruk-aran Aug 30, 2024
bcd144a
Fix device_state_tracker.h and device_state_tracker.cpp file create
omerfaruk-aran Aug 30, 2024
07d0666
Fix device_state_tracker.cpp file remove
omerfaruk-aran Aug 30, 2024
ac409b4
Refactor: Simplified log macros and used consistent TAG casing
omerfaruk-aran Aug 30, 2024
e70a932
Add 'Eco Mode' to preset #172
omerfaruk-aran Sep 10, 2024
5eea1f4
Update readme.md
omerfaruk-aran Oct 7, 2024
a17fc5a
Merge branch 'main' into feature/handle-value-changes
omerfaruk-aran Oct 7, 2024
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
112 changes: 46 additions & 66 deletions components/samsung_ac/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
CONF_DEVICE_ERROR_CODE = "error_code"



CONF_CAPABILITIES = "capabilities"
CONF_CAPABILITIES_HORIZONTAL_SWING = "horizontal_swing"
CONF_CAPABILITIES_VERTICAL_SWING = "vertical_swing"
Expand Down Expand Up @@ -280,41 +281,28 @@ async def to_code(config):
device[CONF_DEVICE_ID], device[CONF_DEVICE_ADDRESS], var)

# setup capabilities
if CONF_CAPABILITIES in device and CONF_CAPABILITIES_VERTICAL_SWING in device[CONF_CAPABILITIES]:
cg.add(var_dev.set_supports_vertical_swing(
device[CONF_CAPABILITIES][CONF_CAPABILITIES_VERTICAL_SWING]))
elif CONF_CAPABILITIES in config and CONF_CAPABILITIES_VERTICAL_SWING in config[CONF_CAPABILITIES]:
cg.add(var_dev.set_supports_vertical_swing(
config[CONF_CAPABILITIES][CONF_CAPABILITIES_VERTICAL_SWING]))

if CONF_CAPABILITIES in device and CONF_CAPABILITIES_HORIZONTAL_SWING in device[CONF_CAPABILITIES]:
cg.add(var_dev.set_supports_horizontal_swing(
device[CONF_CAPABILITIES][CONF_CAPABILITIES_HORIZONTAL_SWING]))
elif CONF_CAPABILITIES in config and CONF_CAPABILITIES_HORIZONTAL_SWING in config[CONF_CAPABILITIES]:
cg.add(var_dev.set_supports_horizontal_swing(
config[CONF_CAPABILITIES][CONF_CAPABILITIES_HORIZONTAL_SWING]))
capabilities = device.get(CONF_CAPABILITIES, config.get(CONF_CAPABILITIES, {}))

if capabilities.get(CONF_CAPABILITIES_VERTICAL_SWING):
cg.add(var_dev.set_supports_vertical_swing(True))

if capabilities.get(CONF_CAPABILITIES_HORIZONTAL_SWING):
cg.add(var_dev.set_supports_horizontal_swing(True))

none_added = False
for preset in PRESETS:
device_preset_conf = device[CONF_CAPABILITIES][CONF_PRESETS][preset] if (
CONF_CAPABILITIES in device
and CONF_PRESETS in device[CONF_CAPABILITIES]
and preset in device[CONF_CAPABILITIES][CONF_PRESETS]) else None
global_preset_conf = config[CONF_CAPABILITIES][CONF_PRESETS][preset] if (
CONF_CAPABILITIES in config
and CONF_PRESETS in config[CONF_CAPABILITIES]
and preset in config[CONF_CAPABILITIES][CONF_PRESETS]) else None

preset_conf = global_preset_conf if device_preset_conf is None else device_preset_conf
presets = capabilities.get(CONF_PRESETS, {})

for preset, preset_info in PRESETS.items():
preset_conf = presets.get(preset, None)
preset_dict = isinstance(preset_conf, dict)
if preset_conf == True or (preset_dict and preset_conf[CONF_PRESET_ENABLED] == True):
if preset_conf == True or (preset_dict and preset_conf.get(CONF_PRESET_ENABLED, False)):
if not none_added:
none_added = True
cg.add(var_dev.add_alt_mode("None", 0))

cg.add(var_dev.add_alt_mode(
preset_conf[CONF_PRESET_NAME] if preset_dict and CONF_PRESET_NAME in preset_conf else PRESETS[preset]["displayName"],
preset_conf[CONF_PRESET_VALUE] if preset_dict and CONF_PRESET_VALUE in preset_conf else PRESETS[preset]["value"]
preset_conf.get(CONF_PRESET_NAME, preset_info["displayName"]),
preset_conf.get(CONF_PRESET_VALUE, preset_info["value"])
))

# if CONF_CAPABILITIES in device and CONF_ALT_MODES in device[CONF_CAPABILITIES]:
Expand All @@ -326,49 +314,28 @@ async def to_code(config):
# for alt in config[CONF_CAPABILITIES][CONF_ALT_MODES]:
# cg.add(var_dev.add_alt_mode(alt[CONF_ALT_MODE_NAME], alt[CONF_ALT_MODE_VALUE]))

if CONF_DEVICE_POWER in device:
conf = device[CONF_DEVICE_POWER]
sens = await switch.new_switch(conf)
cg.add(var_dev.set_power_switch(sens))

if CONF_DEVICE_AUTOMATIC_CLEANING in device:
conf = device[CONF_DEVICE_AUTOMATIC_CLEANING]
sens = await switch.new_switch(conf)
cg.add(var_dev.set_automatic_cleaning_switch(sens))

if CONF_DEVICE_WATER_HEATER_POWER in device:
conf = device[CONF_DEVICE_WATER_HEATER_POWER]
sens = await switch.new_switch(conf)
cg.add(var_dev.set_water_heater_power_switch(sens))
# Mapping of config keys to their corresponding methods and types
device_actions = {
CONF_DEVICE_POWER: (switch.new_switch, var_dev.set_power_switch),
CONF_DEVICE_AUTOMATIC_CLEANING: (switch.new_switch, var_dev.set_automatic_cleaning_switch),
CONF_DEVICE_WATER_HEATER_POWER: (switch.new_switch, var_dev.set_water_heater_power_switch),
CONF_DEVICE_ROOM_TEMPERATURE: (sensor.new_sensor, var_dev.set_room_temperature_sensor),
CONF_DEVICE_OUTDOOR_TEMPERATURE: (sensor.new_sensor, var_dev.set_outdoor_temperature_sensor),
CONF_DEVICE_INDOOR_EVA_IN_TEMPERATURE: (sensor.new_sensor, var_dev.set_indoor_eva_in_temperature_sensor),
CONF_DEVICE_INDOOR_EVA_OUT_TEMPERATURE: (sensor.new_sensor, var_dev.set_indoor_eva_out_temperature_sensor),
CONF_DEVICE_ERROR_CODE: (sensor.new_sensor, var_dev.set_error_code_sensor),
}

if CONF_DEVICE_ROOM_TEMPERATURE in device:
conf = device[CONF_DEVICE_ROOM_TEMPERATURE]
sens = await sensor.new_sensor(conf)
cg.add(var_dev.set_room_temperature_sensor(sens))
# Iterate over the actions
for key, (action, method) in device_actions.items():
if key in device:
conf = device[key]
sens = await action(conf)
cg.add(method(sens))

if CONF_DEVICE_ROOM_TEMPERATURE_OFFSET in device:
cg.add(var_dev.set_room_temperature_offset(
device[CONF_DEVICE_ROOM_TEMPERATURE_OFFSET]))

if CONF_DEVICE_OUTDOOR_TEMPERATURE in device:
conf = device[CONF_DEVICE_OUTDOOR_TEMPERATURE]
sens = await sensor.new_sensor(conf)
cg.add(var_dev.set_outdoor_temperature_sensor(sens))

if CONF_DEVICE_INDOOR_EVA_IN_TEMPERATURE in device:
conf = device[CONF_DEVICE_INDOOR_EVA_IN_TEMPERATURE]
sens = await sensor.new_sensor(conf)
cg.add(var_dev.set_indoor_eva_in_temperature_sensor(sens))

if CONF_DEVICE_INDOOR_EVA_OUT_TEMPERATURE in device:
conf = device[CONF_DEVICE_INDOOR_EVA_OUT_TEMPERATURE]
sens = await sensor.new_sensor(conf)
cg.add(var_dev.set_indoor_eva_out_temperature_sensor(sens))

if CONF_DEVICE_ERROR_CODE in device:
conf = device[CONF_DEVICE_ERROR_CODE]
sens = await sensor.new_sensor(conf)
cg.add(var_dev.set_error_code_sensor(sens))

if CONF_DEVICE_WATER_TARGET_TEMPERATURE in device:
conf = device[CONF_DEVICE_WATER_TARGET_TEMPERATURE]
Expand Down Expand Up @@ -452,6 +419,19 @@ async def to_code(config):

if (CONF_DEBUG_LOG_UNDEFINED_MESSAGES in config):
cg.add(var.set_debug_log_undefined_messages(config[CONF_DEBUG_LOG_UNDEFINED_MESSAGES]))


# Mapping of config keys to their corresponding methods
config_actions = {
CONF_DEBUG_LOG_MESSAGES: var.set_debug_log_messages,
CONF_DEBUG_LOG_MESSAGES_RAW: var.set_debug_log_messages_raw,
CONF_NON_NASA_KEEPALIVE: var.set_non_nasa_keepalive,
CONF_DEBUG_LOG_UNDEFINED_MESSAGES: var.set_debug_log_undefined_messages,
}

# Iterate over the actions
for key, method in config_actions.items():
if key in config:
cg.add(method(config[key]))

await cg.register_component(var, config)
await uart.register_uart_device(var, config)
4 changes: 2 additions & 2 deletions components/samsung_ac/conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace esphome
case Mode::Heat:
return "Heat";
default:
return "";
return "Unknown";
};
}

Expand Down Expand Up @@ -64,7 +64,7 @@ namespace esphome
case WaterHeaterMode::Force:
return "Force";
default:
return "";
return "Unknown";
};
}

Expand Down
34 changes: 12 additions & 22 deletions components/samsung_ac/debug_mqtt.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#include "esphome/core/log.h"
#include "debug_mqtt.h"

#ifdef USE_ESP8266
#if defined(USE_ESP8266)
#include <AsyncMqttClient.h>
AsyncMqttClient *mqtt_client{nullptr};
#endif
#ifdef USE_ESP32
#elif defined(USE_ESP32)
#include <mqtt_client.h>
esp_mqtt_client_handle_t mqtt_client{nullptr};
#endif
Expand All @@ -16,44 +15,40 @@ namespace esphome
{
bool debug_mqtt_connected()
{
#ifdef USE_ESP8266
if (mqtt_client == nullptr)
return false;

#if defined(USE_ESP8266)
return mqtt_client->connected();
#elif USE_ESP32
if (mqtt_client == nullptr)
return false;

#elif defined(USE_ESP32)
return true;
#else
return false;
#endif
}

void debug_mqtt_connect(const std::string &host, const uint16_t port, const std::string &username, const std::string &password)
{
if (host.length() == 0)
if (host.empty())
return;

#ifdef USE_ESP8266
#if defined(USE_ESP8266)
if (mqtt_client == nullptr)
{
mqtt_client = new AsyncMqttClient();
mqtt_client->setServer(host.c_str(), port);
if (username.length() > 0)
if (!username.empty())
mqtt_client->setCredentials(username.c_str(), password.c_str());
}

if (!mqtt_client->connected())
mqtt_client->connect();
#elif USE_ESP32

#elif defined(USE_ESP32)
if (mqtt_client == nullptr)
{
esp_mqtt_client_config_t mqtt_cfg = {};
mqtt_cfg.host = host.c_str();
mqtt_cfg.port = port;
if (username.length() > 0)
if (!username.empty())
{
mqtt_cfg.username = username.c_str();
mqtt_cfg.password = password.c_str();
Expand All @@ -66,18 +61,13 @@ namespace esphome

bool debug_mqtt_publish(const std::string &topic, const std::string &payload)
{
#ifdef USE_ESP8266
if (mqtt_client == nullptr)
return false;

#if defined(USE_ESP8266)
return mqtt_client->publish(topic.c_str(), 0, false, payload.c_str()) != 0;
#elif USE_ESP32
if (mqtt_client == nullptr)
return false;

#elif defined(USE_ESP32)
return esp_mqtt_client_publish(mqtt_client, topic.c_str(), payload.c_str(), payload.length(), 0, false) != -1;
#else
return true;
#endif
}
} // namespace samsung_ac
Expand Down
3 changes: 2 additions & 1 deletion components/samsung_ac/debug_mqtt.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include <iostream>

#include <string>

namespace esphome
{
Expand Down
56 changes: 56 additions & 0 deletions components/samsung_ac/device_state_tracker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#ifndef DEVICE_STATE_TRACKER_H
#define DEVICE_STATE_TRACKER_H

#include "esphome/core/log.h"
#include "esphome/core/helpers.h"
#include <map>
#include <string>

namespace esphome {

template <typename T>
class DeviceStateTracker {
public:
DeviceStateTracker(unsigned long timeout_period)
: TIMEOUT_PERIOD(timeout_period) {}

void update(const std::string &address, const T &current_value) {
unsigned long now = millis();

if (pending_changes_.find(address) != pending_changes_.end()) {
if (current_value == pending_changes_[address]) {
pending_changes_.erase(address);
} else {
ESP_LOGI("device_state_tracker", "Stale value received for device: %s, ignoring.", address.c_str());
return;
}
}

if (last_values_.find(address) == last_values_.end() || last_values_[address] != current_value) {
pending_changes_[address] = current_value;
last_values_[address] = current_value;
last_update_time_[address] = now;

ESP_LOGI("device_state_tracker", "Value changed for device: %s", address.c_str());
} else {
ESP_LOGD("device_state_tracker", "No change in value for device: %s", address.c_str());

if (now - last_update_time_[address] > TIMEOUT_PERIOD) {
if (pending_changes_.find(address) != pending_changes_.end()) {
ESP_LOGW("device_state_tracker", "Timeout for device: %s, forcing update.", address.c_str());
pending_changes_.erase(address);
}
}
}
}

private:
std::map<std::string, T> last_values_;
std::map<std::string, unsigned long> last_update_time_;
std::map<std::string, T> pending_changes_;
const unsigned long TIMEOUT_PERIOD;
};

} // namespace esphome

#endif // DEVICE_STATE_TRACKER_H
29 changes: 6 additions & 23 deletions components/samsung_ac/protocol_nasa.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#include <queue>
#include <iostream>
#include <set>
#include "esphome/core/log.h"
#include "esphome/core/util.h"
#include "esphome/core/hal.h"
#include "util.h"
#include "protocol_nasa.h"
#include "debug_mqtt.h"
Expand All @@ -21,9 +18,9 @@ namespace esphome
return value - (int)65535 /*uint16 max*/ - 1.0;
}

#define LOG_MESSAGE(message_name, temp, source, dest) \
if (debug_log_messages) \
{ \
#define LOG_MESSAGE(message_name, temp, source, dest) \
if (debug_log_messages) \
{ \
ESP_LOGW(TAG, "s:%s d:%s " #message_name " %g", source.c_str(), dest.c_str(), static_cast<double>(temp)); \
}

Expand Down Expand Up @@ -82,8 +79,8 @@ namespace esphome
std::string Address::to_string()
{
char str[9];
sprintf(str, "%02x.%02x.%02x", (int)klass, channel, address);
return str;
sprintf(str, "%02x.%02x.%02x", klass, channel, address);
return std::string(str);
}

void Command::decode(std::vector<uint8_t> &data, unsigned int index)
Expand Down Expand Up @@ -861,11 +858,9 @@ namespace esphome

void process_messageset_debug(std::string source, std::string dest, MessageSet &message, MessageTarget *target)
{
if (source == "20.00.00" || source == "20.00.01" || source == "20.00.03")
if (source == "20.00.00" || source == "20.00.01" || source == "20.00.02" || source == "20.00.03")
return;

// return; // :)

switch ((uint16_t)message.messageNumber)
{
case 0x4003:
Expand Down Expand Up @@ -900,18 +895,6 @@ namespace esphome
LOG_MESSAGE(ENUM_in_fan_vent_mode, message.value, source, dest);
// fan_vent_mode_to_fanmode();
break;
case 0x4205: // VAR_in_temp_eva_in_f unit = 'Celsius'
{
double temp = (double)message.value / (double)10;
LOG_MESSAGE(VAR_in_temp_eva_in_f, temp, source, dest);
break;
}
case 0x4206: // VAR_in_temp_eva_out_f unit = 'Celsius'
{
double temp = (double)message.value / (double)10;
LOG_MESSAGE(VAR_in_temp_eva_out_f, temp, source, dest);
break;
}
case 0x4211: // VAR_in_capacity_request unit = 'kW'
{
double temp = (double)message.value / (double)8.6;
Expand Down
1 change: 0 additions & 1 deletion components/samsung_ac/protocol_nasa.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once

#include <vector>
#include <iostream>
#include "protocol.h"

namespace esphome
Expand Down
Loading