Improved support of the Xiaomi Philips Eyecare 2

I would like to improve the support of the Xiaomi Philips Eyecare 2. light.xiaomi_miio provides basic support so far. I’ve introduced a bunch of new services here:


xiaomi_miio_ambient_on
xiaomi_miio_ambient_off
xiaomi_miio_eyecare_on
xiaomi_miio_eyecare_off
xiaomi_miio_reminder_on
xiaomi_miio_reminder_off
xiaomi_miio_smart_night_light_on
xiaomi_miio_smart_night_light_off
xiaomi_miio_set_scene
xiaomi_miio_set_ambient_brightness
xiaomi_miio_set_delay_off

Is someone (@moskovskiy82) willing to test the new features?

1 Like

Will download and test it out straight away. Thank you!

In first glance - working with no errors. Haven’t tried out advanced functionality (ambient light e.t.c.) yet

Everything works as expected. Is it going to be iintegrated with HA?

It’s merged already and will be part of HA 0.65.

Does the device show up with to entities? Are you able to turn in the lights independently?

Yes 2 entities. They were working before i upgraded to 0.64
I have upgraded and also pulled latest code from your repo. Now i can turn them on but not off. And still get the spam of “Unable to discover”

2018-03-04 03:50:28 ERROR (SyncWorker_9) [miio.device] Got error when receiving: timed out
2018-03-04 03:50:33 ERROR (SyncWorker_9) [miio.device] Unable to discover a device at address xxx.xxx.xxx.61
2018-03-04 03:50:49 ERROR (SyncWorker_16) [miio.device] Unable to discover a device at address 172.16.5.61
2018-03-04 04:09:17 ERROR (SyncWorker_1) [homeassistant.components.light.yeelight] Unable to update bulb status: A socket error occurred when sending the command.
2018-03-04 09:35:24 ERROR (SyncWorker_6) [miio.protocol] unable to parse json '{"result":["on",85,"off"net],"id":5362}': Expecting ',' delimiter: line 1 column 25 (char 24)
2018-03-04 09:35:24 ERROR (MainThread) [homeassistant.helpers.entity] Update for light.kids_philips fails
Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 204, in async_update_ha_state
    yield from self.async_device_update()
  File "/srv/homeassistant/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 325, in async_device_update
    yield from self.async_update()
  File "/home/homeassistant/.homeassistant/custom_components/light/xiaomi_miio.py", line 622, in async_update
    state = yield from self.hass.async_add_job(self._light.status)
  File "/usr/local/lib/python3.6/asyncio/futures.py", line 327, in __iter__
    yield self  # This tells Task to wait for completion.
  File "/usr/local/lib/python3.6/asyncio/tasks.py", line 250, in _wakeup
    future.result()
  File "/usr/local/lib/python3.6/asyncio/futures.py", line 243, in result
    raise self._exception
  File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/srv/homeassistant/lib/python3.6/site-packages/miio/philips_eyecare.py", line 94, in status
    properties
  File "/srv/homeassistant/lib/python3.6/site-packages/miio/device.py", line 249, in send
    self.__id = m.data.value["id"]
