Com-AugustCellars / CoAP-CSharp

CoAP Implementation in C#
Other
41 stars 19 forks source link

Ikea Tradfri - Client Put is not working after a period of time #43

Open bmachuletz opened 6 years ago

bmachuletz commented 6 years ago

Hi, i am using this library to control IKEA Tradfri lamps. But after period of time the connection to my gateway seems to be broken. After restart of my application all is running fine. Maybe anyone has a good starting point to look at for investigating the problem?

Thanx Benjamin

jimsch commented 6 years ago

A couple of questions.

  1. what is the time interval after which it starts failing?
  2. Do you have a router between the machine running the app and the Tradfri gateway?

My first guess is either a) a router is dropping the path from the table so the DTLS connection is no longer getting to the device on the same IP address pair or b) the gateway is dropping the DTLS connection after a period of inactivity. I have not see this when playing with things, but have not tried to do long lived connections.

bmachuletz commented 6 years ago
  1. I'll check the time interval as soon as i can. the app is running on my raspberry pi compiled with mono... so i'm currently not getting notified when the problem occures.
  2. The devices are connected via static ip to an AVM Fritzbox router. I'll plug the devices into another network switch and look what will happen :) Thank you very much!!
jimsch commented 6 years ago

After sleeping on things, if you are running IPv6 it is possible that you have privacy mode where an automatic address change is done every so often.

bmachuletz commented 6 years ago

I have checked the Firmware of my tradfri Gateway (it is currently 1.2.42). It says "newest version". The code i've written is near by your example. <- and it already works :) To be sure there is no link failure, I have connected the gateway and my Raspberry to an other ethernet switch. IPv6 is disabled. I'll report my results tomorrow evening.

jimsch commented 6 years ago

I don't know if you can, but putting a wireshark monitor on the same subnet as the gateway would probably give good information as well

bmachuletz commented 6 years ago

this is a good idea. Imho, the the best way to get this specific traffic is to install a transparent bridge between the Raspberry and the ethernet switch. This gives the opportunity to wireshark on the bridge interface. An other option is to monitor the swich ports itself, but I do not have such infrastructure at home. In other words, if I am not getting further with my problem, I'll looking forward to sniff the traffic and see whats really going on... :)

bmachuletz commented 6 years ago

One shot, one hit... my application is now running for about 20 hours on the new ethernet switch. and voila... it seems to work. I'll report if it passes the next days too.

dominicusmento commented 6 years ago

@bmachuletz I'm looking to do the same thing. Sort of a .net library which would communicate with TradFri gateway. I have a problem with dtls - I haven't found any example of how the package request should look. Can you help with the handshake, how to send the sn and secret to the gateway in coap request?

bmachuletz commented 6 years ago

This is my code fort he connect:

