michielpost / Q42.HueApi

C# helper library to talk to the Philips Hue bridge
MIT License
411 stars 114 forks source link

Working out what sensors belong to what devices #279

Closed PonchoPowers closed 2 years ago

PonchoPowers commented 2 years ago

When I call GetSensorsAsync I get a list of sensors in what appears to be an ordered result but I can't tell if this is guaranteed or not.

The reason this is important is because I have an outdoor motion sensor that returns 3 Sensor classes in the IReadOnlyCollection returned from the GetSensorsAsync call.

The first contains the device name, the second and third contain the sensors in the device.

image image image

Is there a way to relate all 3 so that I know that the two sensors belong to the device named X?

The reason for asking is I would like to be able to create rules based on specific devices so knowing which light sensor belongs to which device is important in order to be able to set up the rules in a GUI.

michielpost commented 2 years ago

If it's just for your personal use, you can give them custom names and select them on name or maybe on Type?

If you really need to find it through the IDs, I would suggest using the V2 APIs. For example motion sensors have a owner resource ID: https://developers.meethue.com/develop/hue-api-v2/api-reference/#resource_motion_get

Support for the V2 APIs is available in the HueApi package: https://github.com/michielpost/Q42.HueApi#clip-v2-api https://www.nuget.org/packages/HueApi/

PonchoPowers commented 2 years ago

I haven't migrated to V2 yet but it sounds like it will be worth looking into. The reason I've blanked out some details is that I'm using this for home security as we had almost £100k of vehicles stolen from our house in a 3 week period so I'm now taking action to prevent any further thefts.

PonchoPowers commented 2 years ago

There are a few missing fields in some of the classes such as HueApi.Models.LightLevel, so if I then parse the ExtensionData to get the information I need I'll have to rewrite the code at some point to make use of the LightLevel model. I appreciate that not everything is implemented yet, but it is also mentioned that an issue or PR should be created if something is needed that is not supported yet. Are you happy with me creating a PR to ensure LightLevel is populated with the data that is retrieved from the bridge?

michielpost commented 2 years ago

Yes, a PR that adds missing fields is more than welcome! Thanks.

PonchoPowers commented 2 years ago

I written the following code:

namespace HueApi.Models
{
  public class LightLevel : HueResource
  {
    [JsonPropertyName("enabled")]
    public bool Enabled { get; set; }

    [JsonPropertyName("light")]
    public Light Light { get; set; }

    [JsonPropertyName("owner")]
    public ResourceIdentifier? Owner { get; set; }
  }

  public class Light
  {
    [JsonPropertyName("light_level")]
    public int LightLevel { get; set; }

    [JsonPropertyName("light_level_valid")]
    public bool LightLevelValid { get; set; }
  }
}

But obviously the Light class already exists, so should I use the namespace HueApi.Models.LightLevel to resolve the conflict or is there a preferred way to resolve the clashing naming convention?

Also, how are you determining whether something can be nullable?

michielpost commented 2 years ago

If the Light here contains the same properties, you can reuse the existing Light class. If it's specific for the LightLevel (what it looks like here), you can create something called LightLevelLight or LightLevelLightModel?

PonchoPowers commented 2 years ago

It is specific for LightLevel, and using the naming you suggested will look like so:

foreach (LightLevel lightLevel in lightLevels.Data)
{
    var lightLevel = lightLevel.LightLevelLight.LightLevel;
}

I was thinking of breaking from the naming convention and using Lux like so:

foreach (LightLevel lightLevel in lightLevels.Data)
{
    var lightLevel = lightLevel.Lux.LuxLevel;
}

Or if we used a different namespace we could do:

foreach (LightLevel lightLevel in lightLevels.Data)
{
    var lightLevel = lightLevel.Light.LightLevel;
}

Which I think is only marginally better than the first.

It is almost like the guys who write the API have overlooked this so I might point it out to them too.

michielpost commented 2 years ago

LuxLevel also sounds good!

PonchoPowers commented 2 years ago

Sorry I did more digging and found that the light level is not the lux, to get the lux you have to do the following:

    public double LuxLevel
    {
      get
      {
        double lightLevel = LightLevel > 0 ? LightLevel - 1 : 0;
        lightLevel = lightLevel / 10000;
        return Math.Pow(10, lightLevel);
      }
    }

So to call it lux could be misleading.

As a result I've gone back to my suggestion of using namespaces, the code looks like so when being called:

var lightLevel = lightLevel.Light.LightLevel;

This means the sensors are all in their own HueApi.Models.Sensors namespace now.

I've created a PR for the change, https://github.com/michielpost/Q42.HueApi/pull/281