Guten Morgen zusammen,
ich bin neu hier im Forum und auch generell neu in der Welt der ESP32 Boards, bitte nehmt mir meine Unwissenheit nicht übel.
Zu meinem Grundproblem bzw. meiner Ausgangssituation
(hat nur indirekt etwas mit den Boards zu tun, kann jedoch Hilfreich sein um mein Problem generell zu verstehen).
Ich möchte in meinem mobilen Camper die Standheizung bei mir in Homeassistant (betrieben bei mir Zuhause) einbinden. Hierbei bin ich auf eine Lösung gestoßen wo ein ESP32 Board eingesetzt wird. Die Herausforderung hier ist jedoch das diese Variante ausschließlich mit WiFi angegeben wurde, ich aber aus diversen Gründen hier kein eigenes Wireless Netzwerk aufbauen kann/möchte. Hier kam mir nun die Idee direkt mit einer SIM Karte zu arbeiten (Datacard bereits vorhanden bei dem Anbieter o2)
Mit ein paar Google Anfragen konnte ich bereits die ein oder anderen Boards mit integrierten 4G Modul auffinden. Da ich hier jedoch absolut keine Erfahrung mit habe, bin ich auf eure Hilfe/Ratschlag angewiesen.
Die bisherige Lösung ist hier wie folgt aufgebaut:
Hier wurde folgendes Board vorgesehen:
diymore 2 Stücke ESP32 WROOM 32 Nodemcu Development Board ESP32 NodeMCU Module USB C 2.4 GHz WLAN WiFi Bluetooth CH340 Chip
Laut der Anleitung wird effektiv darauf hingewiesen das es essentiell ist das man hier ein ESP32 Board mit 2 UART Anschlüssen benötigt.
Nun zu meiner generellen Frage:
- Gibt es hier ESP 32 Boards die den Anforderungen entsprechen (oder dem genannten Board ähneln) aber die Möglichkeit besitzen eine SIM Karte direkt zu verwenden?
- Das ESP Board mit Sim Karte sollte die Möglichkeit besitzen eine VPN über Wireguard aufzubauen
- Kann man eventuell das oben genannte Board mit einem Modul erweitern, wenn Ja mit welchem?
Der Code der hierfür vorgesehen ist:
--> Dieser hat noch keine Wireguard Anbindung
esphome:
name: heater
friendly_name: Heater
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
baud_rate: 0
# Enable Home Assistant API
api:
encryption:
key: "*************************"
ota:
password: "*****************************"
wifi:
ssid: ****************
password: ********************
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Heater Fallback Hotspot"
password: "********************"
captive_portal:
uart:
- id: uart_1_controller
baud_rate: 9600
tx_pin: 17
rx_pin: 16
debug:
direction: RX
dummy_receiver: true
after:
delimiter: "\r\n"
sequence:
- uart.write: #Write rx to tx.
id: uart_2_heater
data: !lambda return bytes ;
- lambda: |-
ESP_LOGD("custom", "Controller:");
UARTDebug::log_hex(direction, bytes, ':');
- id: uart_2_heater
baud_rate: 9600
tx_pin: 1
rx_pin: 3
debug:
direction: RX
dummy_receiver: true
after:
delimiter: "\r\n"
sequence:
- uart.write: #Write rx to tx.
id: uart_1_controller
data: !lambda return bytes ;
- lambda: |-
ESP_LOGD("custom", "Heater:");
UARTDebug::log_hex(direction, bytes, ':');
globals:
- id: read_state
type: int
restore_value: no
initial_value: '0'
- id: message_length
type: int
restore_value: no
- id: message_data
type: std::vector<uint8_t>
restore_value: no
- id: heaterStatus
type: int
initial_value: '0'
- id: connected
type: bool
initial_value: 'false'
- id: tempSet
type: int
initial_value: '15'
restore_value: no
- id: powerSet
type: int
initial_value: '2'
restore_value: no
script:
- id: send_uart_command
then:
- lambda: |-
std::vector<uint8_t> byteArray = {0xAA, 0x03, 0x06, 0x00, 0x01, 0xFF, 0xFF
, (uint8_t) static_cast<uint8_t>(id(power_mode_slider).state)
, (uint8_t) static_cast<uint8_t>(id(tempSet))
, (uint8_t) static_cast<uint8_t>(id(ventilation_slider).state)
, (uint8_t) static_cast<uint8_t>(id(powerSet))};
uint16_t crc = 0xFFFF;
for (uint8_t pos = 0; pos < byteArray.size(); pos++) {
crc ^= byteArray[pos];
for (uint8_t i = 0; i < 8; i++) {
bool odd = crc & 0x0001;
crc >>= 1;
if (odd) {
crc ^= 0xA001;
}
}
}
byteArray.push_back((crc >> 8) & 0xff);
byteArray.push_back(crc & 0xff);
id(uart_2_heater).write_array(&byteArray[0], byteArray.size());
/*for (uint8_t i = 0; i < byteArray.size(); i++) {
ESP_LOGD("send_uart_command", "byteArray[%d] = %02X", i, byteArray[i]);
}*/
- id: update_Settings_uart_command
then:
- lambda: |-
ESP_LOGD("Updating", "");
std::vector<uint8_t> byteArray = {0xAA, 0x03, 0x06, 0x00, 0x02, 0xFF, 0xFF
, (uint8_t) static_cast<uint8_t>(id(power_mode_slider).state)
, (uint8_t) static_cast<uint8_t>(id(tempSet))
, (uint8_t) static_cast<uint8_t>(id(ventilation_slider).state)
, (uint8_t) static_cast<uint8_t>(id(powerSet))};
uint16_t crc = 0xFFFF;
for (uint8_t pos = 0; pos < byteArray.size(); pos++) {
crc ^= byteArray[pos];
for (uint8_t i = 0; i < 8; i++) {
bool odd = crc & 0x0001;
crc >>= 1;
if (odd) {
crc ^= 0xA001;
}
}
}
byteArray.push_back((crc >> 8) & 0xff);
byteArray.push_back(crc & 0xff);
id(uart_2_heater).write_array(&byteArray[0], byteArray.size());
for (uint8_t i = 0; i < byteArray.size(); i++) {
ESP_LOGD("send_uart_command", "byteArray[%d] = %02X", i, byteArray[i]);
}
switch:
- platform: uart
uart_id: uart_2_heater
name: "TurnOnHeaterP3V1heater"
data: [0xAA, 0x03, 0x06, 0x00, 0x01, 0xFF, 0xFF, 0x01, 0x0F, 0x00, 0x05, 0xB6, 0x1F]
- platform: uart
uart_id: uart_2_heater
name: "Turn On Heater in T panel Mode"
data: [0xAA, 0x03, 0x06, 0x00, 0x01, 0xFF, 0xFF, 0x02, 0x0F, 0x02, 0x05, 0x92, 0x1E]
- platform: template
name: "Controllable Heater Start"
lambda: |-
if (id(heaterStatus) != 0) {
return true;
} else {
return false;
}
turn_on_action:
- script.execute: send_uart_command
turn_off_action:
uart.write:
id: uart_2_heater
data: [0xAA, 0x03, 0x00, 0x00, 0x03, 0x5D, 0x7C]
- platform: uart
uart_id: uart_2_heater
name: "Shutdown"
data: [0xAA, 0x03, 0x00, 0x00, 0x03, 0x5D, 0x7C]
- platform: template
name: "Ventillator Power"
turn_on_action:
- uart.write:
id: uart_2_heater
data: [0xAA, 0x03, 0x04, 0x00, 0x23, 0xFF, 0xFF, 0x08, 0xFF]
turn_off_action:
- uart.write:
id: uart_2_heater
data: [0xAA, 0x03, 0x00, 0x00, 0x03]
sensor:
- platform: template
name: "Heater Status"
id: heater_status
update_interval: 1s
- platform: template
name: "Heater Battery Voltage"
id: heater_battery_voltage
update_interval: 1s
unit_of_measurement: "V"
icon: "mdi:battery"
- platform: template
name: "Heater Ventilation Power"
id: heater_ventilation_power
update_interval: 1s
unit_of_measurement: "W"
- platform: template
name: "Heater Temperature"
id: heater_temperature
update_interval: 1s
unit_of_measurement: "°C"
icon: "mdi:thermometer"
- platform: template
name: "Heater Temperature By Panel"
id: heater_temperature_panel
unit_of_measurement: "°C"
icon: "mdi:thermometer"
update_interval: 1s
- platform: template
name: "Heater Power"
id: heater_power_status
update_interval: 1s
unit_of_measurement: '%'
- platform: template
name: "Set Temperature"
id: set_temperature
update_interval: 1s
unit_of_measurement: "°C"
icon: "mdi:thermometer"
- platform: template
name: "Air Temperature"
id: air_temperature
update_interval: 1s
unit_of_measurement: "°C"
icon: "mdi:thermometer"
number:
- platform: template
name: "temperature Slider"
id: "temperature_slider"
step: 1
min_value: 0
max_value: 30
mode: slider
initial_value: '15'
optimistic: true
set_action:
lambda: |-
id(tempSet)=x;
id(update_Settings_uart_command).execute();
- platform: template
name: "power Slider"
id: "power_slider"
step: 1
min_value: 1
max_value: 10
initial_value: '3'
mode: slider
optimistic: true
set_action:
lambda: |-
id(powerSet)=x-1;
id(update_Settings_uart_command).execute();
int modeValue = id(power_slider).state; // Änderung hier zu power_slider
std::map<int, std::string> modes = {{1, "By T Heater"}, {2, "By T Panel"}, {3, "By T Air"}, {4, "Power Mode"}};
if (modes.find(modeValue) != modes.end()) {
id(power_mode_text).publish_state(modes[modeValue]);
} else {
id(power_mode_text).publish_state("Unknown");
}
- platform: template
name: "power mode Slider"
id: "power_mode_slider"
step: 1
min_value: 1
max_value: 4
mode: slider
optimistic: true
set_action:
then:
- script.execute: update_Settings_uart_command
- platform: template
name: "ventilation on/off Slider"
id: "ventilation_slider"
step: 1
min_value: 1
max_value: 2
mode: slider
optimistic: true
set_action:
then:
- script.execute: update_Settings_uart_command
text_sensor:
- platform: template
name: "Power Mode Text"
id: power_mode_text
update_interval: 10s
- platform: template
name: "Heater Ventillator Mode Text"
id: heater_ventillator_mode_text
update_interval: 10s
interval:
- interval: 20ms
then:
- lambda: |-
static uint8_t command_id = 0;
while (id(uart_2_heater).available())
{
uint8_t byte;
id(uart_2_heater).read_byte(&byte);
if (id(read_state) == 0 && byte == 0xAA)
{
// Start of message
id(read_state) = 1;
id(message_data).clear();
}
else if (id(read_state) == 1)
{
id(read_state) = 2;
}
else if (id(read_state) == 2)
{
// Message length
id(message_length) = byte;
id(read_state) = 3;
}
else if (id(read_state) == 3)
{
// 00
id(read_state) = 4;
}
else if (id(read_state) == 4)
{
// this is command id
id(read_state) = 5;
command_id=byte;
}
else if(id(read_state) == 5)
{
id(message_data).push_back(byte);
if (id(message_data).size() >= id(message_length))
{
if (command_id==15)
{
id(connected)=true;
int temperature_calc_heater = id(message_data)[3];
//ESP_LOGD("send_uart_command","Temp Message", id(message_data)[3]);
if (temperature_calc_heater > 127) {
// ESP_LOGD("send_uart_command","Temp temperature_calc_heater", temperature_calc_heater);
temperature_calc_heater = (temperature_calc_heater -256);
// ESP_LOGD("send_uart_command","Temp temperature_calc_heater_calculated", temperature_calc_heater);
}
id(heater_temperature).publish_state(temperature_calc_heater);
//id(heater_temperature).publish_state(id(message_data)[3]);
id(heater_status).publish_state(id(message_data)[9]);
uint8_t statusByte = id(message_data)[9];
int value = static_cast<int>(statusByte);
id(heaterStatus) = value;
id(heater_battery_voltage).publish_state(id(message_data)[6] / 10.0);
id(heater_ventilation_power).publish_state((id(message_data)[16]));
int temperature_calc_air = id(message_data)[4];
//ESP_LOGD("send_uart_command","Temp Message", id(message_data)[4]);
if (temperature_calc_air > 127) {
// ESP_LOGD("send_uart_command","Temp temperature_calc_air", temperature_calc_air);
temperature_calc_air = (temperature_calc_air -256);
// ESP_LOGD("send_uart_command","Temp temperature_calc_air_calculated", temperature_calc_air);
}
id(air_temperature).publish_state(temperature_calc_air);
}
else if (command_id==17)
{
int temperature_calc_panel = id(message_data)[0];
//ESP_LOGD("send_uart_command","Temp Message", id(message_data)[0]);
if (temperature_calc_panel > 127) {
// ESP_LOGD("send_uart_command","Temp temperature_calc_panel", temperature_calc_panel);
temperature_calc_panel = (temperature_calc_panel -256);
// ESP_LOGD("send_uart_command","Temp temperature_calc_panel_calculated", temperature_calc_panel);
}
id(heater_temperature_panel).publish_state(temperature_calc_panel);
//id(temperature_heater).publish_state(id(message_data)[0]);
}
else if (command_id==2 && id(heaterStatus)!=0)
{
id(set_temperature).publish_state(id(message_data)[3]);
id(heater_power_status).publish_state(id(message_data)[5]+1);
std::map<uint32_t, std::string> modes = {{1, "By T Heater"}, {2, "By T Panel"}, {3, "By T Air"}, {4, "By Power"}};
uint32_t mode = round(id(message_data)[2]);
if (modes.find(mode) != modes.end()) {
id(power_mode_text).publish_state(modes[mode]);
} else {
id(power_mode_text).publish_state("Unknown");
}
modes = {{1, "On"}, {2, "Off"}};
mode = round(id(message_data)[4]);
if (modes.find(mode) != modes.end()) {
id(heater_ventillator_mode_text).publish_state(modes[mode]);
} else {
id(heater_ventillator_mode_text).publish_state("Unknown");
}
//id(power_mode_slider).publish_state(id(message_data)[2]);
//id(ventilation_slider).publish_state(id(message_data)[4]);
if(id(temperature_slider).state!=id(message_data)[3])
id(temperature_slider).publish_state(id(message_data)[3]);
if(id(power_slider).state!=id(message_data)[5])
id(power_slider).publish_state(id(message_data)[5]+1);
}
id(read_state) = 0;
}
}
}
Ich bedanke mich schon mal recht Herzlich für eure Unterstützung und eurer Zeit.
Viele Grüße,
Maik L.