Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhanced support for Petkit devices #4

Open
Jezza34000 opened this issue Dec 24, 2024 · 3 comments
Open

Enhanced support for Petkit devices #4

Jezza34000 opened this issue Dec 24, 2024 · 3 comments

Comments

@Jezza34000
Copy link
Contributor

Hi Cristian,
First of all, thank you for this beautiful card.
I've wanted something like this for our feeders for a long time. You did it !
I had a request regarding my Petkit integration, many users asked me for schedule management support.
However, there are specificities to our Petkit distributors that are not found in others.
We have a "To be dispensed" option to activate or deactivate certain portions and this only affects the current day (this does not modify the general feeding plan)

dispense

Do you think that in addition to the add, remove, edit actions, we could add something like: enable, disable?

@Jezza34000
Copy link
Contributor Author

on the other hand thoses feeders had an another specificity : some feeders have 2 hoppers, in fact we have : "amount1" and "amount2" for the add, edit options, do you think this specificity can be added or that make a too big change ?

@cristianchelu
Copy link
Owner

Hey,

Thank you! I'm very glad the card is useful!

Yes, I can definitely add support for both features, however if you agree, I would like a bit of discussion first to decide on the best approach from the technical and UX perspectives, so I have a few questions:

(warning: wall of text, sorry! 😄 )

General questions

  • Do the PetKit feeders have a max schedule entry count?
    Home Assistant text sensors are limited to 255 characters (but action/service responses, as well as sensor attributes are not). For how the original xiaomi format was structured, a text entry of 1,255,255,255,255,[1] 18 characters means we can comfortably fit its max 10 entries in this limit.
  • Do we know how the native petkit app structures its query/command messages? We might be able to take some inspiration from there, to not extend or create another hacky unreadable ^1 format.
  • Do you already have a vision of how you would implement these? We could use it as a starting point for discussions.

I would also need to think about how & where to place this new information. The space is already a bit limited, and I don't want to have too much information

Enable / Disable feeding entry

this only affects the current day (this does not modify the general feeding plan)

Does this mean that
a) Each feeding plan entry has an enabled/disabled switch and every new day the feeder resets the switch to ON? or
b) There are 2 separate schedules; one general daily plan and a separate, temporary today-only that gets cleared?
c) Something else?

If a) I have just yesterday added a disabled status for entry rows when the entire schedule switch is turned off, and adding another action button in the dropdown menu is an easy thing to add. We would just need to decide how to encode this in the sensor for each entry.

If b) we can also just instruct the users to have two separate cards, one for the general plan, another for today-only?

Dual/Multi source schedule

If I understood correctly, the device can simultaneously dispense from both hoppers for one entry; so Entry 1: @10:30 dispense 10 from hopper 1 and 5 from hopper 2, instead of Entry 1: @10:30 dispense 10 from hopper 1; Entry 2: @10:30 dispense 5 from hopper 2?

I see no problem in the add/edit screen as we have the space for more inputs, and no problem for the actions as we are not limited in the data.

But for the state sensor it gets complicated with the device-specific states...

First Ideas

Continue with encoded text sensor

We could continue using a single sensor as an array of numbers,
like [int hour],[int minute],[int amount1],[int amount2],[int status].
12,30,200,100,255, would fit 14 entries in 255 chars. We can extend this with
more sensors if we need more space.

Pros:

  • Easiest to implement now
  • Compatible with ESPHome feeders, which does not support attributes and action responses. (Not relevant to your integration, but only to this card.)

Cons:

  • Unreadable sensor by users, is a hacky approach.
  • User will have to select the proper format for each card/device
    (This can get easier when I implement Config UI, it can be a dropdown)
  • Less maintainable. The state mapping (255 = pending, etc) and device
    capability configuration lives in the card so any updates to the states
    must be done in 2 repos.

Pro/Con:

  • State change history is stored in the recorder DB.
    Bigger DB with time but yay historical data?

I can at least make the 'parseStateString' regex and number-state map
configurable in the yaml.

type: custom:dispenser-schedule-card
device_type: 'petkit-yumshare-dual-hopper'

or custom

type: custom:dispenser-schedule-card
custom_device:
  state_string_regex: /(?<hour>[0-9]{2}),(?<minute>[0-9]{2}),(?<status>[0-9]{3})/
  status_map:
    - "255 -> Pending"
    - "100 -> SurplusControl"
    - etc

Full state in action response

We could implement this the same way as weather.get_forecasts which seems to
be the way forward in HA?

