Com-AugustCellars / CoAP-CSharp

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

Ikea Tradfri #23

Closed Hydro8 closed 7 years ago

Hydro8 commented 7 years ago

Hi Sorry for my question, I'm new on c#. I try to read your example to control my ikea tradfri system but I don't understand everything.

I use this as support https://learn.pimoroni.com/tutorial/sandyj/controlling-ikea-tradfri-lights-from-your-pi

This is my code for the moment Request request = Request.NewPut(); request.URI = new Uri("coap://[192:168:1:128]/"); request.Send();

How can I add extra informations to my put like they discribed in the article ?

Thank !

jimsch commented 7 years ago

Ok - to start with it is going to be easier for you if you use the class CoAP client as it will make it easier to do multiple messages in a row.

Second - some of you questions can be answered if you look at the example code in this project. It does many of the things that you are looking for.

The -u and -k options are used for DTLS. I have not found that the -u option is necessary when testing with my tradfri system. The code for dealing with this is going to be a) create a OneKey object which is going to hold the key b) create a DTLSClientEndpoint to say that you want to talk DTLS c) associate the DTLS endpoint with the request by setting the EndPoint property d) The payload, since it is a string, would go in the PayloadString property on the request but is an arguement to the put function for the CoapClient class.

jimsch commented 7 years ago

See https://github.com/jimsch/CoAP-CSharp/wiki/Ikea-Tradfri-Example

Hydro8 commented 7 years ago

Thanks it work great ! Do you have an idea how to change the color ? I try to change 5706 parameters but it doesn't work.

jimsch commented 7 years ago

Look at https://bitsex.net/software/2017/coap-endpoints-on-ikea-tradfri/

Hydro8 commented 7 years ago

Ok it works by changing all parameters thank for your help :)

Hydro8 commented 7 years ago

Do you know how I can serialize the list of the bulb obtain by .well-known/core ?

jimsch commented 7 years ago

Not sure what you are looking for. If you enumerate the links returned looking for a specific property you should be able to identify which ones are bulbs, which ones are groups and which ones are controllers. The link about should be able to help you distinguish which is which

Hydro8 commented 7 years ago

Yes I can find bulbs. My software will be a plugin to an home automation system.

Basically I want that users indicate the gateway_IP and my software find bulbs on it's own.

JYouren commented 7 years ago

In step #5 of your wiki page how does the command know which bulb to control?

JYouren commented 7 years ago

Ah, I see, the URL is set on the client object

Hydro8 commented 7 years ago

I use IEnumerable links = LinkFormat.Parse(response.PayloadString);

It work well but I can't access to Uri for example. This is the result of links [ { "Uri": "//15001/65536", "Attributes": { "Count": 2, "Keys": [ "obs", "ct" ], "Title": null, "Observable": true, "MaximumSizeEstimate": 0, "MaximumSizeEstimateString": null } }, { "Uri": "//15001/65537", "Attributes": { "Count": 2, "Keys": [ "obs", "ct" ], "Title": null, "Observable": true, "MaximumSizeEstimate": 0, "MaximumSizeEstimateString": null } }]

I'd like to be able to access to Uri only for each loop.

Do you know how to do it ?

jimsch commented 7 years ago
        IEnumerable<WebLink> items = client.Discover();

        foreach (var node in items) {
            Console.WriteLine($"Resource = {node}");

            client.Uri = new Uri($"coaps://{Server}/{node.Uri}");

            Response response = client.Get();

            Console.WriteLine("   Payload: " + response.PayloadString);
            Console.WriteLine();
        }
Hydro8 commented 7 years ago

Thanks a lot for your help ! However, I don't find a proper way to use it. I think I don't use it the right way, my code

` OneKey userKey = new OneKey(); userKey.Add(CoseKeyKeys.KeyType, GeneralValues.KeyType_Octet); userKey.Add(CoseKeyParameterKeys.Octet_k, CBORObject.FromObject(Encoding.UTF8.GetBytes("my_key")));

        CoAPEndPoint ep = new DTLSClientEndPoint(userKey);

        CoapClient client = new CoapClient(new Uri("coaps://192.168.1.128:5684/.well-known/core"))
        {
            EndPoint = ep
        };
        ep.Start();
        IEnumerable<WebLink> items = client.Discover();
        foreach (var node in items)
        {
            Console.WriteLine($"Resource = {node}");
            client.Uri = new Uri($"coaps://192.168.1.128:5684/{node.Uri}");
            Response response = client.Get();
            Console.WriteLine("   Payload: " + response.PayloadString);
            Console.WriteLine();
        }`
