Hue-sensors-HASS icon indicating copy to clipboard operation
Hue-sensors-HASS copied to clipboard

need help creating daylight sensor

Open Mariusthvdb opened this issue 4 years ago • 10 comments

HI,

trying to add the one missing sensor, for Daylight, I seek help please..

this is what I have sofar:

def parse_phd(response):
    """Parse the json for a PHD Daylight sensor and return the data."""
    if response["type"] == "Daylight":
        hue_state = response["state"]["daylight"] #true/false
        if hue_state is True:
            state = STATE_ON
        else:
            state = STATE_OFF

        data = {
            "model": "PHD",
            "on": response["config"]["on"],
            "configured": response["config"]["configured"],
            "sunriseoffset": response["config"]["sunriseoffset"],
            "sunsetoffset": response["config"]["sunsetoffset"],
            "name": name,
            "type": type,
            "modelid": modelid,
            "swversion": swversion,
            "daylight": response["state"]["daylight"],
            "lastupdated": response["state"]["lastupdated"].split("T")
        }

    return data

and I think we need this:

    @property
    def is_on(self):
        """Return the state of the sensor."""
        data = self._data.get(self._hue_id)
        if data and data["model"] in ["SML","PHD"] and data["changed"]:
            return data["state"] == STATE_ON
        return False

not sure though if we need, and how to create the unique Hue id

    @property
    def unique_id(self):
        """Return the ID of this Hue sensor."""
        return self._hue_id[+4:][:-3]

since the PHD sensor is not the exact same format.

this might be needed in:

def parse_hue_api_response(sensors):
    """Take in the Hue API json response."""
    data_dict = {}  # The list of sensors, referenced by their hue_id.

    # Loop over all keys (1,2 etc) to identify sensors and get data.
    for sensor in sensors:
        modelid = sensor["modelid"][0:3]
        if modelid == "SML":
            _key = modelid + "_" + sensor["uniqueid"][:-5]
            if _key not in data_dict:
                data_dict[_key] = parse_sml(sensor)
            else:
                data_dict[_key].update(parse_sml(sensor))

        elif modelid == "PHD":
            _key = modelid
            if _key not in data_dict:
                data_dict[_key] = parse_phd(sensor)
            else:
                data_dict[_key].update(parse_phd(sensor))

    return data_dict

I get this error:

2020-02-01 01:33:43 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 419, in _async_add_entity
    await entity.async_update_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 284, in async_update_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 320, in _async_write_ha_state
    state = self.state
  File "/usr/src/homeassistant/homeassistant/components/binary_sensor/__init__.py", line 152, in state
    return STATE_ON if self.is_on else STATE_OFF
  File "/config/custom_components/hue_custom/binary_sensor.py", line 293, in is_on
    return data["state"] == STATE_ON

while the Hue Api returns:

{"1":{"state":{"daylight":false,"lastupdated":"2020-01-31T15:58:00"},"config":{"on":true,"configured":true,"sunriseoffset":30,"sunsetoffset":-30},"name":"Daylight","type":"Daylight","modelid":"PHDL00","manufacturername":"Philips","swversion":"1.0"},

binary_sensor daylight should have state = 'on' when daylight = 'true'.... it now is 'false' so binary should be off.

why does this error out with said error?

please let me ask for assistance, @koying @robmarkcole @yottatsa thanks!

Mariusthvdb avatar Feb 01 '20 00:02 Mariusthvdb

Assuming you add this to "binary_sensor.py", you don't have to overload "unique_id". It will always be "PHDL00" (which will be a problem if you have multiple bridges, but let's put this problem aside for now)

Problem is probably that you don't set "state" in your "parse_phd". "daylight": response["state"]["daylight"] sould be "state": response["state"]["daylight"], I think

koying avatar Feb 01 '20 08:02 koying

Ok thanks, missed that indeed, will add.

Yes using multiple hubs must be taken care off , (I have 2...) what would be your suggestion to do so?

Also, I think I need to add a catch for None.

Mariusthvdb avatar Feb 01 '20 08:02 Mariusthvdb

We need to get some kind of bridge id. By reading the core hue component source, I think the id can be obtained with bridge.api.id in HueSensorData.update_bridge.

