Eurom Sani-Wall-Heat 2000 Wifi

Here are some pictures (Thanks @drbytes )


The protocol used is not the standard Tuya protocol.
Impossible to integrate it in Home assistant via Tuya.

It was possible to use Tasmota but you had to parse the serial commands in Home assistant. It’s easier in ESPHOME

uart_read_line_sensor.h

#include "esphome.h"

class UartReadLineSensor : public Component, public UARTDevice, public TextSensor {
 public:
  UartReadLineSensor(UARTComponent *parent) : UARTDevice(parent) {}

  void setup() override {
    // nothing to do here
  }

  int readline(int readch, char *buffer, int len)
  {
    static int pos = 0;
	static int checksum = 0;
	
    int rpos;
	int temp;

	if (pos==0 or pos==1) {
		if (readch != 242) {
			pos = 0; // frame must begin with F2F2
			checksum = 0; // Reset checksum ready for next time
			return -1;
		}
	}
	// Calculate Checksum
	if (pos>=2 and pos<=18) {
		checksum = checksum + readch;
	}
	
	temp = (readch / 16);
	if (temp < 10)
		temp =temp + 48;
  	else
		temp = temp + 55;
		 
	buffer[pos*2] = temp;
		   
	temp = readch % 16;
	if (temp < 10)
		temp =temp + 48;
  	else
		temp = temp + 55;
		 
	buffer[pos*2+1] = temp;
     
	 
	if (pos==19 and checksum != readch) {
		pos = 0;
		checksum = 0; // Reset checksum ready for next time
		return -3;
	}
	// Frame must finish with 7E

	if (pos==20) {
		if (readch==126) { 
			rpos = pos;
			pos = 0;  // Reset position index ready for next time
			checksum = 0; // Reset checksum ready for next time
			return rpos;
		} else {
			pos = 0;
			checksum=0;
			return -2;
		}
	}
	pos++;
	return -1;
  }

  void loop() override {
    const int max_line_length = 42;
    static char buffer[max_line_length];
    while (available()) {
      if(readline(read(), buffer, max_line_length) > 0) {
        publish_state(buffer);
      }
    }
  }
};

eurom.yaml

esphome:
  name: eurom
  includes:
   - uart_read_line_sensor.h

esp8266:
  board: esp01_1m

# Enable logging
logger:

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  
  ap:
    ssid: "Eurom Fallback Hotspot"
    password: "sburLSnBEYI1"

captive_portal:
api:
  services:
    - service: heater_trigger
      variables:
        mode: int
        swing: int
      then:
        - uart.write: !lambda |-
            if (mode == 0 )  { 
              return {0xF1,0xF1,0x02,0x10,0x02,0x02,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x1A,0x7E};
            } else if (mode == 1  and swing == 1)  {
              return {0xF1,0xF1,0x02,0x10,0x01,0x01,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x18,0x7E};
            } else if (mode == 2  and swing == 1) {
              return {0xF1,0xF1,0x02,0x10,0x01,0x01,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x19,0x7E};
            } else if (mode == 1 and swing == 0)  { 
              return {0xF1,0xF1,0x02,0x10,0x01,0x02,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x19,0x7E};
            }  else if (mode == 2  and swing == 0) {
              return {0xF1,0xF1,0x02,0x10,0x01,0x02,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x1A,0x7E};
            } else {
              return {};
            }
            
            
ota:
  password: "2f836d76f61876533599b2918cc6c97a"

uart:
  rx_pin: 13
  tx_pin: 15
  baud_rate: 9600
  id: uart_bus


text_sensor:

- platform: wifi_info
  ip_address:
    name: ESP IP Address
  ssid:
    name: ESP Connected SSID
  bssid:
    name: ESP Connected BSSID
  mac_address:
    name: ESP Mac Wifi Address

- platform: custom
  id : recieve_txt
  lambda: |-
    auto my_custom_sensor = new UartReadLineSensor(id(uart_bus));
    App.register_component(my_custom_sensor);
    return {my_custom_sensor};
  
  text_sensors:
    id: "uart_readline"