jimsch commented 7 years ago

I assume that you did switch the string "my_key" to the key on the controller.

jimsch commented 7 years ago

Remove the "/.well-known/core" from the URI. Discover will automatically add that.

jimsch commented 7 years ago

You don't need to add the port number, The "coaps" schema will automatically do that.

Hydro8 commented 7 years ago

I try with your informations but it doesn't work

` OneKey userKey = new OneKey(); userKey.Add(CoseKeyKeys.KeyType, GeneralValues.KeyType_Octet); userKey.Add(CoseKeyParameterKeys.Octet_k, CBORObject.FromObject(Encoding.UTF8.GetBytes(my_key)));

        CoAPEndPoint ep = new DTLSClientEndPoint(userKey);

        CoapClient client = new CoapClient(new Uri("coaps://192.168.1.128"))
        {
            EndPoint = ep
        };
        ep.Start();
        IEnumerable<WebLink> items = client.Discover();
        foreach (var node in items)
        {
            Console.WriteLine($"Resource = {node}");
            client.Uri = new Uri($"coaps://192.168.1.128/{node.Uri}");
            Response response = client.Get();
            Console.WriteLine("   Payload: " + response.PayloadString);
            Console.WriteLine();
        }`
jimsch commented 7 years ago

Where exactly is it failing.

Hydro8 commented 7 years ago

In my main software, when I try to launch this function (named List) I've got (sorry in french)

Unable to dispath the message List : Une exception a été levée par la cible d'un appel.

jimsch commented 7 years ago

Try inserting a Get for the /.well-known/core resource before the discovery and print the payload. Either it is not being parsed right or it is not being returned.

Hydro8 commented 7 years ago

Here my function ` OneKey userKey = new OneKey(); userKey.Add(CoseKeyKeys.KeyType, GeneralValues.KeyType_Octet); userKey.Add(CoseKeyParameterKeys.Octet_k, CBORObject.FromObject(Encoding.UTF8.GetBytes("my_key")));

        CoAPEndPoint ep = new DTLSClientEndPoint(userKey);

        CoapClient client = new CoapClient(new Uri("coaps://192.168.1.128"))
        {
            EndPoint = ep
        };
        ep.Start();

        client.Uri = new Uri("coaps://192.168.1.128:5684/.well-known/core");

        Response response2 = client.Get();
        IEnumerable links = LinkFormat.Parse(response2.PayloadString);
       foreach(var item in links)
         {
           Console.WriteLine(item);
          }

        IEnumerable<WebLink> items = client.Discover();
        foreach (var node in items)
        {
            Console.WriteLine($"Resource = {node}");

            client.Uri = new Uri($"coaps://192.168.1.128/{node.Uri}");

            Response response = client.Get();

        Console.WriteLine("   Payload: " + response.PayloadString);
        Console.WriteLine();
        }`

And the result

[MIDGARD_UI/Trådfri] 08:30:27 : <//15001/65536> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : <//15001/65537> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : <//15004/136834> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : <//15005/136834/217609> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : <//15005/136834/218326> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : <//15005/136834/224384> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : <//15005/136834> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : <//15001> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : <//15001/reset> ct: System.Collections.Generic.SynchronizedCollection1[System.String] [MIDGARD_UI/Trådfri] 08:30:27 : <//status> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : <//15005> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : <//15004> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : <//15004/add> ct: System.Collections.Generic.SynchronizedCollection1[System.String] [MIDGARD_UI/Trådfri] 08:30:27 : <//15004/remove> ct: System.Collections.Generic.SynchronizedCollection1[System.String] [MIDGARD_UI/Trådfri] 08:30:27 : <//15006> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : <//15011/15012> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : <//15011/9034> ct: System.Collections.Generic.SynchronizedCollection1[System.String] [MIDGARD_UI/Trådfri] 08:30:27 : <//15011/9030> ct: System.Collections.Generic.SynchronizedCollection1[System.String] [MIDGARD_UI/Trådfri] 08:30:27 : <//15011/9031> ct: System.Collections.Generic.SynchronizedCollection1[System.String] [MIDGARD_UI/Trådfri] 08:30:27 : <//15011/9063> ct: System.Collections.Generic.SynchronizedCollection1[System.String] [MIDGARD_UI/Trådfri] 08:30:27 : <//15011/9033> ct: System.Collections.Generic.SynchronizedCollection1[System.String] [MIDGARD_UI/Trådfri] 08:30:27 : <//15010> ct: System.Collections.Generic.SynchronizedCollection1[System.String] obs [MIDGARD_UI/Trådfri] 08:30:27 : Unable to dispath the message List : Une exception a été levée par la cible d'un appel.

