Saturday, June 4, 2016

WIO Link - HTTP Requests from Node-RED


Seeedstudio deployed two exchange servers that expose APIs for communicating with WioLink boards. I am using the international server from US and can tell you that the response time is awesome.

https://us.wio.seeed.io
https://cn.wio.seeed.io


There is a comprehensive API guide on Seedstudio webpage. It can be visited by clicking on this link.


I will share some flows that I have used to test the communication via API.

When testing API is very helpful to use a tool like postman or insomnia

You will need a running Node-RED instance and again I suggest you to try FRED to keep things easy. I will assume you already have a WIO Link board online with some Grove module connected. For this post I am using the temperature and humidity sensor.

I have built flows to test 8 different APIs and all of them works in the same general way:

An inject node will launch the flow.
A function node will prepare the required properties in the msg object.
The  HTTP Request node will send the requests to the exchange server.
The result will be displayed in the debug node of Node-RED and also sent via Dweet to allow you to better visualize the results in a web page.




I remind you that it is necessary to use two different tokens when playing with WioLink APIs.  One of them is the user token and is required by some APIs (Eg. to log in, retrieve the password and change the password). The other token is the node token and it is used by the APIs that read and write to the Grove modules (sensors and actuators).

The first flow depicted above will test the API "User Login". As a result, it will provide the user token that was assigned when you created your login in the app (Android or IOS).  This user token will be stored in a global variable in Node-RED. Storing the token will make easier testing another API´s.

In order to test your WioLink board with these flows, you will need to modify the parameters in the dialog box of the inject node "email + password" by using the same data that you informed when configuring your board in the app.






The second flow will test the API "Node List" that lists the WIO Link boards configured under your account. This flow also stores the node token of the first WIO Link (the flow need to be modified if you have more than one WioLink board).

Before you can test the other flows you must first trigger these two initial flows. The reason, like I said before, is that we need to store the user token and the node token before using the next flows. You can play with the flows and modify them to suit your purposes and, if you want, you can hardcode your tokens in the nodes.

The next three flows require the user token and will test the APIs: Boards List, Scan Drivers, and Scan status. Note that the Scan Drivers result in a quite long reply and therefore it will not work with Dweet that limits the payload of the message to 2.000  characters.

The following two APIs are: Node config and Node .well known.

Finally, the last API test the temperature and humidity sensor.



Understanding the nodes used in the flows:

Node-RED can easily access WIO Link exchange servers (in fact any HTTP server) thanks to the function node "HTTP Request".



My choice was not to configure the parameters in the dialog box of the HTTP Request node. When we leave the parameters blank in the configuration box it means that the node expects to receive a msg object from the previous node with some properties configured in advance.

Those properties are:
msg.url
msg.method
msg.headers
msg.payload



Below picture shows that "HTTP Request" dialog boxes have not been configured.




In my flows, I have inserted a  "function" node before each  "HTTP Request" node. Those function nodes are responsible to set up the msg properties with the right values.


Below picture shows how the function node is configured for one of the flows. Note the way to set up and read global variables in Node-RED by using the functions: global.set() and global.get().





Using Dweet.io  is straightforward. The good thing about this environment is that it requires no login and not set up. You just send the information to their servers and read the results in a web browser.

I configured the Dweet node as below.


In such case, I will read the results on this link:

https://dweet.io/get/latest/dweet/for/my-wio

You better to select another "Thing" name, instead of "my-wio" to avoid getting confused by reading my own dweets.


See the results I got from Dweet for the APIs:



{"this":"succeeded","by":"getting","the":"dweets","with":[{"thing":"my-wio","created":"2016-06-04T22:07:48.193Z","content":{"token":"PPxxPQlS7gwSLfwsQyYO9ZxRwq9EuLodP2swG2SpNsaY","user_id":1829}}]}













{"this":"succeeded","by":"getting","the":"dweets","with":[{"thing":"my-wio","created":"2016-06-04T22:11:04.226Z","content":{"nodes":[{"name":"AIOT","node_key":"a1adldfa6dc7726333d49962dde5599b","node_sn":"1c754d28816062345523164b75ccd147","dataxserver":null,"board":"Wio Link v1.0","online":true}]}}]}