select:
  - platform: template
    name: "Mode"
    id : "Eurom_mode"
    options:
      - 'OFF'
      - 50%
      - 100%
    update_interval: 5s
    lambda: !lambda |-
      std::string val = id(uart_readline).state;
      if ( (val[21]=='1') || (val[21]=='4') ) {
        return {"OFF"};
      } else if (val[21]=='2') {
        return {"50%"};
      } else if (val[21]=='3') {
        return {"100%"};
      } else {
        return {};
      }
      
    set_action:
      - logger.log:
          format: "Change mode to %s"
          args: ["x.c_str()"]
      - uart.write: !lambda |-
          std::string val = (x.c_str());
          if (val == "OFF" )  { 
            return {0xF1,0xF1,0x02,0x10,0x02,0x02,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x1A,0x7E};
          } 
          else if (val == "50%" )  { 
            return {0xF1,0xF1,0x02,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x7E};
          } 
          else if (val == "100%" )  { 
            return {0xF1,0xF1,0x02,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x18,0x7E};
          } else {
            return {};
          }

sensor:
  - platform: template
    name: "Eurom_Temperature"
    unit_of_measurement: "°C"
    icon: "mdi:thermometer"
    device_class: "temperature"
    state_class: "measurement"
    accuracy_decimals: 0
    update_interval: 5s

# Convert hexadecimal string to int

    lambda: |-
      std::string val = (id(uart_readline).state);
      int temp1 = val[28] - 48;
      if (temp1 >10) {
        temp1 = temp1 - 7;
      }
      int temp2 = val[29] - 48;
      if (temp2 >10) {
        temp2 = temp2 - 7;
      }
      
      return (temp1*16+temp2);
      
switch:
  - platform: template
    name: "Eurom_swing"
    id: "Eurom_swing"
    lambda: |-
      std::string val = id(uart_readline).state;
      if (val[11]=='1') {
        return 1;
      } else if (val[11]=='2') {
        return 0;
      } else {
        return {};
      }
    turn_on_action:
      - logger.log: "Swing Turned On!"
      - uart.write: [0xF1,0xF1,0x02,0x10,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x16,0x7E]
    turn_off_action:
      - logger.log: "Swing Turned Off!"
      - uart.write: [0xF1,0xF1,0x02,0x10,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x7E]

  - platform: template
    name: "Eurom_power"
    id: "Eurom_power"
    lambda: |-
      std::string val = id(uart_readline).state;
      if (val[9]=='1') {
        return 1;
      } else if (val[9]=='2') {
        return 0;
      } else {
        return {};
      }
      
  
    turn_on_action:
      - logger.log: "Turn On (mode 2 + Swing)"
      - uart.write: [0xF1,0xF1,0x02,0x10,0x01,0x01,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x19,0x7E]
    turn_off_action:
      - logger.log: "Turn off"
      - uart.write: [0xF1,0xF1,0x02,0x10,0x02,0x02,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x1A,0x7E]

# Send serial every 60s to get respond from MCU (to update status...)    

interval:
  - interval: 60s
    then:
      - uart.write: [0xF1, 0xF1, 0x01, 0x00, 0x01, 0x7E]
      

Home assistant
Homeassistant

This is my first development with ESPHOME. If it can help anyone…

2 Likes

Putain, bien joué :smiley:

I solved it going with scenes but this should do the trick nicely, as it reports temperature back using your method.

However,… as you’ll soon find out, the hardware isn’t really any good, it starts to rattle like crazy after a while making it unusable in a bedroom for instance, it’s like sleeping next to a running stationary truck.

Have you managed to get it to work better? I’m using a Eurom Wall Designheat 2000 which seems to be quite similar and also uses the TYJW2.1.

When I use your yaml file, temperature doesn’t report back correctly. Also it doesn’t seem to be able to switch the device and it returns always to off.

Do you have any pointers on how to proceed?

I’ve done some basic testing, but I am no closer to finding the issue.