TypeError: 'NoneType' object is not subscriptable
2018-03-04 09:42:05 ERROR (MainThread) [homeassistant.core] Error executing service <ServiceCall light.turn_off: entity_id=['light.kids_philips_ambient_light']>
Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.6/site-packages/homeassistant/core.py", line 1010, in _event_to_service_call
    yield from service_handler.func(service_call)
  File "/srv/homeassistant/lib/python3.6/site-packages/homeassistant/components/light/__init__.py", line 272, in async_handle_light_service
    yield from light.async_turn_off(**params)
  File "/home/homeassistant/.homeassistant/custom_components/light/xiaomi_miio.py", line 793, in async_turn_off
    yield from self._try_command(
AttributeError: 'XiaomiPhilipsEyecareLampAmbientLight' object has no attribute '_try_command'

Tell me if more information is needed.

Ups. When did you checkout the repository? Could you update the custom component again? I made some changes tonight. The issue should be fixed. Thanks for testing!

Yesterday. Pulled a fresh one and now the errors are gone. But the problem remains. I can switch it on but not off. Now nothing in the logs.

IO have made the following changes to configuration yaml for logging

logger:
  default: error
  logs:
    homeassistant.components.light.xiaomi_miio: debug

But remains the same… Light turns on. When switching off - doesn’t work. It stays on in the interface as well.
Logs are empty. Nothing in them.

Although when switching off manually via the button on the lamp - the state in HA gets updated. But it takes around 5 seconds.

Alright. I will check the code. Wait a sec! :wink: Cannot both lights turned off or just one (eyeceare vs. ambient) light?

I have also noticed in the pull request there is now a model line “model: philips.light.sread1”. I didn’t fill that in.

- platform: xiaomi_miio
  name: Kids Philips
  host: the ip
  token: 'some long token'

Entity id’s show up like

light.kids_philips	off	
model: philips.light.sread1
scene: 1
delayed_turn_off: null
reminder: false
night_light_mode: true
friendly_name: Kids Philips
supported_features: 61

light.kids_philips_2	off	
model: philips.light.sread1
friendly_name: Kids Philips
supported_features: 1

Just noticed there is a delayed_turn_off: null… Null?

This is fine. It just provides a “device unavailable” behavior and avoids the auto detection of the device model.

This is fine, too. It’s a service to turn off the device after a specific delay (in minutes). You didn’t setup a delayed turn off. That’s why the value “null” is fine.

The eyecare (main light) is controllable and the ambient light has problems, right?

Nope. Main light is having problems. Ambient light switches on and off fine of course together with the main light.

You are familiar with the mirobo cli tool, correct? Could you do some investigations:


# The complete mirobo looks like this:
# mirobo --ip ip --token token raw_command ....
# I've reduced the following examples for legibility.

# returns the current state
mirobo raw_command get_prop '["power", "bright", "notifystatus", "ambstatus", "ambvalue", "eyecare", "scene_num", "bls", "dvalue" ]'

# turns the device on, resumes the previous configuration
mirobo raw_command set_power '["on"]'

# returns the current state
mirobo raw_command get_prop '["power", "bright", "notifystatus", "ambstatus", "ambvalue", "eyecare", "scene_num", "bls", "dvalue" ]'

# turns the device off
mirobo raw_command set_power '["off"]'

# returns the current state
mirobo raw_command get_prop '["power", "bright", "notifystatus", "ambstatus", "ambvalue", "eyecare", "scene_num", "bls", "dvalue" ]'

# turns the main light on called eyecare light?
mirobo raw_command set_eyecare '["on"]'

# returns the current state
mirobo raw_command get_prop '["power", "bright", "notifystatus", "ambstatus", "ambvalue", "eyecare", "scene_num", "bls", "dvalue" ]'

# turns the main light off?
mirobo raw_command set_eyecare '["off"]'

# returns the current state
mirobo raw_command get_prop '["power", "bright", "notifystatus", "ambstatus", "ambvalue", "eyecare", "scene_num", "bls", "dvalue" ]'

# turns the ambient light on? 
mirobo raw_command enable_amb '["on"]'

# returns the current state
mirobo raw_command get_prop '["power", "bright", "notifystatus", "ambstatus", "ambvalue", "eyecare", "scene_num", "bls", "dvalue" ]'

# turns the ambient light off? 
mirobo raw_command enable_amb '["off"]'

# returns the current state
mirobo raw_command get_prop '["power", "bright", "notifystatus", "ambstatus", "ambvalue", "eyecare", "scene_num", "bls", "dvalue" ]'

It’s possible to control both lights (eyecare & ambient) independently? It’s possible to use the ambient light without the main light turned on? Is “set_eyecare” the switch of the main light or it’s just a mode (meaning unknown)?

Thanks in advance! The light is a mysterium to me.

raw_command get_prop '["power", "bright", "notifystatus", "ambstatus", "ambvalue", "eyecare", "scene_num", "bls", "dvalue" ]'

Sending cmd get_prop with params ['power', 'bright', 'notifystatus', 'ambstatus', 'ambvalue', 'eyecare', 'scene_num', 'bls', 'dvalue']
['off', 100, 'off', 'off', 97, 'off', 1, 'on', 0]

let’s put it on (switches only the main light on)

raw_command set_power '["on"]'
Sending cmd set_power with params ['on']
['ok']

New status

Sending cmd get_prop with params ['power', 'bright', 'notifystatus', 'ambstatus', 'ambvalue', 'eyecare', 'scene_num', 'bls', 'dvalue']
['on', 100, 'off', 'off', 97, 'off', 1, 'on', 0]

let’s put it off (switches only the main light off)

Sending cmd set_power with params ['off']
['ok']

New status

Sending cmd get_prop with params ['power', 'bright', 'notifystatus', 'ambstatus', 'ambvalue', 'eyecare', 'scene_num', 'bls', 'dvalue']
['off', 100, 'off', 'off', 97, 'off', 1, 'on', 0]

enable_amb ‘[“on”]’ - switches the main light (if it was off) and ambient light on together.

Sending cmd get_prop with params ['power', 'bright', 'notifystatus', 'ambstatus', 'ambvalue', 'eyecare', 'scene_num', 'bls', 'dvalue']
['on', 100, 'off', 'on', 97, 'off', 1, 'on', 0]

enable_amb ‘[“off”]’ switches off only ambient light

And set eyecare - can’t get what it does…
On - switches on both lights

Sending cmd get_prop with params ['power', 'bright', 'notifystatus', 'ambstatus', 'ambvalue', 'eyecare', 'scene_num', 'bls', 'dvalue']
['on', 71, 'off', 'on', 97, 'on', 1, 'on', 0]

off seems to do nothing

Sending cmd get_prop with params ['power', 'bright', 'notifystatus', 'ambstatus', 'ambvalue', 'eyecare', 'scene_num', 'bls', 'dvalue']
['on', 100, 'off', 'on', 97, 'off', 1, 'on', 0]

Seems the ambient light cannot be turned on independently. But we can turn it on and dim the main light as much as possible

1 Like

Alright. I have updated the custom component. The main entity uses set_power now. The ambient light is controlled by enable_amb. I don’t use set_eyecare anymore. Thanks for your time!

1 Like

You must be kidding… Thank you for your time!

Wait before disabling… I think that eyecare is that thing which automatically regulates light intensity based on the built in brightness sensor. I will experiment with that

Cool. If you know the meaning of “set_eyecare” I will implement a service.

I’ve added two new services:

light.xiaomi_miio_eyecare_mode_on
light.xiaomi_miio_eyecare_mode_off

I would be happy about some testing.

After further testing received this error

2018-03-12 18:49:43 ERROR (SyncWorker_11) [miio.protocol] unable to parse json '{"result":["on",100,"off","on",41,"off"net],"id":6561}': Expecting ',' delimiter: line 1 column 40 (char 39)
2018-03-12 18:49:43 ERROR (MainThread) [homeassistant.helpers.entity] Update for light.kids_philips fails
Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 204, in async_update_ha_state
    yield from self.async_device_update()
  File "/srv/homeassistant/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 325, in async_device_update
    yield from self.async_update()
  File "/home/homeassistant/.homeassistant/custom_components/light/xiaomi_miio.py", line 816, in async_update
    state = yield from self.hass.async_add_job(self._light.status)
  File "/usr/local/lib/python3.6/asyncio/futures.py", line 327, in __iter__
    yield self  # This tells Task to wait for completion.
  File "/usr/local/lib/python3.6/asyncio/tasks.py", line 250, in _wakeup
    future.result()
  File "/usr/local/lib/python3.6/asyncio/futures.py", line 243, in result
    raise self._exception
  File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/srv/homeassistant/lib/python3.6/site-packages/miio/philips_eyecare.py", line 94, in status
    properties
  File "/srv/homeassistant/lib/python3.6/site-packages/miio/device.py", line 249, in send
    self.__id = m.data.value["id"]
TypeError: 'NoneType' object is not subscriptable
2018-03-12 18:53:15 ERROR (MainThread) [homeassistant.core] Error doing job: Fatal read error on socket transport
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/asyncio/selector_events.py", line 723, in _read_ready
    data = self._sock.recv(self.max_size)
TimeoutError: [Errno 110] Connection timed out