Search code examples
jsonibm-cloudiotnode-red

Node-RED: Interpreting REST service URL


I am currently using the IBM Bluemix IoT Quickstart for some experiments. For those of you who don't know this, it is an IoT Sensor simulator that can be used to control temperature and humidity values.

I am looking to use a web service connector to look for the temperature reading. How would I go about interpreting the Service URL for this?

Also (but not as important!) I see that the website /test/ fails to display the temperature reading. Any ideas as to why?

Below is the json to be used by web service to display temperature

[
  {
    "id": "e42c6f27.46cca",
    "type": "function",
    "z": "3ed49b1f.4c1164",
    "name": "temp",
    "func": "return {payload:msg.payload.d.temp};",
    "outputs": 1,
    "noerr": 0,
    "x": 422.5,
    "y": 775,
    "wires": [
      [
        "c76cd036.bc2ba"
      ]
    ]
  },
  {
    "id": "f47256cd.a18b78",
    "type": "template",
    "z": "3ed49b1f.4c1164",
    "name": "",
    "field": "payload",
    "fieldType": "msg",
    "format": "handlebars",
    "syntax": "mustache",
    "template": "The temperature is\n{{payload}}\n",
    "output": "str",
    "x": 775,
    "y": 953,
    "wires": [
      [
        "22b54d74.028ae2"
      ]
    ]
  },
  {
    "id": "22b54d74.028ae2",
    "type": "http response",
    "z": "3ed49b1f.4c1164",
    "name": "",
    "statusCode": "",
    "headers": {

    },
    "x": 1064,
    "y": 955,
    "wires": [

    ]
  },
  {
    "id": "243d218a.fe14ae",
    "type": "http in",
    "z": "3ed49b1f.4c1164",
    "name": "",
    "url": "test",
    "method": "get",
    "upload": false,
    "swaggerDoc": "",
    "x": 432,
    "y": 993,
    "wires": [
      [
        "f47256cd.a18b78"
      ]
    ]
  },
  {
    "id": "429ffb9e.7ed404",
    "type": "ibmiot in",
    "z": "3ed49b1f.4c1164",
    "authentication": "quickstart",
    "apiKey": "",
    "inputType": "evt",
    "deviceId": "3bd1c8df5ed2",
    "applicationId": "",
    "deviceType": "iotqs-sensor",
    "eventType": "+",
    "commandType": "",
    "format": "json",
    "name": "IBM IoT App In",
    "service": "quickstart",
    "allDevices": false,
    "allApplications": false,
    "allDeviceTypes": true,
    "allEvents": true,
    "allCommands": false,
    "allFormats": false,
    "x": 269,
    "y": 550,
    "wires": [
      [
        "55064d15.005804",
        "c34674a2.7ea0d8",
        "2356b867.1c3d68",
        "c7ee16c4.493fc8",
        "e42c6f27.46cca"
      ]
    ]
  },
  {
    "id": "55064d15.005804",
    "type": "debug",
    "z": "3ed49b1f.4c1164",
    "name": "name",
    "active": true,
    "complete": "payload.d.name",
    "x": 717.5,
    "y": 551,
    "wires": [

    ]
  },
  {
    "id": "c34674a2.7ea0d8",
    "type": "debug",
    "z": "3ed49b1f.4c1164",
    "name": "Temperature",
    "active": true,
    "complete": "payload.d.temp",
    "x": 717.5,
    "y": 651,
    "wires": [

    ]
  },
  {
    "id": "2356b867.1c3d68",
    "type": "debug",
    "z": "3ed49b1f.4c1164",
    "name": "Humidity",
    "active": true,
    "complete": "payload.d.humidity",
    "x": 717.5,
    "y": 751,
    "wires": [

    ]
  },
  {
    "id": "c7ee16c4.493fc8",
    "type": "debug",
    "z": "3ed49b1f.4c1164",
    "name": "Object Temperature",
    "active": true,
    "complete": "payload.d.objectTemp",
    "x": 717.5,
    "y": 851,
    "wires": [

    ]
  },
  {
    "id": "c76cd036.bc2ba",
    "type": "json",
    "z": "3ed49b1f.4c1164",
    "name": "",
    "pretty": true,
    "x": 531,
    "y": 894,
    "wires": [
      [
        "f47256cd.a18b78"
      ]
    ]
  }
]

