Skip to content

Commit

Permalink
🐱 add miio2miot for mmgg.feeder.petfeeder (#220 #352)
Browse files Browse the repository at this point in the history
  • Loading branch information
al-one committed May 20, 2022
1 parent 9cb43dc commit a814da3
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 72 deletions.
8 changes: 8 additions & 0 deletions custom_components/xiaomi_miot/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,10 @@ def get_customize_options(hass, options={}, bool2selects=[], entity_id='', model
entity_class = attrs.get('entity_class')

if domain == 'sensor':
if entity_class in ['MiotSensorEntity']:
options.update({
'state_property': cv.string,
})
options.update({
'value_ratio': float,
'state_class': cv.string,
Expand All @@ -662,6 +666,10 @@ def get_customize_options(hass, options={}, bool2selects=[], entity_id='', model
options.update({
'stat_power_cost_key': cv.string,
})
if entity_class in ['MiotSwitchActionSubEntity']:
options.update({
'feeding_measure': cv.positive_int,
})

if domain == 'light' or re.search(r'light', model, re.I):
bool2selects.extend(['color_temp_reverse'])
Expand Down
16 changes: 4 additions & 12 deletions custom_components/xiaomi_miot/core/device_customizes.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,18 +339,10 @@
'cloud_delay_update': 10,
},
'mmgg.feeder.petfeeder': {
'sensor_attributes': 'feed_today',
'miio_commands': {
'getprops': [
'food_status', 'feed_plan', 'door_result', 'feed_today', 'clean_days', 'outlet_status',
'dryer_days', 'weight_level', 'wifi_led', 'key_lock', 'country_code',
],
# 'getfeedplan1': [],
# 'getfeedplan2': [],
},
'miot_local_mapping': {
'feeding.measure': {'siid': 2, 'piid': 1},
},
'state_property': 'pet_food_left_level',
'button_actions': 'reset_desiccant_life',
'sensor_properties': 'feed_today,desiccant_left_time,cleantime',
'switch_properties': 'feedstatus',
},
'miaomiaoce.sensor_ht.t1': {
'miot_mapping': {
Expand Down
26 changes: 26 additions & 0 deletions custom_components/xiaomi_miot/core/miio2miot_specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,32 @@ def cbk(prop, params, props, **kwargs):
'chunk_properties': 1,
},

'mmgg.feeder.petfeeder': {
'without_props': True,
'miio_commands': [
{
'method': 'getprops',
'values': [
'food_status', 'feed_status', 'door_status', 'feed_today', 'clean_days', 'outlet_status',
'dryer_days', 'weight_level', 'wifi_led', 'key_lock', 'country_code',
],
},
],
'miio_specs': {
'prop.2.101': {'prop': 'food_status'},
'prop.2.102': {'prop': 'feed_status', 'setter': 'stopfeed', 'set_template': '{{ [value|int] }}'},
'prop.2.103': {'prop': 'feed_today'},
'prop.2.104': {'prop': 'dryer_days'},
'prop.2.105': {'prop': 'clean_days'},
'prop.2.106': {'prop': 'door_status'},
'prop.2.107': {'prop': 'outlet_status'},
'action.2.1': {'setter': 'outfood'},
'action.2.101': {'setter': 'resetdryer'},
'prop.200.201': {'prop': 'wifi_led', 'setter': 'wifiledon', 'set_template': '{{ [value|int] }}'},
'prop.300.301': {'prop': 'key_lock', 'setter': 'keylock', 'set_template': '{{ [value|int] }}'},
}
},

'opple.light.bydceiling': {
'without_props': True,
'miio_commands': [
Expand Down
201 changes: 150 additions & 51 deletions custom_components/xiaomi_miot/core/miot_specs_extend.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,57 +73,6 @@
}
],

"dreame.vacuum.mc1808": [
{
"iid": 18,
"properties": [
{
"iid": 9,
"access": ["read", "notify"]
}
]
}
],

"leshow.humidifier.jsq1": [
{
"iid": 8,
"properties": [
{
"iid": 5,
"access": ["read"]
},
{
"iid": 6,
"access": ["read", "write"]
},
{
"iid": 7,
"access": ["read"]
}
]
}
],

"lumi.airer.acn01": [
{
"iid": 2,
"properties": [
{
"iid": 101,
"type": "urn:miot-spec-v2:property:dry_mode",
"format": "uint8",
"access": ["read", "write"],
"value-list": [
{"value": 0, "description": "off"},
{"value": 1, "description": "dry"},
{"value": 2, "description": "winddry"}
]
}
]
}
],

"deerma.humidifier.jsq": [
{
"iid": 2,
Expand Down Expand Up @@ -210,6 +159,156 @@
}
],

"dreame.vacuum.mc1808": [
{
"iid": 18,
"properties": [
{
"iid": 9,
"access": ["read", "notify"]
}
]
}
],

"leshow.humidifier.jsq1": [
{
"iid": 8,
"properties": [
{
"iid": 5,
"access": ["read"]
},
{
"iid": 6,
"access": ["read", "write"]
},
{
"iid": 7,
"access": ["read"]
}
]
}
],

"lumi.airer.acn01": [
{
"iid": 2,
"properties": [
{
"iid": 101,
"type": "urn:miot-spec-v2:property:dry_mode",
"format": "uint8",
"access": ["read", "write"],
"value-list": [
{"value": 0, "description": "off"},
{"value": 1, "description": "dry"},
{"value": 2, "description": "winddry"}
]
}
]
}
],

"mmgg.feeder.petfeeder": [
{
"iid": 2,
"properties": [
{
"iid": 101,
"type": "urn:mmgg-spec:property:pet-food-left-level",
"format": "uint8",
"access": ["read"],
"value-list": [
{"value": 0, "description": "Normal"},
{"value": 1, "description": "Low"},
{"value": 2, "description": "Empty"}
]
},
{
"iid": 102,
"type": "urn:miot-spec-v2:property:feedstatus",
"format": "bool",
"access": ["read", "write"]
},
{
"iid": 103,
"type": "urn:mmgg-spec:property:feed-today",
"format": "uint8",
"access": ["read"],
"unit": "none",
"value-range": [0, 255, 1]
},
{
"iid": 104,
"type": "urn:miot-spec-v2:property:desiccant-left-time",
"format": "uint16",
"access": ["read"],
"unit": "days",
"value-range": [0, 30, 1]
},
{
"iid": 105,
"type": "urn:miot-spec-v2:property:cleantime",
"description": "Clean Left Time",
"format": "uint8",
"access": ["read"],
"unit": "days",
"value-range": [0, 14, 1]
},
{
"iid": 106,
"type": "urn:mmgg-spec:property:doorstatus",
"format": "uint8",
"access": ["read", "notify"],
"unit": "none",
"value-range": [0, 1, 1]
},
{
"iid": 107,
"type": "urn:mmgg-spec:property:outletstatus",
"format": "uint8",
"access": ["read", "notify"],
"unit": "none",
"value-range": [0, 1, 1]
}
],
"actions": [
{
"iid": 101,
"type": "urn:miot-spec-v2:action:reset-desiccant-life",
"in": [],
"out": []
}
]
},
{
"iid": 200,
"type": "urn:miot-spec-v2:service:indicator-light",
"properties": [
{
"iid": 201,
"type": "urn:miot-spec-v2:property:on",
"description": "Switch Status",
"format": "bool",
"access": ["read", "write"]
}
]
},
{
"iid": 300,
"type": "urn:miot-spec-v2:service:physical-controls-locked",
"properties": [
{
"iid": 301,
"type": "urn:miot-spec-v2:property:physical-controls-locked",
"format": "bool",
"access": ["read", "write"]
}
]
}
],

"rockrobo.vacuum.v1": [
{
"iid": 2,
Expand Down
18 changes: 11 additions & 7 deletions custom_components/xiaomi_miot/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
entities.append(MiotSensorEntity(config, srv))
for entity in entities:
hass.data[DOMAIN]['entities'][entity.unique_id] = entity
async_add_entities(entities, update_before_add=True)
async_add_entities(entities, update_before_add=False)
bind_services_to_entries(hass, SERVICE_TO_METHOD)


Expand Down Expand Up @@ -153,17 +153,18 @@ def __init__(self, config, miot_service: MiotService):
self._attr_state_class = None
self._attr_native_unit_of_measurement = None

async def async_added_to_hass(self):
await super().async_added_to_hass()
if prop := self.custom_config('state_property'):
self._prop_state = self._miot_service.get_property(prop) or self._prop_state
if self._prop_state:
self._attr_icon = self._prop_state.entity_icon
self._attr_device_class = self._prop_state.device_class
self._attr_native_unit_of_measurement = self._prop_state.unit_of_measurement
self._state_attrs.update({
'state_property': self._prop_state.full_name,
})

self._state_attrs.update({
'state_property': self._prop_state.full_name if self._prop_state else None,
})

async def async_added_to_hass(self):
await super().async_added_to_hass()
cls = self.custom_config('state_class')
if cls in STATE_CLASSES:
self._attr_state_class = cls
Expand Down Expand Up @@ -196,6 +197,9 @@ async def async_update(self):
})
self._prop_state.description_to_dict(self._state_attrs)

async def async_update_for_main_entity(self):
await super().async_update_for_main_entity()

if self._miot_service.name in ['washer']:
pls = self._miot_service.get_properties(
'mode', 'spin_speed', 'rinsh_times',
Expand Down
7 changes: 5 additions & 2 deletions custom_components/xiaomi_miot/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,11 @@ def is_on(self):

def turn_on(self, **kwargs):
"""Turn the entity on."""
val = None
if self._miot_property.value_range:
val = self.custom_config_integer(self._miot_property.name)
if val is not None:
# feeding_measure
pass
elif self._miot_property.value_range:
val = int(self._miot_property.range_min() or 0)
elif self._miot_property.value_list:
val = self._miot_property.value_list[0].get('value')
Expand Down
1 change: 1 addition & 0 deletions custom_components/xiaomi_miot/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"sources_via_keycodes": "sources_via_keycodes",
"stat_power_cost_key": "stat_power_cost_key",
"state_class": "state_class",
"state_property": "state_property",
"switch_properties": "switch_properties",
"unit_of_measurement": "unit_of_measurement",
"value_ratio": "value_ratio",
Expand Down

3 comments on commit a814da3

@al-one
Copy link
Owner Author

@al-one al-one commented on a814da3 May 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Wh1terat
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@al-one Woo! 🎉

Although still couldn't resist tweaking it a little 😸

Although still need nicer solution about setting weight_level... currently will just use the prop value which is the last dispensed amount

Screenshot 2022-05-21 at 22 44 58Screenshot 2022-05-21 at 22 45 53

    'mmgg.feeder.petfeeder': { 
        'state_property': 'food_level',
        'binary_sensor_attributes': 'pet_feeder.lid_status,pet_feeder.outlet_status',
        'sensor_attributes': 'fed_today,fed_week,fed_month',
        'sensor_properties': 'dispense_amount,clean_time,dryer_time',
        'switch_properties': 'feed_status,physical-controls-locked,indicator-light',
        'button_actions': 'dispense_food,reset_dryer',
        'miio_cloud_records': 'event.feedStats:500',
        'miio_event_feedStats_template': 'mmgg_feeder_petfeeder_feedstats',
    },
    'mmgg.feeder.petfeeder:fed_*': {
        'state_class': 'total_increasing',
        'unit_of_measurement': 'units'
    },
    'mmgg.feeder.petfeeder:pet_feeder.lid_status': {
        'device_class': 'opening',
    },
    'mmgg.feeder.petfeeder:pet_feeder.outlet_status': {
        'device_class': 'problem',
    },
  "mmgg.feeder.petfeeder": [
    {
      "iid": 2,
      "properties": [
        {
          "iid": 1,
          "type": "urn:mmgg-spec:property:food_level",
          "format": "uint8",
          "access": ["read"],
          "value-list": [
            {"value": 0, "description": "Normal"},
            {"value": 1, "description": "Low"},
            {"value": 2, "description": "Empty"}
          ]
        },
        {
          "iid": 102,
          "type": "urn:miot-spec-v2:property:feed_status",
          "format": "bool",
          "access": ["read", "write"]
        },
        {
          "iid": 103,
          "type": "urn:mmgg-spec:property:dispense_amount",
          "format": "uint8",
          "access": ["read"],
          "unit": "none",
          "value-range": [0, 10, 1]
        },
        {
          "iid": 104,
          "type": "urn:miot-spec-v2:property:dryer_time",
          "format": "uint16",
          "access": ["read"],
          "unit": "days",
          "value-range": [0, 30, 1]
        },
        {
          "iid": 105,
          "type": "urn:miot-spec-v2:property:clean_time",
          "format": "uint8",
          "access": ["read"],
          "unit": "days",
          "value-range": [0, 14, 1]
        },
        {
          "iid": 106,
          "type": "urn:mmgg-spec:property:lid_status",
          "format": "uint8",
          "access": ["read", "notify"],
          "unit": "none",
          "value-range": [0, 1, 1]
        },
        {
          "iid": 107,
          "type": "urn:mmgg-spec:property:outlet_status",
          "format": "uint8",
          "access": ["read", "notify"],
          "unit": "none",
          "value-range": [0, 1, 1]
        }
      ],
      "actions": [
        {
          "iid": 1,
          "type": "urn:miot-spec-v2:action:dispense_food",
          "in": [],
          "out": []
        },
        {
          "iid": 101,
          "type": "urn:miot-spec-v2:action:reset_dryer",
          "in": [],
          "out": []
        }
      ]
    },
    {
      "iid": 200,
      "type": "urn:miot-spec-v2:service:indicator-light",
      "properties": [
        {
          "iid": 201,
          "type": "urn:miot-spec-v2:property:on",
          "format": "bool",
          "access": ["read", "write"]
        }
      ]
    },
    {
      "iid": 300,
      "type": "urn:miot-spec-v2:service:physical-controls-locked",
      "properties": [
        {
          "iid": 301,
          "type": "urn:miot-spec-v2:property:physical-controls-locked",
          "format": "bool",
          "access": ["read", "write"]
        }
      ]
    }
  ],
    'mmgg.feeder.petfeeder': {
        'without_props': True,
        'miio_commands': [
            {
                'method': 'getprops',
                'values': [
                    'food_status', 'feed_status', 'door_status', 'feed_today', 'clean_days', 'outlet_status',
                    'dryer_days', 'weight_level', 'wifi_led', 'key_lock', 'country_code',
                ],
            },
        ],
        'miio_specs': {
            'prop.2.1': {'prop': 'food_status'},
            'prop.2.102': {'prop': 'feed_status', 'setter': 'stopfeed', 'set_template': '{{ [value|int] }}'},
            'prop.2.103': {'prop': 'weight_level'},
            'prop.2.104': {'prop': 'dryer_days'},
            'prop.2.105': {'prop': 'clean_days'},
            'prop.2.106': {'prop': 'door_status'},
            'prop.2.107': {'prop': 'outlet_status'},
            'action.2.1': {
                'setter': 'outfood',                 
                'set_template': '{% set fval = props.get("weight_level")|default(1)|int(0) %}'
                '{{ [fval] }}',
            },
            'action.2.101': {'setter': 'resetdryer'},
            'prop.200.201': {'prop': 'wifi_led', 'setter': 'wifiledon', 'set_template': '{{ [value|int] }}'},
            'prop.300.301': {
                'prop': 'key_lock',
                'setter': 'keylock',
                'template': '{{ not value }}',
                'set_template': '{{ [0 if value else 1] }}',
            },
        }
    },
    'mmgg_feeder_petfeeder_feedstats': "{%- set dat = namespace(today=0,week=0,month=0) %}"
                                        "{%- set tim = now() %}"
                                        "{%- set hour = tim.replace(minute=0, second=0) %}"
                                        "{%- set today = hour.replace(hour=0) %}"
                                        "{%- set week = (today - timedelta(days=7)) | as_timestamp | int(0) %}"
                                        "{%- set month = (today - timedelta(days=tim.day-1)) | as_timestamp | int(0) %}"
                                        "{%- set today = today | as_timestamp | int(0) %}"
                                        "{%- for d in (result or []) %}"
                                        "{%-   set t = d.time | default(0) | int(0) %}"
                                        "{%-   if t >= month %}"
                                        "{%-     set v = (d.value | default('[]') | string | from_json) or [] %}"
                                        "{%-     set n = v[0] | default(0) %}"
                                        "{%-     if t >= week %}"
                                        "{%-       set dat.week = dat.week + n %}"
                                        "{%-       if t >= today %}"
                                        "{%-         set dat.today = dat.today + n %}"
                                        "{%-       endif %}"
                                        "{%-     endif %}"
                                        "{%-     set dat.month = dat.month + n %}"
                                        "{%-   endif %}"
                                        "{%- endfor %}"
                                        "{{ {"
                                        "'fed_today': dat.today | int(0),"
                                        "'fed_week': dat.week | int(0),"
                                        "'fed_month': dat.month | int(0),"
                                        "'_entity_attrs': True,"
                                        "} }}",

@pvdburgt-new
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ì don't see the button to dispense food?

Please sign in to comment.