This is an old revision of the document!
This project implements two functionalities for my smart home setup:
Both tasks are centered around an ESP32-WROOM board.
The goal for this task was to be able to smart control the AC unit that I have in my home, bypassing the included remote control. The end goal was to have them controlled from anywhere around the globe.
The AC units are Bosch Climate 3000i . These are actually manufactured by Midea and sold under the Bosch brand in Romania . The units feature an OEM dongle option, but the functionality is limited and it comes with a steep price .
The logic board of the AC is hidden away by a plastic tray underneath the front lid. A standard Phillips screw and a set of plastic clips hold the tray and have to be carefully removed. The logic board features a female USB-A receptacle. Despite this, the electrical wiring is not for USB, but for UART . Communication with the AC unit can happen over this port using the Midea protocol .
For this task, I have decided to use an ESP32 board which is wired for communication to the UART port on the AC unit logic board. I have determined that both boards use the same logic voltage levels, so there is no need for level shifters when wiring the RX/TX pins. Since some of the commands of the protocol do not work over the UART connection, I have also connected a standard 940nm infrared LED to the board, through which the remote control's commands are replicated in order to send the unsupported commands. I decided for this hybrid solution instead of going with the IR alone since the UART communication also offers feedback about the current status of the AC unit (current room temperature and other sensor data, for example).
Since a standalone dashboard would introduce too much friction, I have decided to have this board connected to my WiFi network and integrate it with my Home Assistant setup as an additional “service”. This is best achieved by writing an ESPHome description file and having the framework glue modules together in order to produce the desired functionality. Getting a usable prototype is accelerated compared to the traditional approach of writing boiler code that links various libraries together at a high level. ESPHome is a mature ecosystem supported by Nabu Casa, the same team that delivers the world renowned Home Assistant ecosystem.
<hidden config.yaml>
esphome: name: ac-esp friendly_name: AC_ESP esp32: board: esp32dev framework: type: arduino logger: baud_rate: 0 api: encryption: key: "fjkhgusyfhygskfhgbvfxkhvbjkdhgxukhxkghxkxrg=" ota: password: "d76v87687db8ebmdbfjdjb8d789bdbd7" wifi: ssid: REPLACE_WITH_YOUR_SSID password: REPLACE_WITH_YOUR_PASSWORD ap: ssid: "Fallback Hotspot" password: "473958869456" uart: tx_pin: 1 rx_pin: 3 baud_rate: 9600 remote_transmitter: pin: GPIO19 # For iot-uni-stick. carrier_duty_percent: 50% # 50% for IR LED, 100% for direct # connect to TSOP IR receiver output. climate: - platform: midea name: AC_ESP # Use a unique name. period: 1s # Optional timeout: 2s # Optional num_attempts: 3 # Optional autoconf: true # Autoconfigure most options. beeper: false # Beep on commands. visual: # Optional. min_temperature: 17 °C # min: 17 max_temperature: 30 °C # max: 30 temperature_step: 1 °C # min: 0.5 supported_modes: # Optional. - FAN_ONLY - HEAT_COOL - COOL - HEAT - DRY custom_fan_modes: # Optional - SILENT - TURBO supported_presets: # Optional. - ECO - BOOST - SLEEP custom_presets: # Optional. - FREEZE_PROTECTION supported_swing_modes: # Optional - VERTICAL - HORIZONTAL - BOTH outdoor_temperature: # Optional. name: Temp switch: - platform: template name: Beeper icon: mdi:volume-source restore_mode: 'RESTORE_DEFAULT_OFF' optimistic: true turn_on_action: midea_ac.beeper_on: turn_off_action: midea_ac.beeper_off: binary_sensor: - platform: status name: Connection Status id: climate_AC_ESP_connection_status text_sensor: - platform: template name: Uptime id: uptime_human icon: mdi:clock-start - platform: version name: ESPHome Version id: climate_AC_ESP_esphome_version - platform: wifi_info ip_address: name: IP id: climate_AC_ESP_ip_address icon: mdi:ip-network sensor: - platform: uptime name: Uptime Sensor id: uptime_sensor update_interval: 60s on_raw_value: then: - text_sensor.template.publish: id: uptime_human state: !lambda |- int seconds = round(id(uptime_sensor).raw_state); int days = seconds / (24 * 3600); seconds = seconds % (24 * 3600); int hours = seconds / 3600; seconds = seconds % 3600; int minutes = seconds / 60; seconds = seconds % 60; return ( (days ? to_string(days) + "d " : "") + (hours ? to_string(hours) + "h " : "") + (minutes ? to_string(minutes) + "m " : "") + (to_string(seconds) + "s") ).c_str(); - platform: wifi_signal name: WiFi Signal id: climate_AC_ESP_wifi_signal update_interval: 60s button: - platform: restart name: Reboot id: climate_AC_ESP_restart icon: "mdi:restart" - platform: shutdown name: Shutdown id: climate_AC_ESP_shutdown - platform: safe_mode name: Reboot (Safe Mode) id: climate_AC_ESP_safe_mode - platform: template name: Display Toggle id: climate_AC_ESP_display_toggle icon: mdi:theme-light-dark on_press: midea_ac.display_toggle: - platform: template name: Swing Step icon: mdi:tailwind on_press: midea_ac.swing_step:
</hidden>
uint8_t i[];
const unsigned int t;