Node-RED: Interpreting REST service URL - json

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"
]
]
}
]

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.

Related

JSON Parsing a Plain Text File

I have a lot of data I need to parse though.
I need to pull all pid's and price's.
`
[
{
"id": 159817,
"price": "10.69",
"stocked": true,
"store": {
"id": 809,
"nsn": "22036-0",
"pricingSource": "manual",
"lastUpdated": "2022-12-05T15:24:33.908Z"
},
"sharedFields": {
"type": "PRODUCT",
"id": 24549,
"pid": "12079",
"labels": [
{
"type": "default",
"value": "Chicken Sandwich",
"locale": "en"
},
{
"type": "fresh",
"value": "Chicken",
"locale": "en"
},
{
"type": "product_json",
"value": "Chicken",
"locale": "en"
}
],
"calMin": 600,
"calMax": 600,
"lastUpdated": "2021-12-31T13:49:22.794Z"
}
},
{
"id": 159818,
"price": "9.29",
"stocked": true,
"store": {
"id": 809,
"nsn": "22036-0",
"pricingSource": "manual",
"lastUpdated": "2022-12-05T15:24:33.908Z"
},
"sharedFields": {
"type": "PRODUCT",
"id": 25,
"pid": "1",
"labels": [
{
"type": "default",
"value": "Ham Sandwich",
"locale": "en"
},
{
"type": "fresh",
"value": "Ham",
"locale": "en"
}
],
"calMin": 540,
"calMax": 540,
"lastUpdated": "2021-07-09T19:30:00.326Z"
}
}
]
`
and I need to place them into a string like this, but on a scale of 150 products. I'd also need to change "pid" to "productId"
[{ "productId": "46238", "price": 6.09 }, { "productId": "40240", "price": 1.49 }]
I need to add a string before this data, but I'm pretty confident I can figure that part out.
I am pretty open to the easiest suggestion, whether that be VBS, Excel macro, etc.

How to change Shape and Color of points in Vega Scatter Plot?