INFO Reading configuration /config/esphome/eurom-garage.yaml...
INFO Starting log output from eurom-garage.local using esphome API
INFO Successfully connected to eurom-garage.local
[10:39:17][I][app:102]: ESPHome version 2022.2.4 compiled on Feb 23 2022, 10:04:27
[10:39:17][C][wifi:491]: WiFi:
[10:39:17][C][wifi:353]:   Local MAC: 98:CD:AC:02:0A:F0
[10:39:17][C][wifi:354]:   SSID: 'IOT'[redacted]
[10:39:17][C][wifi:355]:   IP Address: 192.168.1.72
[10:39:17][C][wifi:356]:   BSSID: E6:63:DA:15:5F:47[redacted]
[10:39:17][C][wifi:358]:   Hostname: 'eurom-garage'
[10:39:17][C][wifi:360]:   Signal strength: -85 dB ▂▄▆█
[10:39:17][C][wifi:364]:   Channel: 1
[10:39:17][C][wifi:365]:   Subnet: 255.255.255.0
[10:39:17][C][wifi:366]:   Gateway: 192.168.1.1
[10:39:17][C][wifi:367]:   DNS1: 192.168.1.1
[10:39:17][C][wifi:368]:   DNS2: 0.0.0.0
[10:39:17][C][logger:233]: Logger:
[10:39:17][C][logger:234]:   Level: DEBUG
[10:39:17][C][logger:235]:   Log Baud Rate: 115200
[10:39:17][C][logger:236]:   Hardware UART: UART0
[10:39:17][C][uart.arduino_esp8266:102]: UART Bus:
[10:39:17][C][uart.arduino_esp8266:103]:   TX Pin: GPIO15
[10:39:17][C][uart.arduino_esp8266:104]:   RX Pin: GPIO13
[10:39:17][C][uart.arduino_esp8266:106]:   RX Buffer Size: 256
[10:39:17][C][uart.arduino_esp8266:108]:   Baud Rate: 9600 baud
[10:39:17][C][uart.arduino_esp8266:109]:   Data Bits: 8
[10:39:17][C][uart.arduino_esp8266:110]:   Parity: NONE
[10:39:17][C][uart.arduino_esp8266:111]:   Stop bits: 1
[10:39:17][C][uart.arduino_esp8266:115]:   Using software serial
[10:39:17][C][template.select:064]: Template Select 'Mode'
[10:39:17][C][template.select:065]:   Update Interval: 10.0s
[10:39:17][C][template.sensor:023]: Template Sensor 'Eurom_Temperature'
[10:39:17][C][template.sensor:023]:   Device Class: 'temperature'
[10:39:17][C][template.sensor:023]:   State Class: 'measurement'
[10:39:17][C][template.sensor:023]:   Unit of Measurement: '°C'
[10:39:17][C][template.sensor:023]:   Accuracy Decimals: 0
[10:39:17][C][template.sensor:023]:   Icon: 'mdi:thermometer'
[10:39:17][C][template.sensor:024]:   Update Interval: 5.0s
[10:39:17][C][template.switch:058]: Template Switch 'Eurom_swing'
[10:39:17][C][template.switch:059]:   Restore State: NO
[10:39:17][C][template.switch:060]:   Optimistic: NO
[10:39:17][C][template.switch:058]: Template Switch 'Eurom_power'
[10:39:17][C][template.switch:059]:   Restore State: NO
[10:39:17][C][template.switch:060]:   Optimistic: NO
[10:39:17][C][wifi_info:013]: WifiInfo Mac Address 'ESP Mac Wifi Address'
[10:39:17][C][captive_portal:144]: Captive Portal:
[10:39:17][C][mdns:084]: mDNS:
[10:39:17][C][mdns:085]:   Hostname: eurom-garage
[10:39:17][C][ota:085]: Over-The-Air Updates:
[10:39:17][C][ota:086]:   Address: eurom-garage.local:8266
[10:39:17][C][ota:089]:   Using Password.
[10:39:17][C][api:138]: API Server:
[10:39:17][C][api:139]:   Address: eurom-garage.local:6053
[10:39:17][C][api:143]:   Using noise encryption: NO
[10:39:17][C][wifi_info:009]: WifiInfo IPAddress 'ESP IP Address'
[10:39:17][C][wifi_info:011]: WifiInfo SSID 'ESP Connected SSID'
[10:39:17][C][wifi_info:012]: WifiInfo BSSID 'ESP Connected BSSID'
[10:39:18][D][select:032]: 'Mode': Sending state OFF
[10:39:19][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:39:24][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:39:25][D][uart_debug:158]: >>> "\xF1\xF1\x01\x00\x01~"
[10:39:25][D][uart_debug:158]: <<< "\xF2\xF2\x02\x10\x01\x01\x00\x00\x00\x00\x03\f\x00\x00\v\x00\x00\x00\x020~"
[10:39:28][D][select:032]: 'Mode': Sending state OFF
[10:39:29][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:39:29][D][switch:013]: 'Eurom_power' Turning ON.
[10:39:29][D][main:190]: Turn On (mode 2 + Swing)
[10:39:29][D][uart_debug:158]: >>> "\xF1\xF1\x02\x10\x01\x01\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x19~"
[10:39:29][D][uart_debug:158]: <<< "\xF2\xF2\x02\x10\x01\x01\x00\x00\x00\x00\x03\f\x00\x00\f\x00\x00\x00\x021~"
[10:39:34][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:39:38][D][select:032]: 'Mode': Sending state OFF
[10:39:39][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:39:40][D][switch:013]: 'Eurom_swing' Turning ON.
[10:39:40][D][main:171]: Swing Turned On!
[10:39:40][D][uart_debug:158]: >>> "\xF1\xF1\x02\x10\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x16~"
[10:39:40][D][uart_debug:158]: <<< "\xF2\xF2\x02\x10\x01\x01\x00\x00\x00\x00\x03\f\x00\x00\f\x00\x00\x00\x021~"
[10:39:41][D][switch:017]: 'Eurom_swing' Turning OFF.
[10:39:41][D][main:163]: Swing Turned Off!
[10:39:41][D][uart_debug:158]: >>> "\xF1\xF1\x02\x10\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x17~"
[10:39:42][D][uart_debug:158]: <<< "\xF2\xF2\x02\x10\x01\x02\x00\x00\x00\x00\x03\f\x00\x00\f\x00\x00\x00\x022~"
[10:39:44][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:39:48][D][select:032]: 'Mode': Sending state OFF
[10:39:49][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:39:54][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:39:57][D][select:010]: 'Mode' - Setting
[10:39:57][D][select:025]:   Option: 50%
[10:39:57][D][main:106]: Change mode to 50%
[10:39:57][D][uart_debug:158]: >>> "\xF1\xF1\x02\x10\x01\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02\x17~"
[10:39:58][D][uart_debug:158]: <<< "\xF2\xF2\x02\x10\x01\x02\x00\x00\x00\x00\x02\f\x00\x00\f\x00\x00\x00\x021~"
[10:39:58][D][select:032]: 'Mode': Sending state OFF
[10:39:59][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:40:04][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:40:06][D][select:010]: 'Mode' - Setting
[10:40:06][D][select:025]:   Option: 100%
[10:40:06][D][main:106]: Change mode to 100%
[10:40:06][D][uart_debug:158]: >>> "\xF1\xF1\x02\x10\x01\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x18~"
[10:40:06][D][uart_debug:158]: <<< "\xF2\xF2\x02\x10\x01\x02\x00\x00\x00\x00\x03\f\x00\x00\f\x00\x00\x00\x022~"
[10:40:08][D][select:032]: 'Mode': Sending state OFF
[10:40:09][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:40:14][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:40:18][D][select:032]: 'Mode': Sending state OFF
[10:40:19][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:40:24][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy
[10:40:24][D][switch:013]: 'Eurom_power' Turning ON.
[10:40:24][D][main:190]: Turn On (mode 2 + Swing)
[10:40:24][D][uart_debug:158]: >>> "\xF1\xF1\x02\x10\x01\x01\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x19~"
[10:40:24][D][uart_debug:158]: <<< "\xF2\xF2\x02\x10\x01\x01\x00\x00\x00\x00\x03\f\x00\x00\f\x00\x00\x00\x021~"
[10:40:28][D][select:032]: 'Mode': Sending state OFF
[10:40:29][D][sensor:124]: 'Eurom_Temperature': Sending state 1364.00000 °C with 0 decimals of accuracy

Great work, looking good. It works on quite some Eurom heaters.
Any idea on how to add this to the dashboard like:

Thx

Edit: nm I cocked up using the string output instead of hex.

[13:03:26][D][uart_debug:114]: >>> F1;F1;02;10;01;01;00;00;00;00;02;00;00;00;00;00;00;00;02;18;7E
[13:03:26][D][uart_debug:114]: <<< F2;F2;02;10;01;01;00;00;00;00;02;0A
[13:03:26][D][uart_debug:114]: <<< 00;00;0F;00;00;00;02;31;7E
[13:03:28][D][uart_debug:114]: >>> F1;F1;01;00;01;7E
[13:03:28][D][uart_debug:114]: <<< F2;F2;02;10;01;01;00;00;00;00;02;0A
[13:03:28][D][uart_debug:114]: <<< 00;00;0F;00;00;00;02;31;7E
[13:03:48][D][uart_debug:114]: >>> F1;F1;01;00;01;7E
[13:03:48][D][uart_debug:114]: <<< F2;F2;02;10;01;01;00;00;00;00;02;0A
[13:03:48][D][uart_debug:114]: <<< 00;00;0F;00;00;00;02;31;7E
[13:04:08][D][uart_debug:114]: >>> F1;F1;01;00;01;7E
[13:04:08][D][uart_debug:114]: <<< F2;F2;02;10;01;01;00;00;00;00;02;0A
[13:04:08][D][uart_debug:114]: <<< 00;00;0F;00;00;00;02;31;7E
[13:04:28][D][uart_debug:114]: >>> F1;F1;01;00;01;7E
[13:04:28][D][uart_debug:114]: <<< F2;F2;02;10;01;01;00;00;00;00;02;0A
[13:04:28][D][uart_debug:114]: <<< 00;00;0F;00;00;00;02;31;7E
[13:04:48][D][uart_debug:114]: >>> F1;F1;01;00;01;7E
[13:04:48][D][uart_debug:114]: <<< F2;F2;02;10;01;01;00;00;00;00;02;0A
[13:04:48][D][uart_debug:114]: <<< 00;00;0F;00;00;00;02;31;7E

Okay, so I somehow managed to break OTA/logs on my ESP, so I need to remove the damn heater again in order to flash it.

Actually the HEX UART format isn’t difficult to understand. It has 20 HEX bytes

nr 1+2 [0+1] are start bytes F2F2
nr 12 [11] is HEX rep of set temp
nr 20 [19] is HEX rep INT of temp +41

I think nr 15 [14] is just HEX rep of sensed temperature.

I’ll try to see if the others are representations of a state (1000w, 2000w, off, mover) if I ever get the esp fixed again.

Hello

I don’t have much time at the moment. I also have problems from time to time:
I can send a serial command but it is not executed and I don’t get any response. Sometimes 5 minutes later, when I resend the command it works again.

For debugging, it is better to replace a part of the code with this

uart:
  rx_pin: 13
  tx_pin: 15
  baud_rate: 9600
  id: uart_bus
  rx_buffer_size : 50
  
  debug:
    direction: BOTH
    dummy_receiver: false
    after:
      delimiter: "\n"
    sequence:
      - lambda: UARTDebug::log_hex(direction, bytes, ' ');

The log will be easier

I used this to help me:
https://templates.blakadder.com/devola_designer.html

1 Like

Thank you kindly for your reply. It will give me pointers in the right direction once I find the time to remove the heater again.

1 Like

Hey Dieter,

I’ve bought a Eurom Wall Designheat 2000 Wifi, which probably uses the same serial protocol. Did you ever finish your flashing project?

Tnx!

No, I gave up on the project unfortunately.

Are you now using local Tuya, or just resorted to the cloud-based access?

Hello,

I had made some mistakes in the serial commands
I switched to tasmota.
I have been using it for several weeks now and I have not had any bugs

RULE1 ON time#minute|1 DO serialsend5 F1F10100017E endon
RULE1 1

Home assistant

mqtt:
  sensor:
    - name: "heater_sdb_temperature"
      state_topic: "tele/tasmota_95864C/RESULT"
      value_template: " {{ value_json.SerialReceived[28:30] | int(base=16) }}"
      unit_of_measurement: "°C"
      payload_available: "Online"
      payload_not_available: "Offline"

  switch:
    - unique_id: heater_sdb_switch2
      name: "heater_sdb_switch2"
      state_topic: "tele/tasmota_95864C/RESULT"
      value_template: "{%if value_json.SerialReceived[9:10] == '1' -%}ON{%-else-%}OFF{%-endif%}"
      command_topic: "cmnd/tasmota_95864C/serialsend5"
      payload_on: "F1F10210010100000000030000000000000000177E"
      payload_off: "F1F10210020000000000000000000000000000147E"
      state_on: "ON"
      state_off: "OFF"
      optimistic: false
      qos: 0
      retain: false
      
    - unique_id: heater_sdb_swing2
      name: "heater_sdb_swing2"
      state_topic: "tele/tasmota_95864C/RESULT"
      value_template: "{%if value_json.SerialReceived[11:12] == '1' -%}ON{%-elif value_json.SerialReceived[11:12] == '0'-%}UNAVAILABLE{%-else-%}OFF{%-endif%}"
      state_on: "ON"
      state_off: "OFF"
      command_topic: "cmnd/tasmota_95864C/serialsend5"
      payload_on: "F1F10210010100000000030000000000000000177E"
      payload_off: "F1F10210020000000000000000000000000000147E"
      availability_topic: "tele/tasmota_95864C/RESULT"
      availability_template : "{%if value_json.SerialReceived[9:10] == '1' -%}ON{%-else-%}OFF{%-endif%}"
      payload_available: "ON"
      payload_not_available: "OFF"
      optimistic: false
      qos: 0
      retain: false

image

I hope this will help you

1 Like

there are a Arduino sketch for the WiFi Module available here:

Maybe this helps somone else too

I bought a second-hand Eurom Wall Designheat 2000 Wifi and wanted to convert it to Tasmota. I succeeded :slight_smile:

Inside is, separate from the main PCB (with KW68F78 / K28210120 MCU) a TYJW2.1 pcb with a TYWE1S chip on it (same as in picture first post of this thread) recognized by esptool.py as an ESP8266EX with 2MB flash. To flash it, connect BOOT to GND for a few seconds when powering on the ESP module. When flashing has succeeded, put module back in the heater as my USB-Serial didn’t seem to have enough power to boot Tasmota (wdt crash reboot loop).

I first tried the TuyaMCU examples that are used for other Eurom products, but wasn’t able to get it working at all. In the end it turned out to be very similar to this device Devola Designer Glass Panel Heater Configuration for Tasmota and same F1F1xxxxxx-commands as posted higher up in this thread. The ‘childlock’ parameter (on/off) seems to control the flap swing on this heater.

I asked ChatGPT to create some Node-RED functionality, so i could easily create the hexcommands i wanted. I used these hexcommands to create a Tasmota rule (#3) that is attached to a dummy switch (‘Relay’ at D2 GPIO4). When the button in webinterface is switched on, it turns the heater on with setpoint 21°C, flap swing on and heating at high (2000W). It then waits 16 secs, this is the time the flap swing needs to reach the highest point. I then disable swing (send same heat level, setpoint etc, but now with childlock (=swing) off). By fixating the flap at the highest point this way, the heat is much better blown into my living room.

The other rules (#1, #2) are inspired from the Devola page. They are present to have the wifi-led blink/on on system boot/wifi connect and to put Tasmota in AP mode when the wifi button is pressed. And a rule to poll the MCU every 60s (to keep it awake or something i read?).

RULE1 ON System#Init do sserialsend5 f1f10210000000000000000000000000000300157E ENDON ON WiFi#Connected do sserialsend5 f1f10210000000000000000000000000000100137E ENDON ON Wifi#Disconnected do sserialsend5 f1f10210000000000000000000000000000300157E ENDON ON sserialreceived#Data=F2F20600067E DO Wificonfig 2 ENDON
RULE2 ON System#Boot DO RuleTimer1 60 ENDON ON Rules#Timer=1 DO backlog sserialsend5 f1f10100017e; ruletimer1 60 ENDON
RULE3 ON Power1#state=1 DO backlog sserialsend5 F1F10210010100000000031500001201000001407E; Delay 160; sserialsend5 F1F10210010200000000031500001201000001417E ENDON ON Power1#state=0 DO sserialsend5 F1F102100202000000000015000012010000013f7E ENDON
rule1 1
rule2 1
rule3 1

Together with the ‘Timers’ functionality in Tasmota, the heater works standalone perfectly fine now. I can also just flick the switch in Tasmota GUI away from home over VPN if i want to preheat my house.

Configured as module ‘Generic’, with:

  • D7 (GPIO13) - SerBr RX
  • D8 (GPIO15) - SerBr TX
  • D2 (GPIO4) - Relay 1 (dummy button for rule, to have power toggle appear in webUI)

Baudrate between ESP and MCU is 9600 (default of SoftwareSerial in Tasmota). Also configured serialdelimiter 254 as otherwise the received serial hex would be weird unreadable characters in the console.

My unit seems to be from 2019 i thought a saw on a sticker somewhere. I am not sure if the same unit sold today works the same. Maybe those can use the TuyaMCU communication protocol.

@MrHaroldA maybe this can help you, assuming you still have yours :slight_smile:

P.S. In case your external sensor goes missing (the seller of mine had lost it unfortunately), it seems to be a 10K NTC. I connected it, as without the temperature is not accurate at all because of the unit hanging near the ceiling and heat building up around it (showing 31°C withing minutes). Also without the external sensor, the fan keeps running for 30 mins after setpoint has been reached/unit turned off. With external sensor this is only 5 mins, much less annoying.

Something interesting i noticed: the MCU is also a bit ‘smart’. If the setpoint is near the measured roomtemperature, only the low heating (1000W) is activated, even when i send mode 3 to it (high). When i supply a higher setpoint, the high heating mode is activated.

1 Like

I still own two of them, with a lot of problems using them through Local Tuya, so I’m definitely going to look into flashing them!

Do you have a back-up of the original firmware? I would hate to brick mine …

Yes i have, but you can dump it yourself with esptool.py quite easily. First run esptool with the flash_id parameter to find out the size of the flash chip. In my case it was 2MB, but might be different on yours. Then dump the content using

esptool.py --baud 115200 --port COM4 read_flash 0x0 0x200000 Eurom-original-firmware.bin

See also: Installing and using ESPtools – Flamingo-Tech

I didn’t try flashing back the original firmware though
Edit 30-1-2024: flashing back the original firmware worked fine, i used this command:

esptool.py --baud 115200 --port COM4 write_flash 0x0 EuromDesignheat2000wifi_dump.bin

And was able to connect the Eurom Smart app without issues. I flashed back the original FW as i have sold the device.

2 Likes

Cool. I really need to try this, since I ruined the built-in firmware…

1 Like

Did you manage to flash your Eurom heater? It still works fine here with Tasmota, I only find the fan in my Wall Designheat 2000 a bit too noisy.

I also dumped the IR-codes from the remote. Might be useful for someone some time?

1 Like

It’s also still on my todo-list. The NSPanel is done now, so this will be my next project.

I’ll report back when I have some news :wink:

1 Like