Hey Guys,
I bought a princess smart panel heater like this:
It is wifi enabled and controllable with the homewizard climat app. I did send a mail to support to ask for an open (local) API, you can guess the answer. You need to stay connected to the internet for the smart functions and HA integration is not possible…
So I started to investigate with tcpdump and nmap, but the traffic was TLS encrypted and no open ports on the heater.
My second option was to MITM the android app with an SSL proxy and custom CA and with great success, i got the ins and outs of the android app (websockets) and created a python bridge (HomewizardWebsocketsToMQTT). There were 2 problems: Every 30min a reconnect and we still needed the homewizard cloud connection. After all, the bridge was merely an android app emulation.
So back to the drawing board…
The heater does a DNS lookup for: m.cloud.homewizard.com and creates a connection to 443 (TLS). I changed my DNS server to point m.cloud.homewizard.com to my SSL proxy, but no cigar.
So maybe the subdomain m stands for mqtt… I knew I needed a TLS connection, and my best guess was MQTT over websockets. So I created a self-signed cert, opened a 443 TLS enable websocket and pointed the m.cloud.homewizard.com domain to my mosquitto server in verbose mode and bingo:
1613210905: New client connected from ::ffff:10.20.30.40 as ESP32_217CC0 (p2, c1, k10).
It immediately started to subscribe to topics and pushed some retained messages!! I disabled the internet of the heater in the firewall, and now I have full local MQTT control!
How TO:
- Connect the heater to the Wi-Fi like original intended (maybe you can sniff the setup stuff and keep it local, but I didn’t, my heater was already on the network with cloud access)
- Block the internet (so no FW updates are possible)
- Redirect m.cloud.homewizard.com to your MQTT server
- Create a self-signed certificate:
openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 3650 -out certificate.pem
Country Name (2 letter code) [XX]:US
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:Let's Encrypt
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:m.cloud.homewizard.com
Email Address []:
- copy the files (key.pem and certificate.pem) to your MQTT broker. (i used mosquitto v1.6.12)
- Create the MQTT websocket listener on port 443
vi /etc/mosquitto/mosquitto.conf
add:
port 443
protocol websockets
certfile /etc/mosquitto/certs/m.cloud.homewizard.certificate.pem
keyfile /etc/mosquitto/certs/m.cloud.homewizard.key.pem
listener 1883
protocol mqtt
Be sure to remove any authentication. I also use listener 1883 with protocol MQTT for non SSL local MQTT stuff.
Restart the broker and enjoy your MQTT local controllable heater.
When the heater connects to the broker, it sends the following retained messages:
appliance/heater/macadressheater/state {"power_on":"false","lock":"false","target_temperature":"25","current_temperature":"12","timer":"0","mode":"low"}
appliance/heater/macadressheater/state/power_on false
appliance/heater/macadressheater/state/lock false
appliance/heater/macadressheater/state/target_temperature 25
appliance/heater/macadressheater/state/timer 0
appliance/heater/macadressheater/state/mode low
appliance/heater/macadressheater/state/current_temperature 12
appliance/heater/macadressheater/$online true
appliance/heater/macadressheater/$version 1.07
appliance/heater/macadressheater/$properties [{"name":"power_on","type":"bool","readonly":false},{"name":"lock","type":"bool","readonly":false},{"name":"target_temperature","type":"int","readonly":false},{"name":"current_temperature","type":"int","readonly":true},{"name":"timer","type":"int","readonly":false},{"name":"mode","type":"enum","values":["high","low"],"readonly":false}]
appliance/heater/macadressheater/$name Heater
appliance/heater/macadressheater/$type heater
And you can control it with:
appliance/heater/macadressheater/$online (true/false) < last will
appliance/heater/macadressheater/$update/set (??)
appliance/heater/macadressheater/$beep (??)
appliance/heater/macadressheater/$wifi_led (??)
appliance/heater/macadressheater/state/power_on/set (true/false)
appliance/heater/macadressheater/state/lock/set (true/false)
appliance/heater/macadressheater/state/target_temperature/set (int)
appliance/heater/macadressheater/state/timer/set (int)
appliance/heater/macadressheater/state/mode/set (low/high)
appliance/heater/macadressheater/$token (??)
HA example:
Yaml in config:
***** SEE EDIT2 FOR THE NEW FORMAT ****
switch:
- platform: mqtt
name: "Badkamer vuurtje lock"
state_topic: "appliance/heater/macadressheater/state/lock"
command_topic: "appliance/heater/macadressheater/state/lock/set"
payload_on: "true"
payload_off: "false"
state_on: "true"
state_off: "false"
- platform: mqtt
name: "Badkamer vuurtje mode"
state_topic: "appliance/heater/macadressheater/state/mode"
command_topic: "appliance/heater/macadressheater/state/mode/set"
payload_on: "high"
payload_off: "low"
state_on: "high"
state_off: "low"
climate:
- platform: mqtt
name: Badkamer
fan_modes:
- "high"
- "low"
modes: ["off", "heat"]
mode_command_topic: "appliance/heater/macadressheater/state/power_on/set"
mode_state_topic: "appliance/heater/macadressheater/state/power_on"
mode_state_template: >-
{% if value == "false" %}
off
{% elif value == "true" %}
heat
{% endif %}
mode_command_template: >-
{% if value == "off" %}
false
{% elif value == "heat" %}
true
{% endif %}
min_temp: 10
max_temp: 35
current_temperature_topic: "appliance/heater/macadressheater/state/current_temperature"
temperature_command_topic: "appliance/heater/macadressheater/state/target_temperature/set"
temperature_state_topic: "appliance/heater/macadressheater/state/target_temperature"
fan_mode_command_topic: "appliance/heater/macadressheater/state/mode/set"
fan_mode_state_topic: "appliance/heater/macadressheater/state/mode"
precision: 1.0
Lovelace yaml:
- type: vertical-stack
title: Badkamer
cards:
- type: thermostat
entity: climate.badkamer
- type: entities
entities:
- entity: switch.badkamer_vuurtje_mode
name: mode (low/high)
- entity: switch.badkamer_vuurtje_lock
name: lock (OFF/ON)
show_header_toggle: false
I only own this exact model, so I don’t know if the other homewizard climat devices acting the same.
I really enjoyed the quest for local control and I hope it can be of use for some of you!
Greets,
Edit: Also check the edit here: Homewizard climate local MQTT control! - #6 by a1ad
Edit2: yml config in the new format:
mqtt:
climate:
- name: Badkamer
fan_modes:
- "high"
- "low"
modes: ["off", "heat"]
mode_command_topic: "appliance/heater/3c39e7217cc0/state/power_on/set"
mode_state_topic: "appliance/heater/3c39e7217cc0/state/power_on"
mode_state_template: >-
{% if value == "false" %}
off
{% elif value == "true" %}
heat
{% endif %}
mode_command_template: >-
{% if value == "off" %}
false
{% elif value == "heat" %}
true
{% endif %}
min_temp: 10
max_temp: 35
current_temperature_topic: "appliance/heater/3c39e7217cc0/state/current_temperature"
temperature_command_topic: "appliance/heater/3c39e7217cc0/state/target_temperature/set"
temperature_state_topic: "appliance/heater/3c39e7217cc0/state/target_temperature"
fan_mode_command_topic: "appliance/heater/3c39e7217cc0/state/mode/set"
fan_mode_state_topic: "appliance/heater/3c39e7217cc0/state/mode"
precision: 1.0
switch:
- name: "Badkamer vuurtje"
state_topic: "appliance/heater/3c39e7217cc0/state/power_on"
command_topic: "appliance/heater/3c39e7217cc0/state/power_on/set"
payload_on: "true"
payload_off: "false"
state_on: "true"
state_off: "false"
- name: "Badkamer vuurtje lock"
state_topic: "appliance/heater/3c39e7217cc0/state/lock"
command_topic: "appliance/heater/3c39e7217cc0/state/lock/set"
payload_on: "true"
payload_off: "false"
state_on: "true"
state_off: "false"
- name: "Badkamer vuurtje mode"
state_topic: "appliance/heater/3c39e7217cc0/state/mode"
command_topic: "appliance/heater/3c39e7217cc0/state/mode/set"
payload_on: "high"
payload_off: "low"
state_on: "high"
state_off: "low"
sensor:
- platform: mqtt
state_topic: "homewiz/heater/3c39e7217cc0/state/current_temperature"
name: Temperatuur Vuurtje badkamer
- platform: mqtt
state_topic: "homewiz/heater/3c39e7217cc0/state/target_temperature"
name: Target temp Vuurtje badkamer