{"this":"succeeded","by":"getting","the":"dweets","with":[{"thing":"my-wio","created":"2016-06-04T21:51:16.758Z","content":{"boards":[{"board_flash_spi_mode":"QIO","board_builtin":{"FUNCTION_KEY":0,"STATUS_LED":2,"GROVE_POWER_SWITCH":15},"interfaces":{"UART0":{"pintx":1,"pinrx":3,"type":"UART"},"D2":{"type":"GPIO","pin":13},"A0":{"type":"ANALOG","pin":17},"I2C0":{"pinscl":5,"type":"I2C","pinsda":4},"D0":{"type":"GPIO","pin":14},"D1":{"type":"GPIO","pin":12}},"board_name":"Wio Link v1.0","board_flash_map":6,"board_vendor":"seeedstudio","board_flash_spi_speed":40},{"board_flash_spi_mode":"QIO","board_builtin":{"FUNCTION_KEY":0,"STATUS_LED":2,"GROVE_POWER_SWITCH":15},"interfaces":{"A0":{"type":"ANALOG","pin":17},"UART0":{"pintx":1,"pinrx":3,"type":"UART"},"I2C0":{"pinscl":3,"type":"I2C","pinsda":1},"I2C1":{"pinscl":5,"type":"I2C","pinsda":4},"D0":{"type":"GPIO","pin":3},"D1":{"type":"GPIO","pin":5}},"board_name":"Wio Node v1.0","board_flash_map":6,"board_vendor":"seeedstudio","board_flash_spi_speed":40}]}}]}










This one will not work with Dweet since the payload size is greater than 2.000 characters.










{"this":"succeeded","by":"getting","the":"dweets","with":[{"thing":"my-wio","created":"2016-06-04T21:54:54.005Z","content":{"msg":"scanned 42 grove drivers at 2016-05-12 11:21:59.295065","result":"OK"}}]}












{"this":"succeeded","by":"getting","the":"dweets","with":[{"thing":"my-wio","created":"2016-06-04T21:55:52.127Z","content":{"type":"json","config":{"board_name":"Wio Link v1.0","connections":[{"sku":"101020019-ffff","port":"D0"}]}}}]}











{"this":"succeeded","by":"getting","the":"dweets","with":[{"thing":"my-wio","created":"2016-06-04T21:58:04.302Z","content":{"name":"AIOT","well_known":["GET /v1/node/GroveTempHumD0/humidity -> float humidity","GET /v1/node/GroveTempHumD0/temperature -> float celsius_degree","GET /v1/node/GroveTempHumD0/temperature_f -> float fahrenheit_degree"]}}]}











{"this":"succeeded","by":"getting","the":"dweets","with":[{"thing":"my-wio","created":"2016-06-04T21:59:07.684Z","content":{"celsius_degree":20}}]}





















Below the JSON with the flows. You can copy and import to Node-RED.











[{"id":"d77c9afc.66f178","type":"inject","z":"2f43f52c.5f5eba","name":"email+password","topic":"","payload":"email=xxx@xxx&password=yyy","payloadType":"str","repeat":"","crontab":"","once":false,"x":146.10226440429688,"y":90.20169067382812,"wires":[["35cc64fc.0c5f3c"]]},{"id":"39f3afa1.0bfa4","type":"debug","z":"2f43f52c.5f5eba","name":"","active":true,"console":"false","complete":"true","x":887.0994110107422,"y":41.090911865234375,"wires":[]},{"id":"35cc64fc.0c5f3c","type":"function","z":"2f43f52c.5f5eba","name":"User Login","func":"msg.url=\"https://iot.seeed.cc/v1/user/login?\"+msg.payload;\nmsg.payload=\" \";\nmsg.method=\"POST\";\nreturn msg;","outputs":1,"noerr":0,"x":313.95738220214844,"y":90.87786865234375,"wires":[["a0a29e6.54e686"]]},{"id":"a0a29e6.54e686","type":"http request","z":"2f43f52c.5f5eba","name":"HTTP Request","method":"use","ret":"obj","url":"","x":523.0994110107422,"y":91.09091186523438,"wires":[["76d6cb8d.d7bcb4"]]},{"id":"1fa972fe.cad82d","type":"inject","z":"2f43f52c.5f5eba","name":"Fire","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"x":125.99995422363281,"y":194.20172119140625,"wires":[["e82a22f.d7e69e"]]},{"id":"e82a22f.d7e69e","type":"function","z":"2f43f52c.5f5eba","name":"Node List","func":"msg.url=\"https://iot.seeed.cc/v1/nodes/list\"; \nmsg.method=\"GET\";\nmsg.headers = {\"Authorization\": global.get(\"user_token\")};\nmsg.payload=\"\";\nreturn msg;","outputs":1,"noerr":0,"x":313.8550720214844,"y":194.87789916992188,"wires":[["9b70d42a.11d4c8"]]},{"id":"9b70d42a.11d4c8","type":"http request","z":"2f43f52c.5f5eba","name":"HTTP Request","method":"use","ret":"obj","url":"","x":530.9970550537109,"y":194.0909423828125,"wires":[["c18e05ff.5ad8c8"]]},{"id":"cfd92133.b8422","type":"debug","z":"2f43f52c.5f5eba","name":"","active":true,"console":"false","complete":"true","x":777.0964508056641,"y":413.9801330566406,"wires":[]},{"id":"6852da9c.f3efc4","type":"function","z":"2f43f52c.5f5eba","name":"User Boards List","func":"msg.url=\"https://iot.seeed.cc/v1/boards/list\"; \nmsg.method=\"GET\";\nmsg.headers = {\"Authorization\": global.get(\"user_token\")};\nmsg.payload=\"\";\nreturn msg;","outputs":1,"noerr":0,"x":320.95448303222656,"y":271.7670593261719,"wires":[["2a30e96d.cf13a6"]]},{"id":"2a30e96d.cf13a6","type":"http request","z":"2f43f52c.5f5eba","name":"HTTP Request","method":"use","ret":"obj","url":"","x":532.0964508056641,"y":271.9801025390625,"wires":[["cfd92133.b8422","eddeb56c.30a548"]]},{"id":"e828c101.e7271","type":"function","z":"2f43f52c.5f5eba","name":"User Scan Drivers","func":"msg.url=\"https://iot.seeed.cc/v1/scan/drivers\"; \nmsg.method=\"GET\";\nmsg.headers = {\"Authorization\": global.get(\"user_token\")};\nmsg.payload=\"\";\nreturn msg;","outputs":1,"noerr":0,"x":320.95448303222656,"y":340.7670593261719,"wires":[["79a9a182.e4043"]]},{"id":"79a9a182.e4043","type":"http request","z":"2f43f52c.5f5eba","name":"HTTP Request","method":"use","ret":"obj","url":"","x":532.0964508056641,"y":339.9801025390625,"wires":[["eddeb56c.30a548","cfd92133.b8422"]]},{"id":"27a0aad2.8ce846","type":"function","z":"2f43f52c.5f5eba","name":"User Scan Status","func":"msg.url=\"https://iot.seeed.cc/v1/scan/status\"; \nmsg.method=\"GET\";\nmsg.headers = {\"Authorization\": global.get(\"user_token\")};\nmsg.payload=\"\";\nreturn msg;","outputs":1,"noerr":0,"x":323.95448303222656,"y":401.76708984375,"wires":[["6e5938c4.1591e8"]]},{"id":"6e5938c4.1591e8","type":"http request","z":"2f43f52c.5f5eba","name":"HTTP Request","method":"use","ret":"obj","url":"","x":530.0964508056641,"y":398.9801330566406,"wires":[["eddeb56c.30a548","cfd92133.b8422"]]},{"id":"6fdb1ba7.a01fc4","type":"function","z":"2f43f52c.5f5eba","name":"Node Config","func":"msg.url=\"https://iot.seeed.cc/v1/node/config\"; \nmsg.method=\"GET\";\nmsg.headers = {\"Authorization\": global.get(\"node_token\")};\nmsg.payload=\"\";\nreturn msg;","outputs":1,"noerr":0,"x":303.9545135498047,"y":493.76702880859375,"wires":[["b848318f.d6a42"]]},{"id":"b848318f.d6a42","type":"http request","z":"2f43f52c.5f5eba","name":"HTTP Request","method":"use","ret":"obj","url":"","x":534.0965118408203,"y":493.9801330566406,"wires":[["eddeb56c.30a548","cfd92133.b8422"]]},{"id":"ec87119f.0731f","type":"function","z":"2f43f52c.5f5eba","name":"Node .well-known","func":"msg.url=\"https://iot.seeed.cc/v1/node/.well-known\"; \nmsg.method=\"GET\";\nmsg.headers = {\"Authorization\": global.get(\"node_token\")};\nreturn msg;","outputs":1,"noerr":0,"x":321.8550567626953,"y":547.7670593261719,"wires":[["11ef70ee.f734df"]]},{"id":"11ef70ee.f734df","type":"http request","z":"2f43f52c.5f5eba","name":"HTTP Request","method":"use","ret":"obj","url":"","x":527.9970550537109,"y":548.9801330566406,"wires":[["eddeb56c.30a548","cfd92133.b8422"]]},{"id":"76d6cb8d.d7bcb4","type":"function","z":"2f43f52c.5f5eba","name":"Store user_token","func":"global.set(\"user_token\",msg.payload.token)\nreturn msg;","outputs":1,"noerr":0,"x":720.9516448974609,"y":89.78408813476562,"wires":[["39f3afa1.0bfa4","106b92ce.32fa4d"]]},{"id":"c18e05ff.5ad8c8","type":"function","z":"2f43f52c.5f5eba","name":"Store node_token","func":"global.set(\"node_token\",\"token \"+msg.payload.nodes[0].node_key);\nreturn msg;","outputs":1,"noerr":0,"x":724.0994110107422,"y":194.09091186523438,"wires":[["106b92ce.32fa4d","ad821c7c.a8c1f"]]},{"id":"f9597e64.eedbb","type":"inject","z":"2f43f52c.5f5eba","name":"Fire","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"x":123.09939575195312,"y":270.9090881347656,"wires":[["6852da9c.f3efc4"]]},{"id":"81cc9ced.dea8","type":"inject","z":"2f43f52c.5f5eba","name":"Fire","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"x":128.09939575195312,"y":340.9090576171875,"wires":[["e828c101.e7271"]]},{"id":"541385e7.66308c","type":"inject","z":"2f43f52c.5f5eba","name":"Fire","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"x":127.09939575195312,"y":403.9090576171875,"wires":[["27a0aad2.8ce846"]]},{"id":"4d3c0e41.e1ab9","type":"inject","z":"2f43f52c.5f5eba","name":"Fire","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"x":133.0994110107422,"y":494.9090576171875,"wires":[["6fdb1ba7.a01fc4"]]},{"id":"fffcf9c2.159ec8","type":"inject","z":"2f43f52c.5f5eba","name":"Fire","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"x":133.0994110107422,"y":548.9090576171875,"wires":[["ec87119f.0731f"]]},{"id":"eddeb56c.30a548","type":"dweetio out","z":"2f43f52c.5f5eba","thing":"my-wio","name":"Dweet ","x":774.9515838623047,"y":365.9062805175781,"wires":[]},{"id":"4a72d4bd.dd359c","type":"function","z":"2f43f52c.5f5eba","name":"Grove Temperature","func":"msg.url=\"https://iot.seeed.cc/v1/node/GroveTempHumD0/temperature\"; \nmsg.method=\"GET\";\nmsg.headers = {\"Authorization\": global.get(\"node_token\")};\nreturn msg;","outputs":1,"noerr":0,"x":319.75563049316406,"y":610.8181762695312,"wires":[["f0eec6d0.24c798"]]},{"id":"f0eec6d0.24c798","type":"http request","z":"2f43f52c.5f5eba","name":"HTTP Request","method":"use","ret":"obj","url":"","x":525.8976287841797,"y":612.03125,"wires":[["c9304765.1d5a98","c9aa3db2.8f90a"]]},{"id":"319b9cb3.10f4a4","type":"inject","z":"2f43f52c.5f5eba","name":"Fire","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"x":130.99998474121094,"y":611.9601745605469,"wires":[["4a72d4bd.dd359c"]]},{"id":"c9aa3db2.8f90a","type":"debug","z":"2f43f52c.5f5eba","name":"","active":true,"console":"false","complete":"true","x":787.0994110107422,"y":639.8181762695312,"wires":[]},{"id":"c9304765.1d5a98","type":"dweetio out","z":"2f43f52c.5f5eba","thing":"my-wio","name":"Dweet","x":784.9545440673828,"y":591.7443237304688,"wires":[]},{"id":"106b92ce.32fa4d","type":"dweetio out","z":"2f43f52c.5f5eba","thing":"my-wio","name":"Dweet ","x":902.0994110107422,"y":133.09091186523438,"wires":[]},{"id":"ad821c7c.a8c1f","type":"debug","z":"2f43f52c.5f5eba","name":"","active":true,"console":"false","complete":"true","x":893.9970550537109,"y":220.0909423828125,"wires":[]}]


1 comment:

Unknown said...

This is great work! I just started using Node-RED recently and I've put together a set of nodes that should make the integration with Grove modules a bit more streamlined and user friendly. No need to copy and paste urls, tokens, or construct the requests manually.

https://github.com/WarriorRocker/node-red-contrib-wio-seeed

Looking for feedback and/or people who would like to contribute. Let me know what you think!