Skip to content

Commit

Permalink
Merge branch 'main' into refactor_request
Browse files Browse the repository at this point in the history
  • Loading branch information
lanwin committed Feb 8, 2024
2 parents 6be35f3 + af9304b commit c31eacf
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 33 deletions.
File renamed without changes.
174 changes: 144 additions & 30 deletions components/samsung_ac/protocol_non_nasa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,73 @@ namespace esphome
std::string NonNasaCommand20::to_string()
{
std::string str;
str += "target_temp:" + std::to_string(target_temp) + ";";
str += "room_temp:" + std::to_string(room_temp) + ";";
str += "pipe_in:" + std::to_string(pipe_in) + ";";
str += "pipe_out:" + std::to_string(pipe_out) + ";";
str += "power:" + std::to_string(power ? 1 : 0) + ";";
str += "wind_direction:" + std::to_string((uint8_t)wind_direction) + ";";
str += "fanspeed:" + std::to_string((uint8_t)fanspeed) + ";";
str += "mode:" + long_to_hex((uint8_t)mode) + ";";
str += "target_temp:" + std::to_string(target_temp) + "; ";
str += "room_temp:" + std::to_string(room_temp) + "; ";
str += "pipe_in:" + std::to_string(pipe_in) + "; ";
str += "pipe_out:" + std::to_string(pipe_out) + "; ";
str += "power:" + std::to_string(power ? 1 : 0) + "; ";
str += "wind_direction:" + std::to_string((uint8_t)wind_direction) + "; ";
str += "fanspeed:" + std::to_string((uint8_t)fanspeed) + "; ";
str += "mode:" + long_to_hex((uint8_t)mode);
return str;
}

std::string NonNasaCommandC0::to_string()
{
std::string str;
str += "ou_operation_mode:" + long_to_hex((uint8_t)outdoor_unit_operation_mode) + "; ";
str += "ou_4way_valve:" + std::to_string(outdoor_unit_4_way_valve ? 1 : 0) + "; ";
str += "ou_hot_gas_bypass:" + std::to_string(outdoor_unit_hot_gas_bypass ? 1 : 0) + "; ";
str += "ou_compressor:" + std::to_string(outdoor_unit_compressor ? 1 : 0) + "; ";
str += "ou_ac_fan:" + std::to_string(outdoor_unit_ac_fan ? 1 : 0) + "; ";
str += "ou_outdoor_temp[°C]:" + std::to_string(outdoor_unit_outdoor_temp_c) + "; ";
str += "ou_discharge_temp[°C]:" + std::to_string(outdoor_unit_discharge_temp_c) + "; ";
str += "ou_condenser_mid_temp[°C]:" + std::to_string(outdoor_unit_condenser_mid_temp_c);
return str;
}

std::string NonNasaCommandC1::to_string()
{
std::string str;
str += "ou_sump_temp[°C]:" + std::to_string(outdoor_unit_sump_temp_c);
return str;
}

std::string NonNasaCommandF0::to_string()
{
std::string str;
str += "ou_freeze_protection:" + std::to_string(outdoor_unit_freeze_protection ? 1 : 0) + "; ";
str += "ou_heating_overload:" + std::to_string(outdoor_unit_heating_overload ? 1 : 0) + "; ";
str += "ou_defrost_control:" + std::to_string(outdoor_unit_defrost_control ? 1 : 0) + "; ";
str += "ou_discharge_protection:" + std::to_string(outdoor_unit_discharge_protection ? 1 : 0) + "; ";
str += "ou_current_control:" + std::to_string(outdoor_unit_current_control ? 1 : 0) + "; ";
str += "inverter_order_frequency[Hz]:" + std::to_string(inverter_order_frequency_hz) + "; ";
str += "inverter_target_frequency[Hz]:" + std::to_string(inverter_target_frequency_hz) + "; ";
str += "inverter_current_frequency[Hz]:" + std::to_string(inverter_current_frequency_hz) + "; ";
str += "ou_bldc_fan:" + std::to_string(outdoor_unit_bldc_fan ? 1 : 0) + "; ";
str += "ou_error_code:" + long_to_hex((uint8_t)outdoor_unit_error_code);
return str;
}

std::string NonNasaCommandF1::to_string()
{
std::string str;
str += "Electronic Expansion Valves: ";
str += "EEV_A:" + std::to_string(outdoor_unit_EEV_A) + "; ";
str += "EEV_B:" + std::to_string(outdoor_unit_EEV_B) + "; ";
str += "EEV_C:" + std::to_string(outdoor_unit_EEV_C) + "; ";
str += "EEV_D:" + std::to_string(outdoor_unit_EEV_D);
return str;
}

