dominicusmento / CSharpTradFriLibrary

This is a .NET Standard (2.0) library to communicate with the IKEA Home (Tradfri) ZigBee-based Gateway.
GNU General Public License v3.0
37 stars 20 forks source link

Custom moods activation not working properly with multiple bulbs #30

Closed evaanp closed 4 years ago

evaanp commented 4 years ago

When using the SetMood(TradfriGroup group, TradfriMood mood) method with a custom mood (the one i'm using has three lights on 1% and 4 lights on 0%) the lights will just turn on, like they do with the SetLights method.

dominicusmento commented 4 years ago

Can you create a gist/code example or link a code you are using so we can reproduce the issue?

evaanp commented 4 years ago

Well, i could provide some code if you still need it, but the only thing i'm doing is calling the "SetMood" method.

When looking through the code i noticed this: The "SetMood" method receives a TradfriMood object as a paramater. The TradfriMood contains a property called MoodProperties, which contains info about the mood, with light levels and such.

After some googeling i found an API doc about tradfri with the following:

Payload Here is an example payload for coap-client with explanation what each field does:

{
  "3311": [
    {
      "5850": 1, // on / off
      "5851": 254, // dimmer (1 to 254)
      "5706": "f1e0b5", // color in HEX (Don't use in combination with: color X and/or color Y)
      "5709": 65535, // color X (Only use in combination with color Y)
      "5710": 65535, // color Y (Only use in combination with color X)
      "5712": 10 // transition time (fade time)
    }
  ]
}

It kinda looks like this is the same information what is in the mood property of the mood object.

The first call made in the "SetMood" method seems like you need to tell the tradfri hub what mood properties you want to set, but there only the first property is passed:

content: mood.MoodProperties[0]

When referring back to the api docs, it looks like it should pass a JSON string with all the properties, while in the request only the first one is sent. Could this be the problem?

Full method:

public async Task SetMood(long id, TradfriMood mood)
        {
            await HandleRequest($"/{(int)TradfriConstRoot.Groups}/{id}", Call.PUT, content: mood.MoodProperties[0], statusCode: System.Net.HttpStatusCode.NoContent);

            var set = new SwitchStateLightRequestOption()
            {
                Mood = mood.ID
            };
            await HandleRequest($"/{(int)TradfriConstRoot.Groups}/{id}", Call.PUT, content: set, statusCode: System.Net.HttpStatusCode.NoContent);
        }
dominicusmento commented 4 years ago

Well, i could provide some code if you still need it, but the only thing i'm doing is calling the "SetMood" method.

Yes, because it works for me. You are definitely doing something wrong. The exact values you have given in your json..

evaanp commented 4 years ago

When serializing my mood it looks like this:

{ 
   "15013":[ 
      { 
         "5706":null,
         "5707":0,
         "5708":0,
         "5709":0,
         "5710":0,
         "5711":0,
         "5850":1,
         "5851":3,
         "9003":65537
      },
      { 
         "5706":null,
         "5707":0,
         "5708":0,
         "5709":0,
         "5710":0,
         "5711":0,
         "5850":1,
         "5851":3,
         "9003":65538
      },
      { 
         "5706":null,
         "5707":0,
         "5708":0,
         "5709":0,
         "5710":0,
         "5711":0,
         "5850":0,
         "5851":1,
         "9003":65539
      },
      { 
         "5706":null,
         "5707":0,
         "5708":0,
         "5709":0,
         "5710":0,
         "5711":0,
         "5850":0,
         "5851":1,
         "9003":65554
      },
      { 
         "5706":null,
         "5707":0,
         "5708":0,
         "5709":0,
         "5710":0,
         "5711":0,
         "5850":0,
         "5851":1,
         "9003":65541
      },
      { 
         "5706":null,
         "5707":0,
         "5708":0,
         "5709":0,
         "5710":0,
         "5711":0,
         "5850":0,
         "5851":1,
         "9003":65542
      },
      { 
         "5706":null,
         "5707":0,
         "5708":0,
         "5709":0,
         "5710":0,
         "5711":0,
         "5850":1,
         "5851":2,
         "9003":65556
      }
   ],
   "9001":"Tv modus",
   "9002":1546897957000000,
   "9003":196615,
   "9057":4,
   "9068":0,
   "GroupID":131073
}

The code that calls the SetMood method looks like this:

public async void SetMood(long groupId, long moodId)
        {
            TradfriMood mood = foundMoods.Find(m => m.ID == moodId);
            TradfriGroup group = foundGroups.Find(g => g.ID == groupId);

            Console.WriteLine(JsonConvert.SerializeObject(mood));

            mController.GroupController.SetMood(group, mood);
            //SetDimmer(groupId, moodId);
        }

And the part of the code that collects the groups/moods/fixtures looks like this:

foundGroups = new List<TradfriGroup>(await mController.GatewayController.GetGroupObjects());
            foundDevices = new List<TradfriDevice>(await mController.GatewayController.GetDeviceObjects());
            foundMoods = new List<TradfriMood>(await mController.GatewayController.GetMoods());
evaanp commented 4 years ago

When calling the mood manually like this:

foreach (var moodProp in mood.MoodProperties)
            {
                TradfriDevice device = foundDevices.Find(d => d.ID == moodProp.ID);

                if (device.DeviceType == DeviceType.Light)
                {
                    await mController.DeviceController.SetDimmer(device, (int)moodProp.Dimmer);
                    await mController.DeviceController.SetLight(device, moodProp.LightState > 0);
                }
                else if (device.DeviceType == DeviceType.ControlOutlet)
                {
                    await mController.DeviceController.SetOutlet(device, moodProp.LightState > 0);
                }
            }  

It works, but it will toggle between the right mood and "just on" everytime i call it(strangely enough). The downside of this is that is costs a fair amount of processing power everytime a mood is called. The Tradfri Hub also has trouble processing multiple calls in a row.

However, what this proves is that the props given to the mood are correct.

dominicusmento commented 4 years ago

This should now be solved in version 1.2.2.35. You can find example in TradFriUI project, main.cs file.