Solution

  • There are a few issues with this flow:

    • the JSON node is not necessary, since the msg.payload is already json
    • the output readings from the iot node were being sent to the http response node, which is only needed when the flow is returning results from the API call
    • the output from the http in node contains no msg.payload, so the template node has nothing to format

    Here is a different approach, that I believe gives you what you need:

    • store the output object msg.payload.d into a flow context variable called "lastReadings"
    • use the http in node with url /last/:type as the api endpoint to retrieve the last value for the given sensor type (if you have node-red-node-swagger installed, you can test the endpoint directly from the right-hand sidebar)
    • use a switch node to route the api call, based on the sensor type, to retrieve the last reading and return the output string through the http response node

    A couple things to note: if your settings.js includes either an httpRoot or httpNodeRoot url prefix, this will preceed your api url -- this is probably why you got no results when trying to access the url "http://localhost:1880/test/". Check the notes on the http in node for something like this:

    The url will be relative to /red.

    in which case you would need to use the api url "http://localhost:1880/red/test/"

    Here is the flow I created, along with an inject node for testing your values (since I don't have the ibmiot input node available):

    [
    {
        "id": "5ebe7dff.780724",
        "type": "template",
        "z": "7299298e.a9f058",
        "name": "output value",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "mustache",
        "template": "Last {{sensor}} reading:\n{{payload}}\n",
        "output": "str",
        "x": 630,
        "y": 720,
        "wires": [
            [
                "cb13c651.0ef458",
                "efabaec0.9bd7a"
            ]
        ]
    },
    {
        "id": "cb13c651.0ef458",
        "type": "http response",
        "z": "7299298e.a9f058",
        "name": "",
        "statusCode": "",
        "headers": {},
        "x": 790,
        "y": 760,
        "wires": []
    },
    {
        "id": "361c51b4.f519ae",
        "type": "http in",
        "z": "7299298e.a9f058",
        "name": "",
        "url": "/last/:type",
        "method": "get",
        "upload": false,
        "swaggerDoc": "59b72c5b.bc0fb4",
        "x": 150,
        "y": 640,
        "wires": [
            [
                "c2fb1169.b76e8",
                "61234f00.7faf1"
            ]
        ]
    },
    {
        "id": "884f3eb9.e22be",
        "type": "debug",
        "z": "7299298e.a9f058",
        "name": "payload.d values",
        "active": true,
        "console": "false",
        "complete": "payload.d",
        "x": 470,
        "y": 480,
        "wires": []
    },
    {
        "id": "fef6db49.919728",
        "type": "comment",
        "z": "7299298e.a9f058",
        "name": "Save the last readings to flow context",
        "info": "",
        "x": 210,
        "y": 440,
        "wires": []
    },
    {
        "id": "81bfb514.a63348",
        "type": "change",
        "z": "7299298e.a9f058",
        "name": "save readings",
        "rules": [
            {
                "t": "set",
                "p": "lastReadings",
                "pt": "flow",
                "to": "payload.d",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 460,
        "y": 520,
        "wires": [
            []
        ]
    },
    {
        "id": "9573eab5.84e548",
        "type": "comment",
        "z": "7299298e.a9f058",
        "name": "API endpoints to retrieve sensor values",
        "info": "",
        "x": 210,
        "y": 600,
        "wires": []
    },
    {
        "id": "c2fb1169.b76e8",
        "type": "switch",
        "z": "7299298e.a9f058",
        "name": "sensor type",
        "property": "req.params.type",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "temp",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "humidity",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "objectTemp",
                "vt": "str"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "outputs": 4,
        "x": 250,
        "y": 700,
        "wires": [
            [
                "4eb4657b.cd0b0c"
            ],
            [
                "801c0b28.320308"
            ],
            [
                "a7833d28.f58f"
            ],
            [
                "e30f26ce.a084b8"
            ]
        ]
    },
    {
        "id": "4eb4657b.cd0b0c",
        "type": "change",
        "z": "7299298e.a9f058",
        "name": "Temperature",
        "rules": [
            {
                "t": "set",
                "p": "sensor",
                "pt": "msg",
                "to": "Temperature",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "lastReadings.temp",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 450,
        "y": 680,
        "wires": [
            [
                "5ebe7dff.780724"
            ]
        ]
    },
    {
        "id": "801c0b28.320308",
        "type": "change",
        "z": "7299298e.a9f058",
        "name": "Humidity",
        "rules": [
            {
                "t": "set",
                "p": "sensor",
                "pt": "msg",
                "to": "Humidity",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "lastReadings.humidity",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 440,
        "y": 720,
        "wires": [
            [
                "5ebe7dff.780724"
            ]
        ]
    },
    {
        "id": "a7833d28.f58f",
        "type": "change",
        "z": "7299298e.a9f058",
        "name": "Object Temp",
        "rules": [
            {
                "t": "set",
                "p": "sensor",
                "pt": "msg",
                "to": "Object Temp",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "lastReadings.objectTemp",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 450,
        "y": 760,
        "wires": [
            [
                "5ebe7dff.780724"
            ]
        ]
    },
    {
        "id": "61234f00.7faf1",
        "type": "debug",
        "z": "7299298e.a9f058",
        "name": "API params",
        "active": false,
        "console": "false",
        "complete": "true",
        "x": 450,
        "y": 640,
        "wires": []
    },
    {
        "id": "efabaec0.9bd7a",
        "type": "debug",
        "z": "7299298e.a9f058",
        "name": "API out",
        "active": true,
        "console": "false",
        "complete": "payload",
        "x": 800,
        "y": 720,
        "wires": []
    },
    {
        "id": "b019dd18.1806e",
        "type": "inject",
        "z": "7299298e.a9f058",
        "name": "test values",
        "topic": "",
        "payload": "{\"d\":{\"temp\":21,\"humidity\":69,\"objectTemp\":\"NA\"}}",
        "payloadType": "json",
        "repeat": "",
        "crontab": "",
        "once": false,
        "x": 150,
        "y": 520,
        "wires": [
            [
                "81bfb514.a63348",
                "884f3eb9.e22be"
            ]
        ]
    },
    {
        "id": "e30f26ce.a084b8",
        "type": "change",
        "z": "7299298e.a9f058",
        "name": "invalid type",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "Error! Unknown sensor type...",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 450,
        "y": 800,
        "wires": [
            [
                "cb13c651.0ef458"
            ]
        ]
    },
    {
        "id": "e02d2f38.842d8",
        "type": "ibmiot in",
        "z": "7299298e.a9f058",
        "authentication": "quickstart",
        "apiKey": "",
        "inputType": "evt",
        "deviceId": "3bd1c8df5ed2",
        "applicationId": "",
        "deviceType": "iotqs-sensor",
        "eventType": "+",
        "commandType": "",
        "format": "json",
        "name": "IBM IoT App In",
        "service": "quickstart",
        "allDevices": false,
        "allApplications": false,
        "allDeviceTypes": true,
        "allEvents": true,
        "allCommands": false,
        "allFormats": false,
        "x": 150,
        "y": 480,
        "wires": [
            [
                "884f3eb9.e22be",
                "81bfb514.a63348"
            ]
        ]
    },
    {
        "id": "59b72c5b.bc0fb4",
        "type": "swagger-doc",
        "z": "",
        "summary": "Retrieve last sensor reading",
        "description": "",
        "tags": "",
        "consumes": "",
        "produces": "",
        "parameters": [
            {
                "name": "type",
                "in": "path",
                "description": "Sensor type",
                "required": true,
                "type": "string"
            }
        ],
        "responses": {},
        "deprecated": false
    }
    ]
    

    Please note that I changed the api url to use /last/{type} syntax... where {type} is replaced by the name of the field in your msg.payload.d object.