jimsch commented 7 years ago

Please just put in a Console.WriteLine(respone2.PayloadString) before the parser starts. The enumerator is doing parsing on the fly and something in there is carshing.

Hydro8 commented 7 years ago

The result

<//15001/65536>;ct=0;obs,<//15001/65537>;ct=0;obs,<//15004/136834>;ct=0;obs,<//15005/136834/217609>;ct=0;obs,<//15005/136834/218326>;ct=0;obs,<//15005/136834/224384>;ct=0;obs,<//15005/136834>;ct=0;obs,<//15001>;ct= 0;obs,<//15001/reset>;ct=0,<//status>;ct=0;obs,<//15005>;ct=0;obs,<//15004>;ct=0;obs,<//15004/add>;ct=0,<//15004/remove>;ct=0,<//15006>;ct=0;obs,<//15011/15012>;ct=0;obs,<//15011/9034>;ct=0,<//15011/9030>;ct=0,<//15011/9031>;ct=0,<//15011/9063>;c t=0,<//15011/9033>;ct=0,<//15010>;ct=0;obs

jimsch commented 7 years ago

Based on the above post, I am wrong about where things are going off the rails. At this point I have no idea what is going on. Lets try and get some additional diagnositics and see if it helps to move forward.

Please do the following:

  1. Wrap a try/catch around the function and print out the exception information by just using Console.WriteLine("Exception information is: {0}", e);
  2. Turn on the internal coap logging. Insert the string "LogManager.Level = LogLevel.All;" If you do not setup a logger in the App.config file, it will dump to the console by default.

You might want to just email me the log file rather than putting it on github as it may be large and it will be easier to monkey with inside of emacs rather than on the screen.

jimsch commented 7 years ago

Just a note - to be clear, I want the stack for the exception.

Hydro8 commented 7 years ago

Ok I don't know if I'm right, I'm new to C# so here my function

` [MessageCallback] public void List() { OneKey userKey = new OneKey(); userKey.Add(CoseKeyKeys.KeyType, GeneralValues.KeyType_Octet); userKey.Add(CoseKeyParameterKeys.Octet_k, CBORObject.FromObject(Encoding.UTF8.GetBytes("my_key")));

        CoAPEndPoint ep = new DTLSClientEndPoint(userKey);

        CoapClient client = new CoapClient(new Uri("coaps://192.168.1.128"))
        {
            EndPoint = ep,

        };
        LogManager.Level = Com.AugustCellars.CoAP.Log.LogLevel.All;
        try
        {
            ep.Start();

            client.Uri = new Uri("coaps://192.168.1.128:5684/.well-known/core");

            Response response2 = client.Get();
            PackageHost.WriteError("{0}", response2.PayloadString);
        }
        catch (Exception ex)
        {
            PackageHost.WriteError("Exception information is: {0}.", ex.Message);
        }`

PackageHost.WriteError is a function to print the result to my main software, so here the result

<//15001/65536>;ct=0;obs,<//15001/65537>;ct=0;obs,<//15004/136834>;ct=0;obs,<//15005/136834/217609>;ct=0;obs,<//15005/136834/218326>;ct=0;obs,<//15005/136834/224384>;ct=0;obs,<//15005/136834>;ct=0;obs,<//15001>;ct= 0;obs,<//15001/reset>;ct=0,<//status>;ct=0;obs,<//15005>;ct=0;obs,<//15004>;ct=0;obs,<//15004/add>;ct=0,<//15004/remove>;ct=0,<//15006>;ct=0;obs,<//15011/15012>;ct=0;obs,<//15011/9034>;ct=0,<//15011/9030>;ct=0,<//15011/9031>;ct=0,<//15011/9063>;c t=0,<//15011/9033>;ct=0,<//15010>;ct=0;obs