We could have a simple sensor that has the count and the last_changed attribute.
When the attribute changes, the card can get the full state
(unlimited length and structure) from an action (service) provided by the integration.

{
  "device": {
    "disable-individual-entry": true,
    "disable-entire-plan": false,
    "hopper-count": 2,
    "weight-scale": true,
    "max-entries": 20,
    "weekly-plan": false
  },
  "schedule": [
    {
      "disabled": false,
      "time": "10:20",
      "amount": [10, 5],
      "dispensed": [10.2, 5.5],
      "status": "Distribuée",
      "icon": "mdi:check" 
      // or one of the predefined card statuses
      // to include status colors:
      // "display-state": "success"
    },
    {
      "disabled": true,
      "time": "10:20",
      "amount": [10, 5],
      "status": "SurplusControl™",
      "icon": "mdi:clock-remove-outline"
      // or one of the predefined card statuses
      // to include status colors:
      // "display-state": "disabled"
    }
  ]
}

Pros:

  • Most flexible. The integration can supply the actual device capabilities
    (number of hoppers, disable of individual entries, actual dispensed weight from integrated scale, etc.) as well as the translated status string.
  • More maintainable, new devices & new features live only in the integration,
    card is a dumb frontend only.
    Device specific translations and custom logic lives in integration.

Cons:

  • Harder initial implementation, more code to write.
  • More delay for updates, we need one more network round-trip for each render
    on state updates.
  • Devices flashed with ESPHome can't use this.

Pro/Con:

  • State change history is not stored in DB.
    Lighter DB but no historical data by default.

State in attributes

Same as the action response approach, but using text sensor attributes.
Seems not to be the preferred approach anymore?

Pros:

  • Same as action response, plus
  • Does not require network round-trip.

Pro/Con:

  • Attribute change history is stored in DB.

Again, sorry for the many words, but I'm curious to hear your thoughts.

Thanks!

@Jezza34000
Copy link
Contributor Author

Do the PetKit feeders have a max schedule entry count?

I don't think so, in my case i have 10 feed entry by day. But i already reached the limit with 255 chars in HA.

Do we know how the native petkit app structures its query/command messages? We might be able to take some inspiration from there, to not extend or create another hacky unreadable ^1 format.

Native petkit feeding plan returned from API :

This for the feeding plan :
"feedDailyList": [ { "items": [ { "amount1": 0, "amount2": 1, "id": "18000", "name": "R1", "time": 18000 }, { "amount1": 1, "amount2": 0, "id": "25200", "name": "R3", "time": 25200 }, { "amount1": 0, "amount2": 1, "id": "28800", "name": "R3-4", "time": 28800 },
Time is in second from 00:00

And this for the "result" :
{ "aesKey": "xxxxxxxxxxxxxxxxxxx\n", "amount1": 0, "amount2": 1, "completedAt": 1735236010, "duration": 4, "eatVideo": 1, "eventId": "300004409_1735236001", "expire": 1735858799, "id": "s68400", "isExecuted": 1, "isNeedUploadVideo": 1, "mark": 1735236006, "mediaApi": "xxxxxxxxxx", "name": "R8", "preview": "http://xxxxxxxxxxx", "src": 1, "startTime": 1735236001, "state": { "completedAt": "2024-12-26T18:00:10.000+0000", "errCode": 0, "media": 1, "realAmount1": 0, "realAmount2": 1, "result": 0, "surplusStandard": 1 }, "status": 0, "storageSpace": 239904, "time": 68400 },
Th result is a bit more complicated beacause of "video" and pet tracking stuff, but important stuff are :
-Status 0/1 => Cancelled or Not
-Src => Where the distribution is initiated from ?
-Planned amount 0,1,2 and RealAmount 0,1,2
-ErrCode and Result => Information about dispense process (this feeder has an IA who analyse bowl and stop dispense if there is too much food on it)

Do you already have a vision of how you would implement these? We could use it as a starting point for discussions.

By writing this information I realize that integrating the specificities of this distributor will be complicated...

a) Each feeding plan entry has an enabled/disabled switch and every new day the feeder resets the switch to ON?

Yes

If I understood correctly, the device can simultaneously dispense from both hoppers for one entry;

No there is 2 entry, one for each hopper

First Ideas
Continue with encoded text sensor

I think this could be kept like that, there is too much information

Full state in action response

Look to be the better solution

Tell me what you think of this information? and I suggest that we continue on Discord, it will be simpler for our exchanges :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants