C# thinger.io client


#1

Hi,

I intend build a client in asp.net. How I can make the calls using C#, you have some example?

Best,


#2

I can make a sample code for interacting with a device. Is this what you need? reading a sensor value, sending data to the device?

Bests!


#3

Yes, I intend to use Thinger API to get data in asp.net C# application and show this data in mvc or web forms.

Best,


#4

Ok, this should be easy!

Let me try that tomorrow. Will you require real-time updates in the interface, or just update the interface periodically, i.e., a minute? Depending on the use case it could be useful to use a websocket or an http request…


#5

Hi Alvaro, just update the interface periodically.

Thanks for help me.


#6

Ok, this is easy then. If you want to try it in the meanwhile, you can take a look at the request example that it is provided in the device api explorer (using curl) like

curl \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0ODg0MjI3MjQsImlhdCI6MTQ4ODQxNTUyNCwidXNyIjoiYWx2YXJvbGIifQ.iPiWWd3BqcQoPsTTXhSjJwPuVQ94LY2MR2ShnQxZpRo" \
  -H "Accept: application/json, text/plain, */*" \
  https://api.thinger.io/v2/users/alvarolb/devices/nodemcu/millis

I did yesterday a sample code just for R, that will be quite similar to C#

thingerReadDeviceResource <- function(username, device, resource, token){
  query <- paste("https://api.thinger.io/v2/users/", username, "/devices/", device, "/", resource, sep="")
  getdata<-GET(url=query, add_headers(Authorization=paste("Bearer ", token, sep="")))
  jsonContent <- content(getdata,type="text",encoding="UTF-8")
  result <- fromJSON(jsonContent)
  return(result$out)
}

Or a similar thing for Node.js

function device_request(username, device, resource, data, auth, res){
  var https = require("https");
  var body = JSON.stringify(data);
  var options = {
    hostname: 'api.thinger.io',
    port: 443,
    path: '/v2/users/' + username + '/devices/' + device + '/' + resource,
    method: data ? 'POST' : 'GET',
    headers: {
        'Authorization': 'Bearer ' + auth,
        'Accept': 'application/json, text/plain, */*',
        'Content-Type' : 'application/json;charset=UTF-8',
        'Content-Length': Buffer.byteLength(body)
    }
  };
  var req = https.request(options, function(res) {
    res.setEncoding('utf8');
    res.on('data', function (body) {
      console.log('Response: ' + body);
    });
  });
  req.on('error', function(e) {
    console.log('problem with request: ' + e.message);
  });
  req.write(body);
  req.end();
};

// example for sending a false to a resource
device_request( "username", "device", "resource", {"in":false}, "token", function(res) {
    res.setEncoding('utf8');
    res.on('data', function (body) {
      console.log('Response: ' + body);
    });
});

#7

Hi Alvaro, If you can help me with C# code for this.

Thanks,


#8

Thanks Alvaro,

I use RESTSharp API and this works:

     var client = new RestClient("https://api.thinger.io/v2/users/matheusefranco/devices/");
        var request = new RestRequest("wemos/lux", Method.GET);
        request.AddHeader("content-type", "application/json;charset=UTF-8");
        request.AddHeader("Authorization", "Bearer XXX"); 
        IRestResponse response = client.Execute(request);
        TextBox1.Text = response.Content;

#9

Hi Alvaro,

I try execute POST command, but I received this return:
{“error”:{“message”:“invalid content type”}}

See my code:

        var client = new   RestClient("https://api.thinger.io/v2/users/matheusefranco/devices/");
        var request = new RestRequest("wemos/led", Method.POST);
        request.AddParameter("in", true);
        request.AddHeader("content-type", "application/json;charset=UTF-8");
        request.AddHeader("Authorization", "Bearer XX"); 
        IRestResponse response = client.Execute(request);
        TextBox1.Text = response.Content;

Best,


#10

Now works, I change AddParameter:

    request.AddParameter("application/json", "{\"in\":true}", ParameterType.RequestBody);

rather than
request.AddParameter(“in”, true);


#11

Nice you get it working! :slight_smile:


#12

nice, thanks for the tip… is there a way to get back the current state of a switch in HTTP request (rather than set its state)?


#13

Just use the same REST endpoint, but instead of issuing a POST request, just send a GET request without body. If your resource is defined correctly, it should return the current state.

Best.


#14

thanks for coming back to me.

I guess, If this is a digital pin for example that would work…

in this instance I need to fire a method to do what I need to do on the request.

eg:

thing[“switch4”] << [](pson& in) {
control.toggle(4, in ? 1 : 0);
};

if I just do a GET (without any body) to switch4, it actually triggers the method with a false
Also the response from the api is just {}

I tried using an IN and OUT thingy and keeping state:

bool thing4state = false;
thing[“switch4”] = [](pson& in, pson& out){
if(in.is_empty()){
in = thing4state;
}
else{
control.toggle(4, in ? 1 : 0);
thing4state= in;
}
out = thing4state;
};

but this ends up creating like ‘two’ switch refernces in the API explorer, although it does allow me to query the state when I want without firing the control.toggle method.

I also just tried like the documentation:

thing[“switch4”] << [](pson& in){
if(in.is_empty()){
in = thing4state;
}
else{
control.toggle(4, in ? 1 : 0);
thing4state = in;
}
}

Is there a tidier way to do this so I can have what looks to thinger like a simple:

thing[“led”] << digitalPin(BUILTIN_LED);

but is firing a method (and keeping state of a variable) rather than reading/writing a digital pin?


#15

Yes, there is another way for doing that. Suppose that you have a variable in your sketch that need to change and also get. You can define a method like:

// outside setup or loop
int hysteresisVar = 0;

// in your setup
thing["hysteresis"] << inputValue(hysteresisVar, {
    // execute some code when the value change
    Serial.println("Hystereis changed to: ");
    Serial.print(hysteresisVar);
});

This way, the GET request will get the current method of hysteresisVar, meanwhile a POST request will modify its value, and also execute the code. Is this what you need?

Take a look to http://docs.thinger.io/arduino/#coding-easier-resources-modify-sketch-variables


#16

thanks again for your reply.

yes, that’s the functionality I am after for sure… I have tested this and the POST is working and firing the method using the inputValue OK and turning my widget on and off.

But, I just can’t get the value itself back using a GET. I have tried on the command line CURL in Linux and a Windows C# app I am working on (that gets the JSON response OK when I am using an outputValue).

eg: thing[“test3state”] >> outputValue(test3Var); - this gives me a JSON response from CURL or using my Windows C# call. eg: {“out”: false}

when I use the same GET method (but specify the device in question), I just get {} back from the API…
I also get this with the LED example - thing[“led”] << digitalPin(LED_BUILTIN); - just a {} response

to confirm, here is my updated code using your example:

thing[“test3”] << inputValue(test3Var, {
control.toggle(4, test3Var ? 1 : 0);
Serial.print(test3Var);
});

Also, to confirm this is on premise server implementation.


#17

Hi again! :wink:

the resource test3 you have defined is good. Please, can you post your POST and GET methods over this resource? The GET method should return the current value. In fact, you can test if the resource is returning the current value with the API explorer by refreshing the API once setting the value. So, change the value, refresh the device API, and check what is the current value in the api explorer. If it returns the latest value, then, the resource is working fine.

Hope that helps!


#18

Response Body in API Explorer is also { } on a POST or GET


#19

ahh, sussed it running trace in chrome when API Explorer page loads…

need to add /api on to the end of the GET request to get JSON result, otherwise querying the same URL as the POST method just returns {}

eg:

GET https://thingerurl/v2/users/myuser/devices/mydevice/test3/api?authorization=ey
returns { “in”: true/false }

Where as:
GET https://thingerurl/v2/users/myuser/devices/mydevice/test3?authorization=ey
returns {}


#20

Nice! I forgot the /api part! Anyway, I think that in future revisions it can make sense to be able to query an input resource without the /api. Will check that option…