std::string NonNasaCommandF3::to_string()
{
std::string str;
str += "inverter_max_frequency[Hz]:" + std::to_string(inverter_max_frequency_hz) + ";";
str += "inverter_total_capacity_requirement[kW]:" + std::to_string(inverter_total_capacity_requirement_kw) + ";";
str += "inverter_current[ADC]:" + std::to_string(inverter_current_a) + ";";
str += "inverter_voltage[VDC]:" + std::to_string(inverter_voltage_v) + ";";
str += "inverter_power[W]:" + std::to_string(inverter_power_w) + ";";
str += "inverter_max_frequency[Hz]:" + std::to_string(inverter_max_frequency_hz) + "; ";
str += "inverter_total_capacity_requirement[kW]:" + std::to_string(inverter_total_capacity_requirement_kw) + "; ";
str += "inverter_current[ADC]:" + std::to_string(inverter_current_a) + "; ";
str += "inverter_voltage[VDC]:" + std::to_string(inverter_voltage_v) + "; ";
str += "inverter_power[W]:" + std::to_string(inverter_power_w);
return str;
}

Expand All @@ -64,19 +112,34 @@ namespace esphome
str += "command20:{" + command20.to_string() + "}";
break;
}
case NonNasaCommand::CmdC0:
{
str += "commandC0:{" + commandC0.to_string() + "}";
break;
}
case NonNasaCommand::CmdC1:
{
str += "commandC1:{" + commandC1.to_string() + "}";
break;
}
case NonNasaCommand::CmdC6:
{
str += "commandC6:{" + commandC6.to_string() + "}";
break;
}
case NonNasaCommand::CmdF3:
case NonNasaCommand::CmdF0:
{
str += "commandF3:{" + commandF3.to_string() + "}";
str += "commandF0:{" + commandF0.to_string() + "}";
break;
}
case NonNasaCommand::CmdF8:
case NonNasaCommand::CmdF1:
{
str += "commandF8:{" + commandF8.to_string() + "}";
str += "commandF1:{" + commandF1.to_string() + "}";
break;
}
case NonNasaCommand::CmdF3:
{
str += "commandF3:{" + commandF3.to_string() + "}";
break;
}
default:
Expand Down Expand Up @@ -131,11 +194,50 @@ namespace esphome

return DecodeResult::Ok;
}
case NonNasaCommand::CmdC0: // outdoor unit data
{
commandC0.outdoor_unit_operation_mode = data[4]; // modes need to be specified
commandC0.outdoor_unit_4_way_valve = data[6] & 0b10000000;
commandC0.outdoor_unit_hot_gas_bypass = data[6] & 0b00100000;
commandC0.outdoor_unit_compressor = data[6] & 0b00000100;
commandC0.outdoor_unit_ac_fan = data[7] & 0b00000011;
commandC0.outdoor_unit_outdoor_temp_c = data[8] - 55;
commandC0.outdoor_unit_discharge_temp_c = data[10] - 55;
commandC0.outdoor_unit_condenser_mid_temp_c = data[11] - 55;
return DecodeResult::Ok;
}
case NonNasaCommand::CmdC1: // outdoor unit data
{
commandC1.outdoor_unit_sump_temp_c = data[8] - 55;
return DecodeResult::Ok;
}
case NonNasaCommand::CmdC6:
{
commandC6.control_status = data[4];
return DecodeResult::Ok;
}
case NonNasaCommand::CmdF0: // outdoor unit data
{
commandF0.outdoor_unit_freeze_protection = data[4] & 0b10000000;
commandF0.outdoor_unit_heating_overload = data[4] & 0b01000000;
commandF0.outdoor_unit_defrost_control = data[4] & 0b00100000;
commandF0.outdoor_unit_discharge_protection = data[4] & 0b00010000;
commandF0.outdoor_unit_current_control = data[4] & 0b00001000;
commandF0.inverter_order_frequency_hz = data[5];
commandF0.inverter_target_frequency_hz = data[6];
commandF0.inverter_current_frequency_hz = data[7];
commandF0.outdoor_unit_bldc_fan = data[8] & 0b00000011; // not sure if correct, i have no ou with BLDC-fan
commandF0.outdoor_unit_error_code = data[10];
return DecodeResult::Ok;
}
case NonNasaCommand::CmdF1: // outdoor unit eev-values
{
commandF1.outdoor_unit_EEV_A = (data[4] * 256) + data[5];
commandF1.outdoor_unit_EEV_B = (data[6] * 256) + data[7];
commandF1.outdoor_unit_EEV_C = (data[8] * 256) + data[9];
commandF1.outdoor_unit_EEV_D = (data[10] * 256) + data[11];
return DecodeResult::Ok;
}
case NonNasaCommand::CmdF3: // power consumption
{
// Maximum frequency for Inverter (compressor-motor of outdoor-unit) in Hz
Expand Down Expand Up @@ -323,12 +425,12 @@ namespace esphome

void NonNasaProtocol::publish_altmode_message(MessageTarget *target, const std::string &address, AltMode value)
{
// TODO
ESP_LOGW(TAG, "change altmode is currently not implemented");
}

void NonNasaProtocol::publish_swing_mode_message(MessageTarget *target, const std::string &address, SwingMode value)
{
// TODO
ESP_LOGW(TAG, "change swingmode is currently not implemented");
}

void NonNasaProtocol::publish_request(MessageTarget *target, const std::string &address, ProtocolRequest &request)
Expand Down Expand Up @@ -389,6 +491,17 @@ namespace esphome
return nonpacket_.decode(data);
}