public TradfriClient() { keepAliveTimer = new System.Timers.Timer(60000); keepAliveTimer.Elapsed += KeepAliveTimer_Elapsed; keepAliveTimer.Start();

        try
        {
            userKey = new OneKey();

            DeviceList = new List<TradfriDevice>();

            userKey.Add(CoseKeyKeys.KeyType, GeneralValues.KeyType_Octet);
            userKey.Add(CoseKeyParameterKeys.Octet_k, CBORObject.FromObject(Encoding.UTF8.GetBytes("XRgp1htdDiVkBQCV")));
        //    userKey.Add(CoseKeyKeys.KeyIdentifier, CBORObject.FromObject(Encoding.UTF8.GetBytes("HomeMagic")));

            // userKey.Add(CoseKeyKeys.KeyIdentifier, CBORObject.FromObject(Encoding.UTF8.GetBytes("user name")));

            ep = new DTLSClientEndPoint(userKey);
            client = new CoapClient(new Uri("coaps://GW-DCEFCAB82B4F"))
            {
                EndPoint = ep
            };

            ep.Start();

            IEnumerable<WebLink> resources = client.Discover();

            foreach (var resource in resources)
            {
                foreach (string s in HomeMagic.Shared.StringHelper.GetMatches(resource.ToString(), "<", ">"))
                {
                    client.UriPath = s;
                    Response response = client.Get();

                    Console.WriteLine(response.PayloadString);

                    try
                    {
                        TradfriDevice dev = Newtonsoft.Json.JsonConvert.DeserializeObject<TradfriDevice>(response.PayloadString);

                        if (dev != null)
                        {
                            if (dev.Id >= 65537
                                && dev.TradfriDeviceName != "TRADFRI group" && dev.TradfriDeviceName != "RELAX"
                                && dev.TradfriDeviceName != "FOCUS" && dev.TradfriDeviceName != "EVERYDAY")
                            {
                                dev.Path = s;
                                DeviceList.Add(dev);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message.ToString());
                        // nothing
                    }

                }
            }

            // ep.Stop();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message.ToString());
        }
    } 

And this is how I am sending requests tot he gateway:

    private void SwitchOnDevice(TradfriDevice dev)
    {
        BesureEndpointIsConnected();

        Console.WriteLine("Versuche das Gerät einzuschalten.");

        if (dev.IsTradfriGroup == true)
        {
            foreach (long currentId in dev.GroupDefinition.DeviceList.DevicesIds)
            {
                var tradfriDevice = (from d in DeviceList
                                     where d.Id == currentId
                                     select d).SingleOrDefault();
                SwitchOnDevice(tradfriDevice);
            }
        }
        else
        {
            client.UriPath = dev.Path;
            client.Put(@"{ ""3311"":[{ ""5850"":1}]}");
        }
    //    ep.Stop();
    } 

hope this helps a bit..

Greetz, Benjamin

Von: tomidix [mailto:notifications@github.com] Gesendet: Samstag, 25. November 2017 16:12 An: Com-AugustCellars/CoAP-CSharp CoAP-CSharp@noreply.github.com Cc: bmachuletz bmachuletz@mnetworx.de; Mention mention@noreply.github.com Betreff: Re: [Com-AugustCellars/CoAP-CSharp] Ikea Tradfri - Client Put is not working after a period of time (#43)

@bmachuletz https://github.com/bmachuletz I'm looking to do the same thing. Sort of a .net library which would communicate with TradFri gateway. I have a problem with dtls - I haven't found any example of how the package request should look. Can you help with the handshake, how to send the sn and secret to the gateway in coap request?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Com-AugustCellars/CoAP-CSharp/issues/43#issuecomment-346946327 , or mute the thread https://github.com/notifications/unsubscribe-auth/Af2Myb-qC1hMa_DscEgTi1S6EcCAGgvBks5s6C5YgaJpZM4QnSoC . https://github.com/notifications/beacon/Af2MyZ0CCbRch_mV6hRAtiU2-OIKmemrks5s6C5YgaJpZM4QnSoC.gif

davidwallis commented 6 years ago

@bmachuletz I have copied your code and finally managed to get some info back.. could you share your Tradfri device class, as I am unsure how you are using json serialiser to get the data ?

Thanks

David

dominicusmento commented 6 years ago

@bmachuletz First of all I want to thank you. I managed to connect successfully to tradfri gateway using your sample code. @davidwallis3101 you can use these python classes to get an idea about whats happening in the background - https://github.com/ggravlingen/pytradfri/tree/master/pytradfri I also think that it would be beneficial if we share the code and make it open source, like the python library. Nobody will lose, only the code can get better and have more features if the author could share so anyone can contribute. This way it puts us to the same position loosing the hours on something whats already written. I'd put my code but I'm at the same position as @davidwallis3101 . Still tracing and getting into this. If you are not into pushing the code to open source, I'll push mine as soon as I'll have something whats working anything useful.

davidwallis commented 6 years ago

I'm happy to share the repo I have - I am trying to make this a class library dll that I can then consume in the home automation system that I am using (also in c#)

bmachuletz commented 6 years ago

Hi David,

i have generated this class with json2csharp.com. Hope it helps… I’ll share my code on github after some houskeeping 😊

using System; using System.Collections.Generic; using Newtonsoft.Json; using HomeMagic.Shared;

namespace HomeMagic.Tradfri {

public partial class TradfriDevice : Device
{
    public bool IsTradfriGroup = false;
    private GroupDefinition internalGroupDefinition;

    public string Path { get; set; }

    [JsonProperty("9001")]
    public string TradfriDeviceName { get; set; }

    [JsonProperty("3311")]
    public TradfriLamp[] TradfriLamp { get; set; }

    [JsonProperty("3")]
    public DeviceInformation Information { get; set; }

    [JsonProperty("5750")]
    public long Unknown5750 { get; set; }

    [JsonProperty("9003")]
    public long Id { get; set; }

    [JsonProperty("9020")]
    public long Lastseen { get; set; }

    [JsonProperty("9002")]
    public long CreatedAt { get; set; }

    [JsonProperty("9019")]
    public long ReachableState { get; set; }

    [JsonProperty("9054")]
    public long OtaUpdatState { get; set; }

    [JsonProperty("9018")]
    public GroupDefinition GroupDefinition { get { return internalGroupDefinition; } set { IsTradfriGroup = true; internalGroupDefinition = value; } }
}

public partial class TradfriLamp
{
    [JsonProperty("5851")]
    public long Brightness { get; set; }

    [JsonProperty("5850")]
    public long State { get; set; }

    [JsonProperty("9003")]
    public long Id { get; set; }
}

public partial class DeviceInformation
{
    [JsonProperty("1")]
    public string Type { get; set; }

    [JsonProperty("3")]
    public string Version { get; set; }

    [JsonProperty("0")]
    public string Vendor { get; set; }

    [JsonProperty("2")]
    public string Unknown2 { get; set; }

    [JsonProperty("6")]
    public long Unknown6 { get; set; }
}

public partial class GroupDefinition
{
    [JsonProperty("15002")]
    public DeviceList DeviceList { get; set; }

}

public partial class DeviceList
{
    [JsonProperty("9003")]
    public List<long> DevicesIds { get; set; }
}

public partial class TradfriDevice
{
    public static TradfriDevice FromJson(string json)
    {
        return JsonConvert.DeserializeObject<TradfriDevice>(json, Converter.Settings);
    }
}

public static class Serialize
{
    public static string ToJson(this TradfriDevice self)
    {
        return JsonConvert.SerializeObject(self, Converter.Settings);
    }
}

public class Converter
{
    public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
        DateParseHandling = DateParseHandling.None,
    };
}

//    public TradfriDevice()
//    {
//    }

}

Greetz,

Benjamin

Von: David Wallis [mailto:notifications@github.com] Gesendet: Montag, 27. November 2017 22:56 An: Com-AugustCellars/CoAP-CSharp CoAP-CSharp@noreply.github.com Cc: bmachuletz bmachuletz@mnetworx.de; Mention mention@noreply.github.com Betreff: Re: [Com-AugustCellars/CoAP-CSharp] Ikea Tradfri - Client Put is not working after a period of time (#43)

@bmachuletz https://github.com/bmachuletz I have copied your code and finally managed to get some info back.. could you share your Tradfri device class, as I am unsure how you are using json serialiser to get the data ?

Thanks

David

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Com-AugustCellars/CoAP-CSharp/issues/43#issuecomment-347341845 , or mute the thread https://github.com/notifications/unsubscribe-auth/Af2MyfwB_HRcTmDh7oeM3c6qtvUhDL4pks5s6y_-gaJpZM4QnSoC . https://github.com/notifications/beacon/Af2MyWUIR4ry_20Vh34Xf2Z-7aL6tsKyks5s6y_-gaJpZM4QnSoC.gif

bmachuletz commented 6 years ago

I am also happy to share code with you. As soon my code is ready to go public I will share it on github.

Did anyone get the subscription to the events working so far?

Greetz,

Benjamin

Outlook for Android herunterladen

On Tue, Nov 28, 2017 at 10:55 AM +0100, "David Wallis" notifications@github.com wrote:

I'm happy to share the repo I have - I am trying to make this a class library dll that I can then consume in the home automation system that I am using (also in c#)

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

dominicusmento commented 6 years ago

@bmachuletz I'm refactoring my testing code right now so it can be used as some kind of backbone / library. It's not perfect but I'm looking to have a nice architecture so it can be built up on it as a nice library. Did not get deep into the features because I'm sure you are already some steps ahead. I also abandoned the idea of using .net core (which would be beneficial as it works on all platforms - mac/linux/win) because I had some problems running the Coap libraries on it. Right now my projects are on .net 4.7.1

P.S. I also used json2csharp although the visual studio has the same possibility, LOL

davidwallis commented 6 years ago

interesting! I might need a lower framework version as mine is used on a Rpi under mono.. but shouldnt be an issue.. had a quick play and looks good.. I did not know you could do a JSON property like that hence why I couldn't get my head around how to do the class and mapping 👍

Just working out a way of storing the encryption key without commiting it to github then I'll mark my repo as public too :)

Then will look to add some unit tests too

dominicusmento commented 6 years ago

@bmachuletz , @davidwallis3101 Ok, I think it's now good enough to be online: https://github.com/tomidix/CSharpTradFriLibrary If you are willing to help with it, make it better together etc. I'll add you as collaborators.. Just tell me

davidwallis commented 6 years ago

Thanks, happy to help where I can

davidwallis commented 6 years ago

incidently I now have your code working here and changing the bulb brightness, can you do the colour temp for the white bulbs?

bmachuletz commented 6 years ago

Very nice work. Currently I am porting my Alexa smart home Skill from v2 to v3. After that I will check your code more in depth. I have to backport it to .net 4.5 to replace my code with yours in order to get it work with  mono on my raspberry.

Outlook for Android herunterladen

On Wed, Nov 29, 2017 at 10:53 PM +0100, "David Wallis" notifications@github.com wrote:

incidently I now have your code working here and changing the bulb brightness, can you do the colour temp for the white bulbs?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

dominicusmento commented 6 years ago

@bmachuletz Ok, no problem take your time. Regarding backporting, I think we can do all that on my solution, I just started with the default (.net 4.7) and it worked straight away so I didn't mess with it.. I need it on a normal pc so I didn't bothered, but I don't have anything against using .net 4.5 and adding rpi support along with that. @davidwallis3101 Please give me the bulb exact number if you have it. I'm afraid that you might be hardware / firmware locked and that the bulb either wouldn't listen the command or it wouldn't be able to respect it due to hardware limitations.

@both I've added you both as the repository collaborators, so I think you should be able to make changes on the code itself and do a pull requests. You can also add another remote repository path if you want to have your own copy of it.

davidwallis commented 6 years ago

I can make the colour temp changes with the app and remote so must be possible, just need to see how.. will make a test app that polls the bulb to test if I can see any param's change, if not I will see if I can get wireshark to sniff and decode dtls encypted coap as people have said it is possible

dominicusmento commented 6 years ago

@davidwallis3101 @bmachuletz Do you maybe have an example code of eventListener (observer).. I've implemented color changes, moods, etc but I need eventListener to complete the feature branch and to merge it into the master.. Also there is a nuget available for you to use now, and it will be built automatically on very completed pull request to master.. https://www.nuget.org/packages/Tomidix.CSharpTradFriLibrary/

Hydro8 commented 6 years ago

@bmachuletz I try your code to connect to my gateway but it didn't work when I use IEnumerable resources = client.Discover();

bmachuletz commented 6 years ago

Hi Hydro8,

I dont't know you are doing wrong. As far as I know from the past I could break my code if I changed the order the commands. Please be sure that your Code has the same order.

Outlook for Android herunterladen

On Sun, Jan 14, 2018 at 8:53 PM +0100, "Hydro8" notifications@github.com wrote:

@bmachuletz I try your code to connect to my gateway but it didn't work when I use IEnumerable resources = client.Discover();

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.