dhewg / esphome-miot

ESPHome components for MIoT devices
Other
16 stars 8 forks source link

Add example `mmgg.feeder.fi1` config #17

Open cristianchelu opened 3 months ago

cristianchelu commented 3 months ago

This PR adds almost complete support for the Xiaomi Pet Feeder. Even though it's not 100%, I think it's still good enough to include as an example, and what's missing can be considered "polish".

I based it off #16 for the Last Feed Portions and Last Feed Source sensors.

Quirks

This is an ESP8266 device, so I had to disable serial logging on UART1 for stable serial comms with the MCU. This is commented in the config.

I also think I managed to overflow an output buffer on the MCU with a really long get_properties command, but I can't say for certain if I caused it or it's been that way from the factory, I get garbage strings 122 0 12 0 get_down at the end of my results. Would something like a limit on how many props we request in one message help? (even if the specs say all MCUs should handle 512+ bytes)

What's missing

Mi IoT Spec implementation

I think this section rather belongs in the wiki and not in this PR, but I wrote it already, so if you're curious, here's a breakdown by service (deep breath):

Observation: Parameters that are listed as input or output of actions are not usually usable by themselves. They only appear in the result message of an action or used in the action message.

Device Info (SIID: 1)

Nothing is sent on 1:1 ~ 1:5 on power cycle.

Feeder (SIID: 2)

Properties

1 - Device Fault. Works as expected 5 - Feeding measure. Can be read, but garbage. Used as input for the pet-food-out action. 6 - Pet Food Level Left - Works as expected

Actions

1 - Pet Food Out. Works as expected. Dispenses the specified portions immediately. Optional feeding-measure parameter; if left out, dispenses one portion.

Indicator Light (SIID: 3)

Everything works as expected

Feed Service (SIID: 4)

Properties

4 - outfood-num. Number of dispensed portions in last event. Specs say this is read|notify, but really it's only notify. The feed started|status|successful events use this to communicate what happened 5 - outfood-id. Index of scheduled feed that dispensed outfood-num portions in last event, or 255 if a manual feed. Specs say this is read|notify, but really it's only notify. The feed started|status|successful events use this to communicate what happened 8 - outletstatus. There is a motorized door protecting the dispensing outlet, "for freshness". Can be read. Is notified by properties_changed, but only after it's closed; there's no notification when it's opened, not even in the "Feeding Started" event. 9 - doorstatus. Top Lid of the device. Works as expected, thankfully.

Feeding Schedule (SIID: 5)

Properties

5 - feedplan-contr. Enable or disable the automatic feeding schedule. Works as expected. 9 - feedplan-stat. Unknown? Marked as write-only.

6 - feedplan-hour, 7 - feedplan-min, 8 - feedplan-unit, 10 - feedplan-id, 11 - getfeedplan-num, 12 - feddplan-string produce garbage if read by themselves. They're used as inputs/outputs for actions.

Actions

5 - stopfeed. Unknown, didn't try. Marks feedplan-contr as input, but the control is switchable by itself, making this action redundant. 6 - getfeedplan. Usage action 5 6 11 0 or action 5 6 11 1, and returns the first 5 or last 5 schedules in the feddplan-string property as output. Example:

// Get page 0 of schedule. (schedules 0-4)
[15:04:28][V][miot:189]: Sending reply 'down action 5 6 11 0' to MCU
[15:04:28][V][miot:095]: Received MCU message 'result 5 6 0 12 "0,6,0,5,0,1,10,0,5,0,2,255,255,255,255,3,255,255,255,255,4,255,255,255,255"'
[15:04:28][V][miot.text_sensor:011]: MCU reported text sensor 5:12 is: 0,6,0,5,0,1,10,0,5,0,2,255,255,255,255,3,255,255,255,255,4,255,255,255,255
[15:04:28][V][text_sensor:013]: 'Raw Feed Plan': Received new state 0,6,0,5,0,1,10,0,5,0,2,255,255,255,255,3,255,255,255,255,4,255,255,255,255
[15:04:28][D][text_sensor:064]: 'Raw Feed Plan': Sending state '0,6,0,5,0,1,10,0,5,0,2,255,255,255,255,3,255,255,255,255,4,255,255,255,255'

// Get page 1 of schedule. (schedules 5-9)
[15:05:06][V][miot:189]: Sending reply 'down action 5 6 11 1' to MCU
[15:05:06][V][miot:095]: Received MCU message 'result 5 6 0 12 "5,255,255,255,255,6,255,255,255,255,7,255,255,255,255,8,255,255,255,255,9,255,255,255,255"'
[15:05:06][V][miot.text_sensor:011]: MCU reported text sensor 5:12 is: 5,255,255,255,255,6,255,255,255,255,7,255,255,255,255,8,255,255,255,255,9,255,255,255,255
[15:05:06][V][text_sensor:013]: 'Raw Feed Plan': Received new state 5,255,255,255,255,6,255,255,255,255,7,255,255,255,255,8,255,255,255,255,9,255,255,255,255
[15:05:06][D][text_sensor:064]: 'Raw Feed Plan': Sending state '5,255,255,255,255,6,255,255,255,255,7,255,255,255,255,8,255,255,255,255,9,255,255,255,255'

This means that in order to get all schedules exposed we need a different sensor to combine the two results.

5 - feedlistadd, 6 - feedlistedit, 7 - feedlistdel are implemented as home assistant service calls add_scheduled_feed, edit_scheduled_feed and remove_scheduled_feed respectively. All work as intended.

Child Lock (SIID: 6)

Everything works as expected.

Cleaning Reminder (SIID: 8)

Everything works as expected.

Device Control (SIID:9)

Properties

11 - factory-result. Did not test. Specs say read|notify but I expect is only an output for the prtest action 12 - phon-time-zone. Unknown if this is useful. read|write|notify works. 13 - countrycode. Unknown if this is useful. read|write|notify works.

Actions

Did not test. Properties 12, 13 are read|write anyway and I didn't want to do a "factory test" on my device.

Replace Dessicant Reminder (SIID: 11)

Everything works as expected.

Device Screenshots

Controls Sensors
mmgg feeder fi1 controls Screenshot from 2024-02-08 22-29-16
Configuration Diagnostics
mmgg feeder fi1 config mmgg feeder fi1 diagnostic
dhewg commented 2 months ago

Sorry for the delay, I'm a bit swamped right now. I'll try to look at this soon ;)

cristianchelu commented 2 months ago

Sorry for the delay, I'm a bit swamped right now. I'll try to look at this soon ;)

Don't worry about it, we're not on a deadline :)

I hope you don't mind me editing this and the event_occurred PR with new functionality in the meantime, I ironed out some more kinks.

I'll keep this as a draft a bit more as I add the final missing pieces for 100% feature parity.