void send_requests(MessageTarget *target, uint8_t delay_ms)
{
while (nonnasa_requests.size() > 0)
{
delay(delay_ms);
auto data = nonnasa_requests.front().encode();
target->publish_data(data);
nonnasa_requests.pop();
}
}

void process_non_nasa_packet(MessageTarget *target)
{
if (debug_log_packets)
Expand All @@ -415,19 +528,20 @@ namespace esphome
else if (nonpacket_.cmd == NonNasaCommand::CmdF8)
{
// After cmd F8 (src:c8 dst:f0) is a lage gap in communication, time to send data

if (nonpacket_.src == "c8" && nonpacket_.dst == "f0")
{
while (nonnasa_requests.size() > 0)
{
auto data = nonnasa_requests.front().encode();
// the communication needs a delay from cmdf8 to send the data.
// series of test-delay-times: 1ms: no reaction, 7ms reactions half the time, 10ms very often a reaction (95%) -> delay on 20ms should be safe
// the gap is around ~300ms
delay(20);
target->publish_data(data);
nonnasa_requests.pop();
}
// the communication needs a delay from cmdf8 to send the data.
// series of test-delay-times: 1ms: no reaction, 7ms reactions half the time, 10ms very often a reaction (95%) -> delay on 20ms should be safe
// the gap is around ~300ms
send_requests(target, 20);
}
}
else if (nonpacket_.cmd == NonNasaCommand::CmdC6)
{
// If the control status is set we can send also
if (nonpacket_.src == "c8" && nonpacket_.dst == "d0" && nonpacket_.commandC6.control_status == true)
{
send_requests(target, 20);
}
}
}
Expand Down
62 changes: 59 additions & 3 deletions components/samsung_ac/protocol_non_nasa.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace esphome
Stop = 31
};

struct NonNasaCommand20
struct NonNasaCommand20 // from indoor units
{
uint8_t target_temp = 0;
uint8_t room_temp = 0;
Expand All @@ -53,6 +53,27 @@ namespace esphome
std::string to_string();
};

struct NonNasaCommandC0 // from outdoor unit
{
uint8_t outdoor_unit_operation_mode = 0;
bool outdoor_unit_4_way_valve = false;
bool outdoor_unit_hot_gas_bypass = false;
bool outdoor_unit_compressor = false;
bool outdoor_unit_ac_fan = false;
uint8_t outdoor_unit_outdoor_temp_c = 0;
uint8_t outdoor_unit_discharge_temp_c = 0;
uint8_t outdoor_unit_condenser_mid_temp_c = 0;

std::string to_string();
};

struct NonNasaCommandC1 // from outdoor unit
{
uint8_t outdoor_unit_sump_temp_c = 0;

std::string to_string();
};

struct NonNasaCommandC6
{
bool control_status = false;
Expand All @@ -62,7 +83,34 @@ namespace esphome
};
};

struct NonNasaCommandF3
struct NonNasaCommandF0 // from outdoor unit
{
bool outdoor_unit_freeze_protection = false;
bool outdoor_unit_heating_overload = false;
bool outdoor_unit_defrost_control = false;
bool outdoor_unit_discharge_protection = false;
bool outdoor_unit_current_control = false;
uint8_t inverter_order_frequency_hz = 0;
uint8_t inverter_target_frequency_hz = 0;
uint8_t inverter_current_frequency_hz = 0;
bool outdoor_unit_bldc_fan = false;
uint8_t outdoor_unit_error_code = 0;

std::string to_string();
};

struct NonNasaCommandF1 // from outdoor unit
{
uint16_t outdoor_unit_EEV_A = 0;
uint16_t outdoor_unit_EEV_B = 0;
uint16_t outdoor_unit_EEV_C = 0;
uint16_t outdoor_unit_EEV_D = 0;

std::string to_string();
};


struct NonNasaCommandF3 // from outdoor unit
{
uint8_t inverter_max_frequency_hz = 0;
float inverter_total_capacity_requirement_kw = 0;
Expand All @@ -88,8 +136,12 @@ namespace esphome
enum class NonNasaCommand : uint8_t
{
Cmd20 = 0x20,
CmdC0 = 0xc0,
CmdC1 = 0xc1,
CmdC6 = 0xc6,
CmdF3 = 0xf3,
CmdF0 = 0xf0,
CmdF1 = 0xf1,
CmdF3 = 0xf3,
CmdF8 = 0xF8,
};

Expand All @@ -107,7 +159,11 @@ namespace esphome
union
{
NonNasaCommand20 command20;
NonNasaCommandC0 commandC0;
NonNasaCommandC1 commandC1;
NonNasaCommandC6 commandC6;
NonNasaCommandF0 commandF0;
NonNasaCommandF1 commandF1;
NonNasaCommandF3 commandF3;
NonNasaCommandRaw commandF8; // Unknown structure for now
NonNasaCommandRaw commandRaw;
Expand Down

0 comments on commit c31eacf

Please sign in to comment.