I have a scatter plot generated with contours code in Vega.
Plot looks like
Based on 3rd field, differentiated the points with colour as Blue and Green Dots, but couldn't see the difference very clearly.
Is it possible to Change the Shape and Colour (atleast one) of the points to make the difference more visible
Code
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"title": {
"text": "Outlier Distribution between Duration Vs Age",
"anchor": "middle",
"fontSize": 16,
"frame": "group",
"offset": 4
},
"signals": [
{
"name": "bandwidth", "value": 0.5,
"bind": {"input": "range", "min": -1, "max": 1, "step": 0.1}
}
],
"data": [
{
"name": "source",
"url" : {
"index": "tenant_id.model_training_artefact",
"body": {
"size":10000,
"_source": ["duration", "credit_amount", "asnm", "age", "outlier"]
}
}
"format": {"property": "hits.hits"},
},
{
"name": "density",
"source": "source",
"transform": [
{
"type": "kde2d",
"groupby": ["_source.outlier"],
"size": [{"signal": "width"}, {"signal": "height"}],
"x": {"expr": "scale('x', datum.duration)"},
"y": {"expr": "scale('y', datum.age)"},
"bandwidth": {"signal": "[bandwidth, bandwidth]"}
}
]
},
{
"name": "contours",
"source": "density",
"transform": [
{
"type": "isocontour",
"field": "grid",
"levels": 4
}
]
}
],
"scales": [
{
"name": "x",
"type": "linear",
"round": true,
"nice": true,
"zero": true,
"domain": {"data": "source", "field": "_source.duration"},
"range": "width"
},
{
"name": "y",
"type": "linear",
"round": true,
"nice": true,
"zero": true,
"domain": {"data": "source", "field": "_source.age"},
"range": "height"
},
{
"name": "color",
"type": "ordinal",
"domain": {
"data": "source", "field": "_source.outlier",
"sort": {"order": "descending"}
},
"range": "category"
}
],
"axes": [
{
"scale": "x",
"grid": true,
"domain": false,
"orient": "bottom",
"tickCount": 5,
"title": "Duration"
},
{
"scale": "y",
"grid": true,
"domain": false,
"orient": "left",
"titlePadding": 5,
"title": "Age"
}
],
"legends": [
{"stroke": "color", "symbolType": "stroke"}
],
"marks": [
{
"name": "marks",
"type": "symbol",
"from": {"data": "source"},
"encode": {
"update": {
"x": {"scale": "x", "field": "_source.duration"},
"y": {"scale": "y", "field": "_source.age"},
"size": {"value": 50},
"fill": {"scale": "color" , "field": "_source.outlier"}
}
}
},
{
"type": "image",
"from": {"data": "density"},
"encode": {
"update": {
"x": {"value": 0},
"y": {"value": 0},
"width": {"signal": "width"},
"height": {"signal": "height"},
"aspect": {"value": false}
}
},
"transform": [
{
"type": "heatmap",
"field": "datum.grid",
"color": {"expr": "scale('color', datum.datum.outlier)"}
}
]
},
{
"type": "path",
"clip": true,
"from": {"data": "contours"},
"encode": {
"enter": {
"strokeWidth": {"value": 1},
"strokeOpacity": {"value": 1},
"stroke": {"scale": "color", "field": "outlier"}
}
},
"transform": [
{ "type": "geopath", "field": "datum.contour" }
]
}
]
}
Try defining scales for mark symbol color, shape and size.
For example, assuming your field outlier has 3 possible values:
"scales": [
...
{
"name": "scale_symbol_color",
"type": "ordinal",
"domain": {
"data": "source", "field": "_source.outlier",
"sort": {"order": "descending"}
},
"range": ["red", "orange", "blue"]
},
{
"name": "scale_symbol_shape",
"type": "ordinal",
"domain": {
"data": "source", "field": "_source.outlier",
"sort": {"order": "descending"}
},
"range": ["triangle", "square", "circle"]
},
{
"name": "scale_symbol_size",
"type": "ordinal",
"domain": {
"data": "source", "field": "_source.outlier",
"sort": {"order": "descending"}
},
"range": [400, 300, 200]
}
],
...
"marks": [
{
"name": "marks",
"type": "symbol",
"from": {"data": "source"},
"encode": {
"update": {
"x": {"scale": "x", "field": "_source.duration"},
"y": {"scale": "y", "field": "_source.age"},
"size": {"value": 50},
"fill": {"scale": "scale_symbol_color" , "field": "_source.outlier"},
"shape": {"scale": "scale_symbol_shape" , "field": "_source.outlier"},
"size": {"scale": "scale_symbol_size" , "field": "_source.outlier"},
}
}
},
...
Vega docs:
https://vega.github.io/vega/docs/scales/#ordinal
https://vega.github.io/vega/docs/marks/symbol/

AWS Cloudformation YML File with Embedded JSON Strong for Dashboard Body

Trying to make our dashboard as code while using CloudFormation. Getting an error while validating template with the embedded JSON String inside the YML File. It is having problems with the "SEARCH('{AWS/EC2,InstanceId) fields saying those are invalid strings. I have ran it through a JSON Linter and works fine. I have also deployed the CloudWatch Dashboard console just fine with the JSON.
Question:
Is there anyway to just wrap this section as a string for CloudFormation in the YML file so it doesn't get tripped up on the JSON string contents?
Example:
DetailedDashboard:
Type: "AWS::CloudWatch::Dashboard"
Properties:
DashboardName: "DetailedDashboard"
DashboardBody: !Sub
...,
{
"type": "metric",
"x": 6,
"y": 18,
"width": 6,
"height": 6,
"properties": {
"metrics": [
[ { "expression": "SEARCH('{AWS/EC2,InstanceId} NetworkIn', 'Average', 300)", "id": "network_in", "period": 300, "region": "us-east-1", "label": "net_in" } ],
[ { "expression": "SEARCH('{AWS/EC2,InstanceId} NetworkOut', 'Average', 300)", "id": "network_out", "period": 300, "region": "us-east-1", "label": "net_out" } ]
],
"view": "timeSeries",
"stacked": false,
"region": "us-east-1",
"title": "Network in/out by Host",
"stat": "Average",
"period": 300,
"yAxis": {
"left": {
"label": "bytes"
}
}
}
},
DetailedDashboard:
Type: 'AWS::CloudWatch::Dashboard'
Properties:
DashboardName: 'DetailedDashboard'
DashboardBody: !Sub |
{
"type": "metric",
"x": 6,
"y": 18,
"width": 6,
"height": 6,
"properties": {
"metrics": [
[ { "expression": "SEARCH('{AWS/EC2,InstanceId} NetworkIn', 'Average', 300)", "id": "network_in", "period": 300, "region": "us-east-1", "label": "net_in" } ],
[ { "expression": "SEARCH('{AWS/EC2,InstanceId} NetworkOut', 'Average', 300)", "id": "network_out", "period": 300, "region": "us-east-1", "label": "net_out" } ]
],
"view": "timeSeries",
"stacked": false,
"region": "us-east-1",
"title": "Network in/out by Host",
"stat": "Average",
"period": 300,
"yAxis": {
"left": {
"label": "bytes"
}
}
}
},

How do I insert an ip address into mysql

good morning
im new to node red and javascript so this may be a simple issue im having
im trying to insert an ip address into a mysql table
in mysql i set the field to varchar(20)
9/28/2019, 9:08:38 AMnode: 7bfc4d89.726dbc
msg : error
"Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '[object Object])' at line 1"
the basic flows are as follows:
[
{
"id": "df624ad9.0db0f8",
"type": "function",
"z": "661acf87.d0306",
"name": "Defining inside ip",
"func": "global.set(\"inside_ip\",msg.payload);\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 530,
"y": 120,
"wires": [
[]
]
},
{
"id": "400e4f07.42965",
"type": "inject",
"z": "661acf87.d0306",
"name": "",
"topic": "",
"payload": "",
"payloadType": "date",
"repeat": "1",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"x": 190,
"y": 120,
"wires": [
[
"f3f24f92.29582"
]
]
},
{
"id": "f3f24f92.29582",
"type": "ip",
"z": "661acf87.d0306",
"name": "ip",
"https": false,
"timeout": "5000",
"internalIPv4": true,
"internalIPv6": false,
"publicIPv4": false,
"publicIPv6": false,
"x": 330,
"y": 120,
"wires": [
[
"df624ad9.0db0f8"
]
]
},
{
"id": "47202c3d.71ebfc",
"type": "inject",
"z": "661acf87.d0306",
"name": "",
"topic": "",
"payload": "1",
"payloadType": "num",
"repeat": "1",
"crontab": "",
"once": true,
"onceDelay": "5",
"x": 230,
"y": 180,
"wires": [
[
"20c745e0.57fb2a"
]
]
},
{
"id": "7bfc4d89.726dbc",
"type": "mysql",
"z": "661acf87.d0306",
"mydb": "ca2479e3.1dda58",
"name": "",
"x": 510,
"y": 180,
"wires": [
[]
]
},
{
"id": "20c745e0.57fb2a",
"type": "function",
"z": "661acf87.d0306",
"name": "",
"func": "msg.topic =\"INSERT INTO`node`(`inside_ip`) VALUES(\" + global.get(\"inside_ip\") + \")\";\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"x": 350,
"y": 180,
"wires": [
[
"7bfc4d89.726dbc"
]
]
},
{
"id": "ca2479e3.1dda58",
"type": "MySQLdatabase",
"z": "",
"host": "72.90.182.40",
"port": "3306",
"db": "mysql_test",
"tz": "eastern"
}
]
However
if i set the "ip" like this it works:
[
{
"id": "1f5e06b6.76e931",
"type": "function",
"z": "87908bbe.239128",
"name": "Defining inside ip",
"func": "global.set(\"inside_ip\",msg.payload);\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 645,
"y": 228,
"wires": [
[]
]
},
{
"id": "4dd624b5.e58f34",
"type": "inject",
"z": "87908bbe.239128",
"name": "",
"topic": "",
"payload": "",
"payloadType": "date",
"repeat": "1",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"x": 305,
"y": 228,
"wires": [
[
"b9528c26.ceca2"
]
]
},
{
"id": "b9528c26.ceca2",
"type": "ip",
"z": "87908bbe.239128",
"name": "ip",
"https": false,
"timeout": "5000",
"internalIPv4": true,
"internalIPv6": false,
"publicIPv4": false,
"publicIPv6": false,
"x": 445,
"y": 228,
"wires": [
[]
]
},
{
"id": "215d3000.15a8b8",
"type": "inject",
"z": "87908bbe.239128",
"name": "",
"topic": "",
"payload": "1",
"payloadType": "num",
"repeat": "1",
"crontab": "",
"once": true,
"onceDelay": "5",
"x": 345,
"y": 288,
"wires": [
[
"fdcd98f2.a35838"
]
]
},
{
"id": "17946cb4.862c23",
"type": "mysql",
"z": "87908bbe.239128",
"mydb": "59bd1ef5.938c2",
"name": "",
"x": 625,
"y": 288,
"wires": [
[]
]
},
{
"id": "fdcd98f2.a35838",
"type": "function",
"z": "87908bbe.239128",
"name": "",
"func": "msg.topic =\"INSERT INTO`node`(`inside_ip`) VALUES(\" + global.get(\"inside_ip\") + \")\";\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"x": 465,
"y": 288,
"wires": [
[
"17946cb4.862c23"
]
]
},
{
"id": "a248bafe.b02ac",
"type": "inject",
"z": "87908bbe.239128",
"name": "",
"topic": "",
"payload": "\"192.168.1.1\"",
"payloadType": "str",
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"x": 341,
"y": 145,
"wires": [
[
"1f5e06b6.76e931"
]
]
},
{
"id": "59bd1ef5.938c2",
"type": "MySQLdatabase",
"z": "",
"host": "72.90.182.40",
"port": "3306",
"db": "mysql_test",
"tz": "eastern"
}
]
any advise would be great
regards mike
Okay so the IP node you are using returns the following in msg.payload
{"internalIPv4":"192.168.1.107"}
For you to be able to save it to the database you need to crop the:
({"internalIPv4":" and "}
there are a couple of ways to do this by using the function node.
The first, one is to replace the unnecessary string with nothing (this is my way to go!)
var str = JSON.stringify(msg.payload)
var ip = str.replace('{"internalIPv4":"', '');
ip = ip.replace('"}', '')
msg.payload = ip
return msg;
The second method is to crop by character number
var str = JSON.stringify(msg.payload)
var ip = str.substring(17,30 );
msg.payload = ip
return msg;
The problem with this code is if the length of your IP changes, possibly one number from IP will be missing.
Both of these functions return me the same message (first is before function, the second is after)
{"internalIPv4":"192.168.1.107"}
"192.168.1.107"
Four more hints on your small project:
1. No need to send the SQL query every second.
Better use some unique identifier (if running on raspberry pi use its serial number to identify which IP is for what device)
Add UNIQUE key on MYSQL for the IP addresses
Where you cant use", use ' (especially in fitting data in a MySQL query)
Hope I helped!

Pulling values from a csv file in JSON [SyntaxError: Unexpected token a in JSON at position 0]

I'm using VEGA with the code at the bottom of this post. The code works fine when I manually specify values for a, b, c and d.
Now I'm trying to change the code so that rather than manually specifying the values for a-d, it reads it from a csv file [which looks like this:
[
However my problem is that the graph fails to display any info, instead I get the following error in chrome's console:
This is my configuration file:
{
"$schema": "https://vega.github.io/schema/vega/v4.json",
"width": 400,
"padding": 5,
"autosize": "pad",
"data": [
{
"url": "data/summary3.csv",
"name": "tuples",
"transform": [
{
"type": "aggregate",
"groupby": ["a", "b", "d"],
"fields": ["c"],
"ops": ["average"],
"as": ["c"]
}
]
},
{
"name": "trellis",
"source": "tuples",
"transform": [
{"type": "aggregate", "groupby": ["a"]},
{
"type": "formula",
"as": "span",
"expr": "rangeStep * bandspace(datum.count, innerPadding, outerPadding)"
},
{"type": "stack", "field": "span"},
{"type": "extent", "field": "y1", "signal": "trellisExtent"}
]
}
],
"legends": [
{"fill": "color", "orient": "right", "title": "Objective Categories"}
],
"signals": [
{"name": "rangeStep", "value": 20},
{"name": "innerPadding", "value": 0.1},
{"name": "outerPadding", "value": 0.2},
{"name": "height", "update": "trellisExtent[1]"},
{"name": "colors", "value": ["#1f77b4", "#2ca02c", "#ff7f0e", "#1f77b4"]}
],
"scales": [
{
"name": "xscale",
"domain": {"data": "tuples", "field": "c"},
"nice": true,
"zero": true,
"round": true,
"range": "width"
},
{
"name": "color",
"type": "ordinal",
"range": {"signal": "colors"},
"domain": {"data": "trellis", "field": "a"}
}
],
"axes": [
{
"orient": "bottom",
"scale": "xscale",
"title": "Percent complete",
"ticks": true,
"labels": true,
"grid": true,
"domain": true
}
],
"marks": [
{
"type": "group",
"from": {
"data": "trellis",
"facet": {"name": "faceted_tuples", "data": "tuples", "groupby": "a"}
},
"encode": {
"enter": {"x": {"value": 0}, "width": {"signal": "width"}},
"update": {"y": {"field": "y0"}, "y2": {"field": "y1"}}
},
"scales": [
{
"name": "yscale",
"type": "band",
"paddingInner": {"signal": "innerPadding"},
"paddingOuter": {"signal": "outerPadding"},
"round": true,
"domain": {"data": "faceted_tuples", "field": "b"},
"range": {"step": {"signal": "rangeStep"}}
}
],
"axes": [
{
"orient": "left",
"scale": "yscale",
"ticks": false,
"domain": false,
"labelPadding": 4
}
],
"marks": [
{
"type": "rect",
"from": {"data": "faceted_tuples"},
"encode": {
"enter": {
"x": {"value": 0},
"x2": {"scale": "xscale", "field": "c"},
"fill": {"scale": "color", "field": "a"},
"strokeWidth": {"value": 2},
"tooltip": {"field": "d"},
"hover": {"fill": {"value": "red"}}
},
"update": {
"y": {"scale": "yscale", "field": "b"},
"height": {"scale": "yscale", "band": 1},
"stroke": {"value": null},
"zindex": {"value": 0}
},
"hover": {"stroke": {"value": "firebrick"}, "zindex": {"value": 1}}
}
}
]
}
]
}
Your example works if you add "format": {"type":"csv"} into the spec after line 9, i.e.
...
"name": "tuples",
"format": {"type":"csv"},
"transform": [
{
...
The error message is saying it's trying to parse the csv file as json. I'm not sure why it doesn't auto detect from the file extension like it does in vega lite, but it looks from the docs like this is expected behaviour:
https://vega.github.io/vega/docs/data/#format