Closed dhewg closed 9 months ago
I'm planning to give this a shot during the weekend, I need to familiarize myself with the details of the process.
Here are my findings:
Overall very usable, I'm only really missing favorite speed.
Huh, at first glance display brightness and favorite speed is set up correctly. Can you switch the logger level from DEBUG
to VERBOSE
and post some logs?
Sure, I need to figure out how to do this trough mqtt. I've reassembled the unit.
Here is a fragment where esp queries stm for various things.
[18:12:40][D][miot:125]: Queuing MCU command 'get_properties 2 1 2 2 2 4 3 4 4 1 4 3 6 1 7 2 8 1 9 1 9 3'
[18:12:40][V][miot:091]: Received MCU message 'get_down'
[18:12:40][V][miot:171]: Sending reply 'down get_properties 2 1 2 2 2 4 3 4 4 1 4 3 6 1 7 2 8 1 9 1 9 3' to MCU
[18:12:40][V][miot:091]: Received MCU message 'result 2 1 0 false 2 2 0 "null" 2 4 0 1 3 4 0 1 4 1 0 100 4 3 0 0 6 1 0 true 7 2 0 3 8 1 0 false 9 1 0 0 9 3 0 1700'
[18:12:40][V][miot.switch:012]: MCU reported switch 2:1 is: OFF
[18:12:40][V][miot.text_sensor:011]: MCU reported text sensor 2:2 is: null
[18:12:40][V][text_sensor:013]: 'Device Fault': Received new state null
[18:12:40][D][text_sensor:064]: 'Device Fault': Sending state 'null'
[18:12:40][V][mqtt:474]: Publish(topic='purifier/sensor/device_fault/state' payload='null' retain=1)
[18:12:40][V][miot.select:011]: MCU reported select 2:4 is: 1
[18:12:40][D][select:015]: 'Mode': Sending state Sleep (index 1)
[18:12:40][V][mqtt:474]: Publish(topic='purifier/select/mode/state' payload='Sleep' retain=1)
[18:12:40][V][miot.sensor:011]: MCU reported sensor 3:4 is: 1.000000
[18:12:40][V][sensor:043]: 'PM2.5 Density': Received new state 1.000000
[18:12:40][D][sensor:094]: 'PM2.5 Density': Sending state 1.00000 µg/m³ with 0 decimals of accuracy
[18:12:40][V][mqtt:474]: Publish(topic='purifier/sensor/pm2_5_density/state' payload='1' retain=1)
[18:12:40][V][miot.sensor:011]: MCU reported sensor 4:1 is: 100.000000
[18:12:40][V][sensor:043]: 'Filter Life Level': Received new state 100.000000
[18:12:40][D][sensor:094]: 'Filter Life Level': Sending state 100.00000 % with 0 decimals of accuracy
[18:12:40][V][mqtt:474]: Publish(topic='purifier/sensor/filter_life_level/state' payload='100' retain=1)
[18:12:40][V][miot.sensor:011]: MCU reported sensor 4:3 is: 0.000000
[18:12:40][V][sensor:043]: 'Filter Used Time': Received new state 0.000000
[18:12:40][D][sensor:094]: 'Filter Used Time': Sending state 0.00000 h with 0 decimals of accuracy
[18:12:40][V][mqtt:474]: Publish(topic='purifier/sensor/filter_used_time/state' payload='0' retain=1)
[18:12:40][V][miot.switch:012]: MCU reported switch 6:1 is: ON
[18:12:40][V][miot.number:011]: MCU reported number 7:2 is: 3.000000
[18:12:40][D][number:012]: 'Display Brightness': Sending state 3.000000
[18:12:40][V][mqtt:474]: Publish(topic='purifier/number/display_brightness/state' payload='3.000000' retain=1)
[18:12:40][V][miot.switch:012]: MCU reported switch 8:1 is: OFF
[18:12:40][V][miot.sensor:011]: MCU reported sensor 9:1 is: 0.000000
[18:12:40][V][sensor:043]: 'Motor Speed': Received new state 0.000000
[18:12:40][D][sensor:094]: 'Motor Speed': Sending state 0.00000 rpm with 0 decimals of accuracy
[18:12:40][V][mqtt:474]: Publish(topic='purifier/sensor/motor_speed/state' payload='0' retain=1)
[18:12:40][V][miot.number:011]: MCU reported number 9:3 is: 1700.000000
[18:12:40][D][number:012]: 'Favorite Speed': Sending state 1700.000000
[18:12:40][V][mqtt:474]: Publish(topic='purifier/number/favorite_speed/state' payload='1700.000000' retain=1)
[18:12:40][V][miot:171]: Sending reply 'ok' to MCU
[18:12:40][V][miot:091]: Received MCU message 'get_down'
[18:12:40][V][miot:171]: Sending reply 'down none' to MCU
[18:12:40][V][miot:091]: Received MCU message 'error "method not found" -5000'
[18:12:40][E][miot:284]: MCU command error -5000: method not found
[18:12:40][V][miot:171]: Sending reply 'ok' to MCU
[18:12:40][W][component:214]: Component miot took a long time for an operation (0.39 s).
[18:12:41][W][component:215]: Components should block for at most 20-30ms.
[18:12:41][V][miot:091]: Received MCU message 'get_down'
[18:12:41][V][miot:171]: Sending reply 'down none' to MCU
[18:12:41][V][miot:091]: Received MCU message 'get_down'
[18:12:41][V][miot:171]: Sending reply 'down none' to MCU
[18:12:41][V][miot:091]: Received MCU message 'mac'
[18:12:41][W][miot:291]: Unknown command 'mac'
[18:12:41][V][miot:171]: Sending reply 'ok' to MCU
[18:12:41][V][miot:091]: Received MCU message 'get_down'
[18:12:41][V][miot:171]: Sending reply 'down none' to MCU
[18:12:41][V][miot:091]: Received MCU message 'get_down'
[18:12:41][V][miot:171]: Sending reply 'down none' to MCU
Here is where I try to set the fav speed
[18:15:36][V][miot:171]: Sending reply 'down none' to MCU
[18:15:36][D][number:054]: 'Favorite Speed' - Setting number value
[18:15:36][D][number:113]: New number value: 1000.000000
[18:15:36][V][miot.number:017]: Setting number 9:3 1000.000000
[18:15:36][D][miot:125]: Queuing MCU command 'set_properties 9 3 1000.000000'
[18:15:36][D][number:012]: 'Favorite Speed': Sending state 1000.000000
[18:15:36][V][mqtt:474]: Publish(topic='purifier/number/favorite_speed/state' payload='1000.000000' retain=1)
[18:15:36][W][component:214]: Component api took a long time for an operation (0.06 s).
[18:15:36][W][component:215]: Components should block for at most 20-30ms.
[18:15:36][V][miot:091]: Received MCU message 'get_down'
[18:15:36][V][miot:171]: Sending reply 'down set_properties 9 3 1000.000000' to MCU
[18:15:36][V][miot:091]: Received MCU message 'result 9 3 -4003'
[18:15:36][E][miot:218]: Result error on property 9:3: -4003
[18:15:36][V][miot:171]: Sending reply 'ok' to MCU
[18:15:37][V][miot:091]: Received MCU message 'get_down'
[18:15:37][V][miot:171]: Sending reply 'down none' to MCU
[18:15:37][V][miot:091]: Received MCU message 'get_down'
[18:15:37][V][miot:171]: Sending reply 'down none' to MCU
[18:15:37][V][miot:091]: Received MCU message 'mac'
[18:15:37][W][miot:291]: Unknown command 'mac'
[18:15:37][V][miot:171]: Sending reply 'ok' to MCU
[18:15:37][V][miot:091]: Received MCU message 'get_down'
[18:15:37][V][miot:171]: Sending reply 'down none' to MCU
Interestingly on startup there is
[18:21:10][W][miot:183]: Received property value without component: 7 1 true
Which does not seem to appear later
Here is one for the brightness:
[18:25:47][D][number:054]: 'Display Brightness' - Setting number value
[18:25:47][D][number:113]: New number value: 7.000000
[18:25:47][V][miot.number:017]: Setting number 7:2 7.000000
[18:25:47][D][miot:125]: Queuing MCU command 'set_properties 7 2 7.000000'
[18:25:47][D][number:012]: 'Display Brightness': Sending state 7.000000
[18:25:47][V][miot:091]: Received MCU message 'get_down'
[18:25:47][V][miot:171]: Sending reply 'down set_properties 7 2 7.000000' to MCU
[18:25:47][V][miot:091]: Received MCU message 'result 7 2 -4003'
[18:25:47][E][miot:218]: Result error on property 7:2: -4003
[18:25:47][V][miot:171]: Sending reply 'ok' to MCU
[18:25:47][V][miot:091]: Received MCU message 'get_down'
[18:25:47][V][miot:171]: Sending reply 'down none' to MCU
Device Fault
is null
as that's the mcu answer, as you can see in the logs.
You can try adding
filters:
- substitute:
- "null -> No Faults"
to the text sensor to make it more user/gui friendly. An opened door might just not show up there, e.g. my 4lite has serious stuff like motor fault
in there ;)
The brightness/fav speed is weird, the values are sent as e.g. 7.000000
, but it's supposed to be just 7
. I'll take a look, but my first guess is that's it's how mtqq sends values. Does it work with api:
?
I may be mistaken, but I'm testing the commands from HASS, therefore it should be using api, right ?
Btw, that mqtt stuff that I said earlier was because of my ignorance, I thought that was the correct way to obtain logs, but figured it out and removed mqtt:
from config there after
I didn't have time to test this module, but here is the component I originally adapted. All functionalities are working as expected... just in case It helps debug...
Some of the code is there just because it was used while testing, specially the dirty part around these variables:
int last_41, last_21, last_24, last_34, last_61, last_81, last_72, last_93, last_43, last_91;
https://gist.github.com/daniel-dona/bea0773e3ec4147cd0a58150f055318d
Filter used time went up to 1h. I guess it works then, weird that it reset itself.
Filter used time went up to 1h. I guess it works then, weird that it reset itself.
One of the MIOT defined actions is filter reset, check this:
Yes, but I did not trigger this action on purpose (as far as I am aware).
I checked my device, and indeed it also get values like 7.000000
. But compared to the 3C it accepts that value. I guess the fw on the 3C refuses the precision, and I pushed a possible fix to the number
branch here. Please test that by replacing @main
with @number
at the top of the yaml file, does it work then?
Yes, but I did not trigger this action on purpose (as far as I am aware).
That's unexpected. The filter life was kept as I replaced the vendor fw with esphome, I only tested a reset afterwards, which worked too.
Yes, but I did not trigger this action on purpose (as far as I am aware).
The other way to reset it was something like pressing the buttons for some time, maybe that was the case (?)
Mine only reset by calling the action manually, I'm not sure...
Well, because I've screwed up I had to ask my friend to solder in a new ESP32 (which I've programed beforehand) there is a good chance that this has something to do with this depending on where this info is stored.
In any case @number
works like a charm (both fan speed and backlight)
[20:31:18][D][number:054]: 'Favorite Speed' - Setting number value
[20:31:18][D][number:113]: New number value: 1000.000000
[20:31:18][V][miot.number:017]: Setting number 9:3 1000.000000
[20:31:18][D][miot:125]: Queuing MCU command 'set_properties 9 3 1000'
[20:31:18][D][number:012]: 'Favorite Speed': Sending state 1000.000000
[20:31:18][V][miot:091]: Received MCU message 'get_down'
[20:31:18][V][miot:171]: Sending reply 'down set_properties 9 3 1000' to MCU
[20:31:18][V][miot:091]: Received MCU message 'result 9 3 0'
[20:31:18][V][miot:171]: Sending reply 'ok' to MCU
[20:31:18][V][miot:091]: Received MCU message 'properties_changed 9 3 1000 2 4 2'
[20:31:18][V][miot.number:011]: MCU reported number 9:3 is: 1000.000000
[20:31:18][D][number:012]: 'Favorite Speed': Sending state 1000.000000
[20:31:18][V][miot.select:011]: MCU reported select 2:4 is: 2
[20:31:18][D][select:015]: 'Mode': Sending state Favorite (index 2)
Nice, thanks for the confirmation! Fix pushed to @main
, so please switch back to that branch as I deleted @number
now :)
In the mean time I've tested the "Reset filter" action:
[20:41:20][D][button:010]: 'Reset Filter Life' Pressed.
[20:41:20][D][miot:125]: Queuing MCU command 'action 4 1 3'
[20:41:20][V][miot:091]: Received MCU message 'get_down'
[20:41:20][V][miot:171]: Sending reply 'down action 4 1 3' to MCU
[20:41:20][V][miot:091]: Received MCU message 'result -4006'
[20:41:20][V][miot:171]: Sending reply 'ok' to MCU
HASS keeps showing "2h" and when the periodic check occurs this is the fragment for the filter life:
[20:42:29][V][miot.sensor:011]: MCU reported sensor 4:3 is: 2.000000
[20:42:29][V][sensor:043]: 'Filter Used Time': Received new state 2.000000
[20:42:29][D][sensor:094]: 'Filter Used Time': Sending state 2.00000 h with 0 decimals of accuracy
Btw. Thank you guys for your work, you are amazing :beers:
In the mean time I've tested the "Reset filter" action:
[20:41:20][D][button:010]: 'Reset Filter Life' Pressed. [20:41:20][D][miot:125]: Queuing MCU command 'action 4 1 3' [20:41:20][V][miot:091]: Received MCU message 'get_down' [20:41:20][V][miot:171]: Sending reply 'down action 4 1 3' to MCU [20:41:20][V][miot:091]: Received MCU message 'result -4006' [20:41:20][V][miot:171]: Sending reply 'ok' to MCU
HASS keeps showing "2h" and when the periodic check occurs this is the fragment for the filter life:
[20:42:29][V][miot.sensor:011]: MCU reported sensor 4:3 is: 2.000000 [20:42:29][V][sensor:043]: 'Filter Used Time': Received new state 2.000000 [20:42:29][D][sensor:094]: 'Filter Used Time': Sending state 2.00000 h with 0 decimals of accuracy
Btw. Thank you guys for your work, you are amazing 🍻
Try using a different value in the action, 100 or something like that worked for me...
action 4 1 100
Not even sure what the last parameter means, is not clearly documented in the spec
Unfortunately it did not work
[20:51:49][D][button:010]: 'Reset Filter Life' Pressed.
[20:51:49][D][miot:125]: Queuing MCU command 'action 4 1 100'
[20:51:49][V][miot:091]: Received MCU message 'get_down'
[20:51:49][V][miot:171]: Sending reply 'down action 4 1 100' to MCU
[20:51:49][V][miot:091]: Received MCU message 'result -4006'
[20:51:49][V][miot:171]: Sending reply 'ok' to MCU
[20:51:49][V][miot:091]: Received MCU message 'net'
[20:51:49][V][miot:171]: Sending reply 'cloud' to MCU
The 3
is supposed to be the PIID, see https://github.com/blakadder/miot?tab=readme-ov-file#action
And PIID 3 here is filter-used-time, so to me the yaml looks in sync with the specs.
But maybe the specs are wrong. Maybe an additional value is missing, what to set the used time to. Wild guess, but does maybe miot_action_args: "3 0"
work?
Bingo
[20:59:23][D][button:010]: 'Reset Filter Life' Pressed.
[20:59:23][D][miot:125]: Queuing MCU command 'action 4 1 3 0'
[20:59:23][V][miot:091]: Received MCU message 'get_down'
[20:59:23][V][miot:171]: Sending reply 'down action 4 1 3 0' to MCU
[20:59:23][V][miot:091]: Received MCU message 'result 4 1 0'
[20:59:23][V][miot:171]: Sending reply 'ok' to MCU
[20:59:23][V][miot:091]: Received MCU message 'properties_changed 4 1 100 4 3 0'
[20:59:23][V][miot.sensor:011]: MCU reported sensor 4:1 is: 100.000000
[20:59:23][V][sensor:043]: 'Filter Life Level': Received new state 100.000000
[20:59:23][D][sensor:094]: 'Filter Life Level': Sending state 100.00000 % with 0 decimals of accuracy
[20:59:23][V][miot.sensor:011]: MCU reported sensor 4:3 is: 0.000000
[20:59:23][V][sensor:043]: 'Filter Used Time': Received new state 0.000000
[20:59:23][D][sensor:094]: 'Filter Used Time': Sending state 0.00000 h with 0 decimals of accuracy
Woot, nice! Once you have a nice and complete yaml, please open a PR to add it. Or, alternatively, attach it here and I'll add it
After switching back to main issue with number precision is back.
I have run esphome clean ....yaml
just to make sure.
[21:11:47][D][number:054]: 'Display Brightness' - Setting number value
[21:11:47][D][number:113]: New number value: 3.000000
[21:11:47][V][miot.number:017]: Setting number 7:2 3.000000
[21:11:47][D][miot:125]: Queuing MCU command 'set_properties 7 2 3.000000'
[21:11:47][D][number:012]: 'Display Brightness': Sending state 3.000000
[21:11:47][V][miot:091]: Received MCU message 'get_down'
[21:11:47][V][miot:171]: Sending reply 'down set_properties 7 2 3.000000' to MCU
[21:11:47][V][miot:091]: Received MCU message 'result 7 2 -4003'
[21:11:47][E][miot:218]: Result error on property 7:2: -4003
It's most likely the latest because this was couple of lines before:
[21:11:46][V][miot.select:011]: MCU reported select 2:4 is: 2
[21:11:46][D][select:015]: 'Mode': Sending state Favorite (index 2)
[21:11:46][V][miot.number:011]: MCU reported number 9:3 is: 1000.000000
[21:11:46][D][number:012]: 'Favorite Speed': Sending state 1000.000000
[21:11:46][V][miot.sensor:011]: MCU reported sensor 3:4 is: 1.000000
[21:11:46][V][sensor:043]: 'PM2.5 Density': Received new state 1.000000
[21:11:46][D][sensor:094]: 'PM2.5 Density': Sending state 1.00000 µg/m³ with 0 decimals of accuracy
[21:11:46][V][miot.sensor:011]: MCU reported sensor 4:1 is: 100.000000
[21:11:46][V][sensor:043]: 'Filter Life Level': Received new state 100.000000
[21:11:46][D][sensor:094]: 'Filter Life Level': Sending state 100.00000 % with 0 decimals of accuracy
[21:11:46][V][miot.sensor:011]: MCU reported sensor 4:3 is: 0.000000
[21:11:46][V][sensor:043]: 'Filter Used Time': Received new state 0.000000
[21:11:46][D][sensor:094]: 'Filter Used Time': Sending state 0.00000 h with 0 decimals of accuracy
[21:11:46][V][miot.switch:012]: MCU reported switch 8:1 is: OFF
[21:11:46][V][miot.switch:012]: MCU reported switch 6:1 is: OFF
[21:11:46][W][miot:183]: Received property value without component: 7 1 true
[21:11:46][V][miot.number:011]: MCU reported number 7:2 is: 7.000000
[21:11:46][D][number:012]: 'Display Brightness': Sending state 7.000000
[21:11:46][V][miot:171]: Sending reply 'ok' to MCU
[21:11:46][W][component:214]: Component miot took a long time for an operation (0.13 s).
[21:11:46][W][component:215]: Components should block for at most 20-30ms.
I guess that's due to esphome's caching. Try setting refresh: https://esphome.io/components/external_components.html#external-components-refresh
Sorry for barging in on this issue, but I need to say a massive THANK YOU for this insight:
But maybe the specs are wrong. Maybe an additional value is missing, what to set the used time to. Wild guess, but does maybe miot_action_args: "3 0" work?
The specs aren't clear, but the action arguments have to be named (well... numbered) and you can send the arguments in whicever order.
For a more illustrative example, here I have an action for a Pet Feeder, which takes a bunch of parameters:
SIID 5 feedplanserve
Action 7 feedlistadd
10 - feedplan-id
6 - feedplan-hour
7 - feedplan-min
8 - feedplan-unit
Only calling the action in this format works:
down action 5 7 10 [id_value] 6 [hour_value] 7 [minute_value] 8 [servings_value]
down action 5 7 8 [servings_value] 10 [id_value] 7 [minute_value] 6 [hour_value]
down action 5 7 [ other permutations of the above ]
Directly calling the action with just the argument values results either in an error or gibberish data, depending on the firmware validation, even if we keep the order from the spec;
down action 5 7 [id_value] [hour_value] [minute_value] [servings_value]
# Fails or results in gibberish data
[12:21:48][V][miot:171]: Sending reply 'down action 5 7 10 0 6 11 7 5 8 1' to MCU
[12:21:48][V][miot:091]: Received MCU message 'result 5 7 0'
[12:21:54][V][miot:171]: Sending reply 'down action 5 6' to MCU
[12:21:54][V][miot:091]: Received MCU message 'result 5 6 0 12 "0,11,5,1,255,1,255,255,255,255,2,255,255,255,255,3,255,255,255,255,4,255,255,255,255"'
# ID 0, Hour 11, Minute 05, Servings 1
# Swapped arg 6 [hour] and 7 [minute] order
[12:22:12][V][miot:171]: Sending reply 'down action 5 7 10 1 7 05 6 12 8 1' to MCU
[12:22:12][V][miot:091]: Received MCU message 'result 5 7 0'
[12:22:14][V][miot:171]: Sending reply 'down action 5 6' to MCU
[12:22:14][V][miot:091]: Received MCU message 'result 5 6 0 12 "0,11,5,1,255,1,12,5,1,255,2,255,255,255,255,3,255,255,255,255,4,255,255,255,255"'
# ID 0, Hour 11, Minute 05, Servings 1
# ID 1, Hour 12, Minute 05, Servings 1 -- still correct
Some actions work without args on some devices. For example, down action 4 1
on my zhimi.airp.mb5
still resets the time same as down action 4 1 3 0
, but I guess it's better to always be explicit in argument passing.
So yeah... thanks!
@gfduszynski I commited some changes to unify all 3 devices, let me know if I messed up ;)
@dhewg Looks good to me :)
There is still a mystery with [20:23:21][W][miot:183]: Received property value without component: 7 1 true
I don't know if this is useful or not.
SIID 7 is Screen
, and it's a bool. Turn display on/off maybe?
Try this: Go to HA's Developer tools
, then Services
, select <your device name>_mcu_command
, at command
enter set_properties 7 1 false
and then watch the device while hitting Call service
False turns off the screen, while True does not appear to do anything.
[20:54:57][D][miot:125]: Queuing MCU command 'set_properties 7 1 true'
[20:54:57][W][miot:183]: Received property value without component: 7 1 true
[20:55:00][D][miot:125]: Queuing MCU command 'set_properties 7 1 false'
[20:55:00][W][miot:183]: Received property value without component: 7 1 true
Weird, '1' maybe? Or it's just to turn it off and the other brightness is able to light it up again? But that'll be weird too...
Maybe it's just some left over debug thing, it's not part of the spec anyway...
Tried 1, but to no avail. After turning it off adjusting brightness restores the screen. I think you are right and It's not worth the effort.
I've enabled the wiki here, have you taken some pics to put some basic instructions there?
Unfortunately no, however what I can say is I did it probably in the worst possible way as evident by the need to replace the ESP32 :smiling_face_with_tear:
I tried to do everything in place as one of the screws for PCB is covered by a piece of plastic. Once I was sure I killed the esp (because I was lazy and didn't want disassemble the whole thing) I chosen violence and bent the whole case to gain access to the second screw. Actually worked and I didn't destroy it.
Pins are in different order than on other air purifiers tx/rx are in the middle surrounded by gnd and vcc. I'm not giving exact order because I don't want to mislead anybody. They have nice labels on the underside luckily.
Good tip in case your uart adapter cannot handle the required current is to use built in power from the device. There is a ribbon cable providing 24V to the board.
Be very careful with the PCB whenever doing anything as solder mask appears to be very fragile.
Wow, okay, but nice that you were able to get it working again!
Blind attempt to add support for Mi Air Purifier 3C (zhimi.airp.mb4a): zhimi.airp.mb4a.yaml.txt
I can't tell if this works, but please try and report back (with logs if possible): cc @daniel-dona @gfduszynski