@@ -90,45 +90,57 @@ def extra_state_attributes(self):
9090 """Return entity specific state attributes."""
9191 match self .key :
9292 case "feeding_plan_state" :
93- # Today's feeding plan events with formatted amounts
93+ # Today's feeding plan events with amounts in all units
9494 today_data = getattr (self .device , "feeding_plan_today_data" , {})
9595 plans = today_data .get ("plans" , []) if isinstance (today_data , dict ) else []
9696 if not plans :
9797 return {}
9898 plan_data = getattr (self .device , "feeding_plan_data" , {})
9999 conv = getattr (self .device , "feed_conv_factor" , 1 )
100- unit = self .member .feedUnitType
101- weight = unit if unit in (Unit .GRAMS , Unit .OUNCES ) else Unit .GRAMS
102- volume = unit if unit in (Unit .MILLILITERS , Unit .CUPS ) else Unit .MILLILITERS
103100 return {
104101 plan_data .get (str (plan ["planId" ]), {}).get ("label" ) or f"plan_{ plan .get ('index' , plan ['planId' ])} " : {
102+ "planID" : plan .get ("planId" ),
105103 "time" : plan .get ("time" ),
106- "amount (weight)" : f"{ Unit .convert_feed (plan .get ('grainNum' , 0 ) * conv , None , weight , True )} { weight .symbol } " ,
107- "amount (volume)" : f"{ Unit .convert_feed (plan .get ('grainNum' , 0 ) * conv , None , volume , True )} { volume .symbol } " ,
108- "state" : {1 : "Pending" , 2 : "Skipped" , 3 : "Completed" , 4 : "Skipped, Time Passed" }.get (plan .get ("state" ), "Unknown" ),
104+ ** {
105+ f"amount_{ unit .symbol .lower ()} " : Unit .convert_feed (plan .get ("grainNum" , 0 ) * conv , None , unit , True )
106+ for unit in VALID_UNIT_TYPES [API .FEED_UNIT ] if unit
107+ },
108+ "amount_raw" : plan .get ("grainNum" , 0 ),
109+ "feed_conv_factor" : conv ,
110+ "enabled" : plan_data .get (str (plan ["planId" ]), {}).get ("enable" , False ),
111+ "repeat_days" : plan_data .get (str (plan ["planId" ]), {}).get ("repeatDay" , "[]" ),
112+ "sound" : plan_data .get (str (plan ["planId" ]), {}).get ("enableAudio" , False ),
113+ "feed_state" : {1 : "Pending" , 2 : "Skipped" , 3 : "Completed" , 4 : "Skipped, Time Passed" }.get (plan .get ("state" ), "Unknown" ),
109114 "repeat" : plan .get ("repeat" ),
110- "planID" : plan .get ("planId" ),
111115 }
112116 for plan in plans
113117 } or {}
114118 case "feeding_schedule" :
115- # Full recurring schedule with formatted amounts
119+ # Full recurring schedule with amounts in all units + today's state
116120 plans = getattr (self .device , "feeding_plan_data" , {})
117121 if not plans :
118122 return {}
119123 conv = getattr (self .device , "feed_conv_factor" , 1 )
120- unit = self .member .feedUnitType
121- weight = unit if unit in (Unit .GRAMS , Unit .OUNCES ) else Unit .GRAMS
122- volume = unit if unit in (Unit .MILLILITERS , Unit .CUPS ) else Unit .MILLILITERS
124+ # Build lookup of today's feed states by planId
125+ today_data = getattr (self .device , "feeding_plan_today_data" , {})
126+ today_plans = today_data .get ("plans" , []) if isinstance (today_data , dict ) else []
127+ today_state_map = {p ["planId" ]: p .get ("state" ) for p in today_plans }
123128 return {
124129 plan .get ("label" ) or f"plan_{ plan_id } " : {
125130 "planID" : int (plan_id ),
126131 "time" : plan .get ("executionTime" ),
127- "amount (weight)" : f"{ Unit .convert_feed (plan .get ('grainNum' , 0 ) * conv , None , weight , True )} { weight .symbol } " ,
128- "amount (volume)" : f"{ Unit .convert_feed (plan .get ('grainNum' , 0 ) * conv , None , volume , True )} { volume .symbol } " ,
132+ ** {
133+ f"amount_{ unit .symbol .lower ()} " : Unit .convert_feed (plan .get ("grainNum" , 0 ) * conv , None , unit , True )
134+ for unit in VALID_UNIT_TYPES [API .FEED_UNIT ] if unit
135+ },
136+ "amount_raw" : plan .get ("grainNum" , 0 ),
137+ "feed_conv_factor" : conv ,
129138 "enabled" : plan .get ("enable" , False ),
130139 "repeat_days" : plan .get ("repeatDay" , "[]" ),
131140 "sound" : plan .get ("enableAudio" , False ),
141+ "feed_state" : {1 : "Pending" , 2 : "Skipped" , 3 : "Completed" , 4 : "Skipped, Time Passed" }.get (
142+ today_state_map .get (int (plan_id )), "Not Scheduled Today"
143+ ),
132144 }
133145 for plan_id , plan in plans .items ()
134146 } or {}
@@ -189,13 +201,15 @@ def extra_state_attributes(self):
189201 key = "feeding_plan_state" ,
190202 translation_key = "feeding_plan_state" ,
191203 icon = "mdi:calendar-check" ,
204+ device_class = BinarySensorDeviceClass .RUNNING ,
192205 should_report = lambda device : device .feeding_plan_state is not None ,
193- name = "Today's Feeding Schedule "
206+ name = "Feeding Plan "
194207 ),
195208 PetLibroBinarySensorEntityDescription [AirSmartFeeder ](
196209 key = "feeding_schedule" ,
197210 translation_key = "feeding_schedule" ,
198211 icon = "mdi:calendar-clock" ,
212+ device_class = BinarySensorDeviceClass .RUNNING ,
199213 should_report = lambda device : bool (getattr (device , "feeding_plan_data" , {})),
200214 value_fn = lambda device : device .feeding_plan_state ,
201215 name = "Feeding Schedule"
@@ -252,13 +266,15 @@ def extra_state_attributes(self):
252266 key = "feeding_plan_state" ,
253267 translation_key = "feeding_plan_state" ,
254268 icon = "mdi:calendar-check" ,
269+ device_class = BinarySensorDeviceClass .RUNNING ,
255270 should_report = lambda device : device .feeding_plan_state is not None ,
256- name = "Today's Feeding Schedule "
271+ name = "Feeding Plan "
257272 ),
258273 PetLibroBinarySensorEntityDescription [GranarySmartFeeder ](
259274 key = "feeding_schedule" ,
260275 translation_key = "feeding_schedule" ,
261276 icon = "mdi:calendar-clock" ,
277+ device_class = BinarySensorDeviceClass .RUNNING ,
262278 should_report = lambda device : bool (getattr (device , "feeding_plan_data" , {})),
263279 value_fn = lambda device : device .feeding_plan_state ,
264280 name = "Feeding Schedule"
@@ -315,13 +331,15 @@ def extra_state_attributes(self):
315331 key = "feeding_plan_state" ,
316332 translation_key = "feeding_plan_state" ,
317333 icon = "mdi:calendar-check" ,
334+ device_class = BinarySensorDeviceClass .RUNNING ,
318335 should_report = lambda device : device .feeding_plan_state is not None ,
319- name = "Today's Feeding Schedule "
336+ name = "Feeding Plan "
320337 ),
321338 PetLibroBinarySensorEntityDescription [GranarySmartCameraFeeder ](
322339 key = "feeding_schedule" ,
323340 translation_key = "feeding_schedule" ,
324341 icon = "mdi:calendar-clock" ,
342+ device_class = BinarySensorDeviceClass .RUNNING ,
325343 should_report = lambda device : bool (getattr (device , "feeding_plan_data" , {})),
326344 value_fn = lambda device : device .feeding_plan_state ,
327345 name = "Feeding Schedule"
@@ -409,13 +427,15 @@ def extra_state_attributes(self):
409427 key = "feeding_plan_state" ,
410428 translation_key = "feeding_plan_state" ,
411429 icon = "mdi:calendar-check" ,
430+ device_class = BinarySensorDeviceClass .RUNNING ,
412431 should_report = lambda device : device .feeding_plan_state is not None ,
413- name = "Today's Feeding Schedule "
432+ name = "Feeding Plan "
414433 ),
415434 PetLibroBinarySensorEntityDescription [OneRFIDSmartFeeder ](
416435 key = "feeding_schedule" ,
417436 translation_key = "feeding_schedule" ,
418437 icon = "mdi:calendar-clock" ,
438+ device_class = BinarySensorDeviceClass .RUNNING ,
419439 should_report = lambda device : bool (getattr (device , "feeding_plan_data" , {})),
420440 value_fn = lambda device : device .feeding_plan_state ,
421441 name = "Feeding Schedule"
@@ -472,6 +492,7 @@ def extra_state_attributes(self):
472492 key = "feeding_plan_state" ,
473493 translation_key = "feeding_plan_state" ,
474494 icon = "mdi:calendar-check" ,
495+ device_class = BinarySensorDeviceClass .RUNNING ,
475496 should_report = lambda device : device .feeding_plan_state is not None ,
476497 name = "Feeding Plan"
477498 ),
@@ -550,13 +571,15 @@ def extra_state_attributes(self):
550571 key = "feeding_plan_state" ,
551572 translation_key = "feeding_plan_state" ,
552573 icon = "mdi:calendar-check" ,
574+ device_class = BinarySensorDeviceClass .RUNNING ,
553575 should_report = lambda device : device .feeding_plan_state is not None ,
554- name = "Today's Feeding Schedule "
576+ name = "Feeding Plan "
555577 ),
556578 PetLibroBinarySensorEntityDescription [SpaceSmartFeeder ](
557579 key = "feeding_schedule" ,
558580 translation_key = "feeding_schedule" ,
559581 icon = "mdi:calendar-clock" ,
582+ device_class = BinarySensorDeviceClass .RUNNING ,
560583 should_report = lambda device : bool (getattr (device , "feeding_plan_data" , {})),
561584 value_fn = lambda device : device .feeding_plan_state ,
562585 name = "Feeding Schedule"
0 commit comments