This would need to be passed down to parse_hue_api_response, and appended to the modelid.

koying avatar Feb 01 '20 09:02 koying

bingo:

Schermafbeelding 2020-02-01 om 10 29 12

check the sensor, it is not showing the correct state though....

Schermafbeelding 2020-02-01 om 10 32 31

Now I want to prefix "hue_" so it creates binary_sensor.hue_daylight. Will check the device_tracker for that. Nice!

Mariusthvdb avatar Feb 01 '20 09:02 Mariusthvdb

update:

def parse_phd(response):
    """Parse the json for a PHD Daylight sensor and return the data."""
    if response["type"] == "Daylight":
        daylight = response["state"]["daylight"]
        hue_state = response["state"]["daylight"]
        if hue_state is True:
            state = STATE_ON
        else:
            state = STATE_OFF
        if daylight is not None:
            data = {
                "model": "PHD",
                "state": daylight,
                "on": response["config"]["on"],
                "configured": response["config"]["configured"],
                "sunriseoffset": response["config"]["sunriseoffset"],
                "sunsetoffset": response["config"]["sunsetoffset"],
                "name": response["name"],
                "type": response["type"],
                "modelid": response["modelid"],
                "swversion": response["swversion"],
                "daylight": daylight,
                "lastupdated": response["state"]["lastupdated"].split("T")
            }
        else:
            data = {
                "model": "PHD",
                "state": "No Daylight data",
                "on": None,
                "configured": None,
                "sunriseoffset": None,
                "sunsetoffset": None,
                "name": None,
                "type": None,
                "modelid": None,
                "swversion": None,
                "daylight": "No Daylight data",
                "lastupdated": None
            }

    return data

must I use hue_state (maybe for use elsewhere in the config) or would daylight also do for the state calculation ?

Mariusthvdb avatar Feb 01 '20 09:02 Mariusthvdb

"state": daylightmust be "state": state Not sure you need the intermediary hue_state variable

I don't think you could get a "Daylight" sensor without actual daylight info, so the if: else: is unnecessary, imo

koying avatar Feb 01 '20 10:02 koying

yep:

Schermafbeelding 2020-02-01 om 12 58 03

added some more changes: took out the icon setting, device_class sets Icon automatically

# ICONS = {"SML": "mdi:run"}
DEVICE_CLASSES = {"SML": "motion","PHD": "light"}

changed tholdoffset to threshold_offset by request @robmarkcole and took sunrise and sunset along, as well as last_updated...

    "PHD": [
        "on",
        "configured",
        "sunrise_offset",
        "sunset_offset",
        "name",
        "type",
        "modelid",
        "swversion",
        "daylight",
        "last_updated",
    ]
Schermafbeelding 2020-02-01 om 13 40 55

will change in PR later today!

left to do still:

add prefix hue_ to name add unique id to sensor, need some help with what you said there...

Mariusthvdb avatar Feb 01 '20 11:02 Mariusthvdb

separate post:

adding this:

def parse_phd(response):
    """Parse the json for a PHD Daylight sensor and return the data."""
    if response["type"] == "Daylight":
        daylight = response["state"]["daylight"]
        name_raw = response["name"]
        name = "Hue " + name_raw

gives a friendly name to the binary_sensor, but doesn't change the device_id (entity_id) in to binary_sensor.hue_daylight which is what I think we would need. Please have a lok how we can realize that? (taking into account a multiple Hub setup is should be possible too, so if we can prevent the hard coded name, that would be better)

thanks for the assistance!

Schermafbeelding 2020-02-01 om 15 18 34

Mariusthvdb avatar Feb 01 '20 14:02 Mariusthvdb

I suggest you create the PR, then we can go from that and add the remaining open points

koying avatar Feb 01 '20 14:02 koying

ok willl do, Ill wait for the PR on threshold_offset https://github.com/robmarkcole/Hue-sensors-HASS/pull/190 to be merged.

update

see: https://github.com/robmarkcole/Hue-sensors-HASS/pull/195

Mariusthvdb avatar Feb 01 '20 15:02 Mariusthvdb