The result doesn't change so maybe something is wrong in my code ?

jimsch commented 7 years ago

Except that I want the client.Discover function call and the enumeration inside of the try, that looks fine.

Hydro8 commented 7 years ago

I send you the result via email :)

jimsch commented 7 years ago

Ok - so the file you sent me did not have the same error as what you said you were having. With the unable to dispatch. I am not sure what to say as things appear to be working correctly. I think you need to try and narrow down you bug a bit more or perhaps share your code.

Hydro8 commented 7 years ago

I try to reduce my code, here what I use

` OneKey userKey = new OneKey(); userKey.Add(CoseKeyKeys.KeyType, GeneralValues.KeyType_Octet); userKey.Add(CoseKeyParameterKeys.Octet_k, CBORObject.FromObject(Encoding.UTF8.GetBytes("my_key")));

        CoAPEndPoint ep = new DTLSClientEndPoint(userKey);

        CoapClient client = new CoapClient(new Uri("coaps://192.168.1.128"))
        {
            EndPoint = ep,

        };
        LogManager.Level = Com.AugustCellars.CoAP.Log.LogLevel.All;
        try
        {
            ep.Start();

            client.Uri = new Uri("coaps://192.168.1.128:5684/.well-known/core");

           IEnumerable<WebLink> items = client.Discover();
             foreach (var node in items)
            {
           PackageHost.WriteInfo($"Resource = {node}");

            client.Uri = new Uri($"coaps://192.168.1.128/{node.Uri}");

            Response response = client.Get();

            PackageHost.WriteInfo("   Payload: " + response.PayloadString);
             PackageHost.WriteInfo("fin");
            }
        }
        catch (Exception ex)
        {
            PackageHost.WriteError("Exception information is: {0}.", ex.Message);
        }`

But I've got a new error

[MIDGARD_UI/Trådfri] 07:50:31 : Resource = <//15001/65536> ct: System.Collections.Generic.SynchronizedCollection`1[System.String] obs [MIDGARD_UI/Trådfri] 07:50:31 : Exception information is: Le format de la chaîne d'entrée est incorrect..

If I remove, it work I got the logs that I send you

client.Uri = new Uri($"coaps://192.168.1.128/{node.Uri}");

jimsch commented 7 years ago
  1. I am afraid I do not understand what you are adding and/or removing to either get or not get the error.
  2. As I noted above, I really want the stack for the exception not just the message.

I will note that I do not believe that there are any messages in my code that would produce a French string. This implies that the exception is probably not being thrown in my code. That is why a stack would be so useful.

Hydro8 commented 7 years ago

How do you obtain the stack ? Sorry I don't know c#.

Is it good if I use Exception.ToString() ?

jimsch commented 7 years ago

yes, as I noted above compare my print with yours

jimsch commented 7 years ago

You should also look at https://github.com/jimsch/CoAP-CSharp/wiki/Logging-Example for how to get my logging dumped someplace usable as the write to console is not working.

Hydro8 commented 7 years ago

I try

catch (Exception ex) { PackageHost.WriteError("Exception information is: {0}.", ex.ToString()); }

But I've got the same result. I read that you use Ikea Tradfri too. You don't need to loop through all available bulbs/groups ?

jimsch commented 7 years ago

I do not have any problem enumerating trough my bulbs and groups. I do not have any problems with doing observers on the bulb that I have. I have not however developed any type of application for it. It was just an easy thing to play with. If you look in the sandbox project that I have, you can see what my ikea code looks like. However, I will say that it is a mess because it is just things that I am playing with.

jimsch commented 7 years ago

Lots of documentation on line for this things - try https://msdn.microsoft.com/en-us/library/system.exception.stacktrace(v=vs.110).aspx

Hydro8 commented 7 years ago

I saw your sandbox and test your code, it works well ! I will test further but it seems ok now

Hydro8 commented 7 years ago

Ok so like I said it work well ! In node.Uri is it possible to separate type and id? For example node.Uri = //15001/65537 and I want to have 15001 et 65537 un two variables. I guess I can do it with string separate but if there is a way to do this with the library ? Thank for all your help !