├── docs └── img │ ├── ui.png │ └── nodes.png ├── README.md └── iot-device-simulator.json /docs/img/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farmassistX/farmassist-iot-device-simulator/HEAD/docs/img/ui.png -------------------------------------------------------------------------------- /docs/img/nodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farmassistX/farmassist-iot-device-simulator/HEAD/docs/img/nodes.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Farmassist IoT Device Simulator 2 | 3 | *[Ray Jasson](mailto:holmesqueen2070@yahoo.com)*
4 | *31/01/2021*
5 | 6 |
7 | 8 | ## :satellite: IoT Device Simulation 9 | 10 | This is a minimal IoT device simulator built using [Node-RED](https://nodered.org/). It sends telemetry data to [Firebase Realtime Database](https://firebase.google.com/docs/database) for Farmassist app. There are 5 types of telemetry data: 11 | - Air Humidity (%) 12 | - Air Temperature (°C) 13 | - Soil Moisture (%) 14 | - Soil pH (pH) 15 | - Soil Salinity (Millisiemens/cm) 16 | 17 |

18 |

Connected Nodes in Node-RED editor

19 | 20 |
21 | 22 |

23 |

UI Dashboard of the IoT Device Simulator

24 | 25 |
26 | 27 | ## :computer: How to Run the IoT Device Simulator 28 | 29 | The IoT device simulator is a Node-RED flow stored using JSON. The functions are written in JavaScript. 30 | 31 | ### Run the Node-RED flow locally 32 | 33 | - To run the simulator locally, you will need a supported version of Node.js and Node-RED editor. 34 | - To install Node.js, download the recent version from [here](https://nodejs.org/en/download/). 35 | - To install Node-RED editor, run: 36 | ``` 37 | npm install -g --unsafe-perm node-red 38 | ``` 39 | - Open Node-RED editor by running: 40 | ``` 41 | node-red start 42 | ``` 43 | - Open [http://localhost:1880](http://localhost:1880) to view the editor in the browser. 44 | - 2 extra node modules: `node-red-dashboard` and `node-red-contrib-firebase-data`, are required to run the simulator. `node-red-dashboard` is used to create a dashboard, whereas `node-red-contrib-firebase-data` is used to connect the nodes to Firebase Realtime Database. To install them, run: 45 | ``` 46 | npm install node-red-dashboard 47 | npm install node-red-contrib-firebase-data 48 | ``` 49 | - Download the JSON file and import it into the Node-RED editor. You will see the import option at the upper-right corner of the editor. 50 | 51 | ### Customize the simulator 52 | 53 | - You need to add your Realtime Database URL into the configuration node. You can find the URL in the Realtime Database section of your Firebase console. The configuration node :gear: is located at the third option in the right panel. 54 | - Double-click `Add Firebase` node to configure your Firebase URL and set the child path to where the telemetry data is stored in the database. Also, there are several methods for you to write data into Realtime Database, for example, `set`, `push` or `update`. The default method in the JSON file is `update`. 55 | - Remember to click "Deploy" to save your configurations. 56 | - Open the dashboard, and use the sliders to select the range of the telemetry data you would want to send. 57 | - Toggle the switch to start/stop sending the telemetry data. 58 | 59 |
60 | 61 | ## :black_nib: References 62 | 63 | - [A YouTube tutorial teaching you how to build a Node-RED IoT Device Simulator](https://www.youtube.com/watch?v=2GcVvD08nGE) 64 | - [Reference for types of telemetry data from Microsoft Azure Virtual Hackathon 2020 in Asia Pacific](https://news.microsoft.com/apac/2020/08/20/drones-data-science-and-innovation-at-the-microsoft-azure-virtual-hackathon-in-asia-pacific/) -------------------------------------------------------------------------------- /iot-device-simulator.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "bb155f83.a4277", 4 | "type": "tab", 5 | "label": "main", 6 | "disabled": false, 7 | "info": "" 8 | }, 9 | { 10 | "id": "7f15f7f9.621a48", 11 | "type": "subflow", 12 | "name": "airTemperature", 13 | "info": "", 14 | "category": "", 15 | "in": [{ "x": 320, "y": 340, "wires": [{ "id": "1624d34d.8c440d" }] }], 16 | "out": [ 17 | { "x": 900, "y": 340, "wires": [{ "id": "13b9c3ef.f5db2c", "port": 0 }] } 18 | ], 19 | "env": [], 20 | "color": "#DDAA99" 21 | }, 22 | { 23 | "id": "5d3f7c11.023534", 24 | "type": "subflow", 25 | "name": "airHumidity", 26 | "info": "", 27 | "category": "", 28 | "in": [{ "x": 320, "y": 340, "wires": [{ "id": "c620f442.386f18" }] }], 29 | "out": [ 30 | { "x": 900, "y": 340, "wires": [{ "id": "ed27784e.86a9d8", "port": 0 }] } 31 | ], 32 | "env": [], 33 | "color": "#DDAA99" 34 | }, 35 | { 36 | "id": "41719d6c.3cfb44", 37 | "type": "subflow", 38 | "name": "soilMoisture", 39 | "info": "", 40 | "category": "", 41 | "in": [{ "x": 320, "y": 340, "wires": [{ "id": "66d8b839.f565a8" }] }], 42 | "out": [ 43 | { "x": 900, "y": 340, "wires": [{ "id": "d0abdcdc.837d", "port": 0 }] } 44 | ], 45 | "env": [], 46 | "color": "#DDAA99" 47 | }, 48 | { 49 | "id": "f9d383cb.41058", 50 | "type": "subflow", 51 | "name": "soilpH", 52 | "info": "", 53 | "category": "", 54 | "in": [{ "x": 320, "y": 340, "wires": [{ "id": "a841f15a.dfbdf" }] }], 55 | "out": [ 56 | { "x": 880, "y": 340, "wires": [{ "id": "bdca0114.d69de", "port": 0 }] } 57 | ], 58 | "env": [], 59 | "color": "#DDAA99" 60 | }, 61 | { 62 | "id": "7a111b85.eca174", 63 | "type": "subflow", 64 | "name": "soilSalinity", 65 | "info": "", 66 | "category": "", 67 | "in": [{ "x": 320, "y": 340, "wires": [{ "id": "578fce88.15de5" }] }], 68 | "out": [ 69 | { "x": 860, "y": 340, "wires": [{ "id": "f33a2102.a728", "port": 0 }] } 70 | ], 71 | "env": [], 72 | "color": "#DDAA99" 73 | }, 74 | { 75 | "id": "74df1345.04015c", 76 | "type": "firebaseCertificate", 77 | "z": "", 78 | "firebaseurl": "", 79 | "loginType": "none" 80 | }, 81 | { 82 | "id": "8c5b05a2.ccb108", 83 | "type": "ui_base", 84 | "theme": { 85 | "name": "theme-light", 86 | "lightTheme": { 87 | "default": "#0094CE", 88 | "baseColor": "#4a8a3d", 89 | "baseFont": "Arial,Arial,Helvetica,sans-serif", 90 | "edited": true, 91 | "reset": false 92 | }, 93 | "darkTheme": { 94 | "default": "#097479", 95 | "baseColor": "#097479", 96 | "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", 97 | "edited": false 98 | }, 99 | "customTheme": { 100 | "name": "Untitled Theme 1", 101 | "default": "#4B7930", 102 | "baseColor": "#4B7930", 103 | "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" 104 | }, 105 | "themeState": { 106 | "base-color": { 107 | "default": "#0094CE", 108 | "value": "#4a8a3d", 109 | "edited": true 110 | }, 111 | "page-titlebar-backgroundColor": { 112 | "value": "#4a8a3d", 113 | "edited": false 114 | }, 115 | "page-backgroundColor": { "value": "#fafafa", "edited": false }, 116 | "page-sidebar-backgroundColor": { "value": "#ffffff", "edited": false }, 117 | "group-textColor": { "value": "#6cb75c", "edited": false }, 118 | "group-borderColor": { "value": "#ffffff", "edited": false }, 119 | "group-backgroundColor": { "value": "#ffffff", "edited": false }, 120 | "widget-textColor": { "value": "#111111", "edited": false }, 121 | "widget-backgroundColor": { "value": "#4a8a3d", "edited": false }, 122 | "widget-borderColor": { "value": "#ffffff", "edited": false }, 123 | "base-font": { "value": "Arial,Arial,Helvetica,sans-serif" } 124 | }, 125 | "angularTheme": { 126 | "primary": "indigo", 127 | "accents": "blue", 128 | "warn": "red", 129 | "background": "grey" 130 | } 131 | }, 132 | "site": { 133 | "name": "IoT Device Simulator", 134 | "hideToolbar": "false", 135 | "allowSwipe": "false", 136 | "lockMenu": "false", 137 | "allowTempTheme": "true", 138 | "dateFormat": "DD/MM/YYYY", 139 | "sizes": { 140 | "sx": 48, 141 | "sy": 48, 142 | "gx": 6, 143 | "gy": 6, 144 | "cx": 6, 145 | "cy": 6, 146 | "px": 0, 147 | "py": 0 148 | } 149 | } 150 | }, 151 | { 152 | "id": "d82b4e88.7d197", 153 | "type": "ui_tab", 154 | "z": "", 155 | "name": "IoT Device Simulator", 156 | "icon": "dashboard", 157 | "order": 1, 158 | "disabled": false, 159 | "hidden": false 160 | }, 161 | { 162 | "id": "a1f71297.5b069", 163 | "type": "ui_group", 164 | "z": "", 165 | "name": "Simulation Control", 166 | "tab": "d82b4e88.7d197", 167 | "order": 1, 168 | "disp": true, 169 | "width": "25", 170 | "collapse": false 171 | }, 172 | { 173 | "id": "5d47cc2.fe17834", 174 | "type": "ui_group", 175 | "z": "", 176 | "name": "Air Temperature", 177 | "tab": "d82b4e88.7d197", 178 | "order": 3, 179 | "disp": true, 180 | "width": "5", 181 | "collapse": false 182 | }, 183 | { 184 | "id": "856d803c.8b0cc", 185 | "type": "ui_group", 186 | "z": "", 187 | "name": "Air Humidity", 188 | "tab": "d82b4e88.7d197", 189 | "order": 2, 190 | "disp": true, 191 | "width": "5", 192 | "collapse": false 193 | }, 194 | { 195 | "id": "b9c3ab84.f017f8", 196 | "type": "ui_group", 197 | "z": "", 198 | "name": "Soil Moisture", 199 | "tab": "d82b4e88.7d197", 200 | "order": 4, 201 | "disp": true, 202 | "width": "5", 203 | "collapse": false 204 | }, 205 | { 206 | "id": "99a1466b.ac8278", 207 | "type": "ui_group", 208 | "z": "", 209 | "name": "Soil pH", 210 | "tab": "d82b4e88.7d197", 211 | "order": 5, 212 | "disp": true, 213 | "width": "5", 214 | "collapse": false 215 | }, 216 | { 217 | "id": "bc339738.e6a1e8", 218 | "type": "ui_group", 219 | "z": "", 220 | "name": "Soil Salinity", 221 | "tab": "d82b4e88.7d197", 222 | "order": 6, 223 | "disp": true, 224 | "width": "5", 225 | "collapse": false 226 | }, 227 | { 228 | "id": "13f27471.8ac73c", 229 | "type": "ui_spacer", 230 | "name": "spacer", 231 | "group": "91dd813.4ee908", 232 | "order": 8, 233 | "width": "0", 234 | "height": "0" 235 | }, 236 | { 237 | "id": "bb58c10d.e7b37", 238 | "type": "ui_spacer", 239 | "name": "spacer", 240 | "group": "88de906.e68327", 241 | "order": 7, 242 | "width": "4", 243 | "height": "18" 244 | }, 245 | { 246 | "id": "b1d0e473.439698", 247 | "type": "addFirebase", 248 | "z": "bb155f83.a4277", 249 | "firebaseCertificate": "", 250 | "client_email": "", 251 | "private_key": "", 252 | "data": "", 253 | "childpath": "", 254 | "propertyType": "str", 255 | "method": "update", 256 | "newchildpath": "", 257 | "x": 710, 258 | "y": 300, 259 | "wires": [["7c8b78a0.1d4308"]] 260 | }, 261 | { 262 | "id": "23447946.4dc476", 263 | "type": "inject", 264 | "z": "bb155f83.a4277", 265 | "name": "Timestamp", 266 | "props": [{ "p": "payload" }], 267 | "repeat": "5", 268 | "crontab": "", 269 | "once": false, 270 | "onceDelay": 0.1, 271 | "topic": "", 272 | "payload": "", 273 | "payloadType": "date", 274 | "x": 130, 275 | "y": 260, 276 | "wires": [["db2c7552.3980f8"]] 277 | }, 278 | { 279 | "id": "bf37538d.4e7b9", 280 | "type": "ui_switch", 281 | "z": "bb155f83.a4277", 282 | "name": "Start/Stop", 283 | "label": "Start/Stop Simulation", 284 | "tooltip": "Start sending telemetry data to Firebase Realtime Database", 285 | "group": "a1f71297.5b069", 286 | "order": 2, 287 | "width": 0, 288 | "height": 0, 289 | "passthru": true, 290 | "decouple": "false", 291 | "topic": "gate", 292 | "style": "", 293 | "onvalue": "true", 294 | "onvalueType": "bool", 295 | "onicon": "", 296 | "oncolor": "", 297 | "offvalue": "false", 298 | "offvalueType": "bool", 299 | "officon": "", 300 | "offcolor": "", 301 | "x": 100, 302 | "y": 340, 303 | "wires": [["db2c7552.3980f8"]] 304 | }, 305 | { 306 | "id": "3c7bbdb4.397652", 307 | "type": "ui_slider", 308 | "z": "7f15f7f9.621a48", 309 | "name": "Min", 310 | "label": "Min", 311 | "tooltip": "Minimum value of air temperature", 312 | "group": "5d47cc2.fe17834", 313 | "order": 1, 314 | "width": 0, 315 | "height": 0, 316 | "passthru": true, 317 | "outs": "all", 318 | "topic": "", 319 | "min": 0, 320 | "max": "100", 321 | "step": 1, 322 | "x": 90, 323 | "y": 80, 324 | "wires": [["3cc63cd5.bfd614", "19e8c238.3d103e"]] 325 | }, 326 | { 327 | "id": "de94d6da.924528", 328 | "type": "ui_slider", 329 | "z": "7f15f7f9.621a48", 330 | "name": "Max", 331 | "label": "Max", 332 | "tooltip": "Maximum value of air temperature", 333 | "group": "5d47cc2.fe17834", 334 | "order": 3, 335 | "width": 0, 336 | "height": 0, 337 | "passthru": true, 338 | "outs": "all", 339 | "topic": "", 340 | "min": 0, 341 | "max": "100", 342 | "step": 1, 343 | "x": 90, 344 | "y": 200, 345 | "wires": [["bc16f7a3.5459e8", "af5ddc0e.7a70d"]] 346 | }, 347 | { 348 | "id": "b4177b1d.a5f0b8", 349 | "type": "subflow:7f15f7f9.621a48", 350 | "z": "bb155f83.a4277", 351 | "name": "airTemperature", 352 | "env": [], 353 | "x": 500, 354 | "y": 220, 355 | "wires": [["663e13b2.82511c"]] 356 | }, 357 | { 358 | "id": "3cc63cd5.bfd614", 359 | "type": "ui_text", 360 | "z": "7f15f7f9.621a48", 361 | "group": "5d47cc2.fe17834", 362 | "order": 2, 363 | "width": 0, 364 | "height": 0, 365 | "name": "Value", 366 | "label": "Value:", 367 | "format": "{{msg.payload}}", 368 | "layout": "row-spread", 369 | "x": 250, 370 | "y": 80, 371 | "wires": [] 372 | }, 373 | { 374 | "id": "bc16f7a3.5459e8", 375 | "type": "ui_text", 376 | "z": "7f15f7f9.621a48", 377 | "group": "5d47cc2.fe17834", 378 | "order": 4, 379 | "width": 0, 380 | "height": 0, 381 | "name": "Value", 382 | "label": "Value:", 383 | "format": "{{msg.payload}}", 384 | "layout": "row-spread", 385 | "x": 250, 386 | "y": 200, 387 | "wires": [] 388 | }, 389 | { 390 | "id": "e2b7dec9.cfb4", 391 | "type": "subflow:5d3f7c11.023534", 392 | "z": "bb155f83.a4277", 393 | "name": "airHumidity", 394 | "env": [], 395 | "x": 490, 396 | "y": 140, 397 | "wires": [["fe4fd7ce.70c838"]] 398 | }, 399 | { 400 | "id": "22c0bacc.5c2df6", 401 | "type": "subflow:41719d6c.3cfb44", 402 | "z": "bb155f83.a4277", 403 | "name": "soilMoisture", 404 | "env": [], 405 | "x": 490, 406 | "y": 300, 407 | "wires": [["b1d0e473.439698"]] 408 | }, 409 | { 410 | "id": "1f165dbf.a39cb2", 411 | "type": "subflow:f9d383cb.41058", 412 | "z": "bb155f83.a4277", 413 | "name": "soilpH", 414 | "env": [], 415 | "x": 470, 416 | "y": 380, 417 | "wires": [["4085dcbe.3c7024"]] 418 | }, 419 | { 420 | "id": "636bbabe.171a84", 421 | "type": "subflow:7a111b85.eca174", 422 | "z": "bb155f83.a4277", 423 | "name": "soilSalinity", 424 | "env": [], 425 | "x": 490, 426 | "y": 460, 427 | "wires": [["59fd8bd1.dc7b84"]] 428 | }, 429 | { 430 | "id": "19e8c238.3d103e", 431 | "type": "function", 432 | "z": "7f15f7f9.621a48", 433 | "name": "minValue", 434 | "func": "flow.set(\"airTemperatureMin\", msg.payload);\nreturn msg;", 435 | "outputs": 1, 436 | "noerr": 0, 437 | "initialize": "", 438 | "finalize": "", 439 | "x": 260, 440 | "y": 140, 441 | "wires": [["1624d34d.8c440d"]] 442 | }, 443 | { 444 | "id": "af5ddc0e.7a70d", 445 | "type": "function", 446 | "z": "7f15f7f9.621a48", 447 | "name": "maxValue", 448 | "func": "flow.set(\"airTemperatureMax\", msg.payload);\nreturn msg;", 449 | "outputs": 1, 450 | "noerr": 0, 451 | "initialize": "", 452 | "finalize": "", 453 | "x": 260, 454 | "y": 260, 455 | "wires": [["1624d34d.8c440d"]] 456 | }, 457 | { 458 | "id": "1624d34d.8c440d", 459 | "type": "function", 460 | "z": "7f15f7f9.621a48", 461 | "name": "airTemperature", 462 | "func": "if (global.get(\"control\") === true) {\n let min = flow.get(\"airTemperatureMin\");\n let max = flow.get(\"airTemperatureMax\");\n let airTemperature = (Math.random() * (max - min) + min).toFixed(2);\n global.set(\"airTemperature\", airTemperature);\n msg.payload = airTemperature;\n return msg;\n}\nelse {\n return null;\n}", 463 | "outputs": 1, 464 | "noerr": 0, 465 | "initialize": "", 466 | "finalize": "", 467 | "x": 480, 468 | "y": 180, 469 | "wires": [["c5dd25cb.aafdd8", "5e05ee13.787a1", "13b9c3ef.f5db2c"]] 470 | }, 471 | { 472 | "id": "c5dd25cb.aafdd8", 473 | "type": "ui_gauge", 474 | "z": "7f15f7f9.621a48", 475 | "name": "airTemperatureReading", 476 | "group": "5d47cc2.fe17834", 477 | "order": 5, 478 | "width": 0, 479 | "height": 0, 480 | "gtype": "gage", 481 | "title": "°C", 482 | "label": "°C", 483 | "format": "{{value}}", 484 | "min": 0, 485 | "max": "100", 486 | "colors": ["#00b500", "#e6e600", "#ca3838"], 487 | "seg1": "", 488 | "seg2": "", 489 | "x": 750, 490 | "y": 180, 491 | "wires": [] 492 | }, 493 | { 494 | "id": "5e05ee13.787a1", 495 | "type": "ui_chart", 496 | "z": "7f15f7f9.621a48", 497 | "name": "airTemperatureChart", 498 | "group": "5d47cc2.fe17834", 499 | "order": 6, 500 | "width": 0, 501 | "height": 0, 502 | "label": "Air temperature last minute", 503 | "chartType": "line", 504 | "legend": "false", 505 | "xformat": "HH:mm:ss", 506 | "interpolate": "linear", 507 | "nodata": "Awaiting new data", 508 | "dot": true, 509 | "ymin": "0", 510 | "ymax": "100", 511 | "removeOlder": 1, 512 | "removeOlderPoints": "", 513 | "removeOlderUnit": "60", 514 | "cutout": 0, 515 | "useOneColor": false, 516 | "useUTC": false, 517 | "colors": [ 518 | "#1f77b4", 519 | "#aec7e8", 520 | "#ff7f0e", 521 | "#2ca02c", 522 | "#98df8a", 523 | "#d62728", 524 | "#ff9896", 525 | "#9467bd", 526 | "#c5b0d5" 527 | ], 528 | "outputs": 1, 529 | "x": 740, 530 | "y": 260, 531 | "wires": [[]] 532 | }, 533 | { 534 | "id": "db2c7552.3980f8", 535 | "type": "function", 536 | "z": "bb155f83.a4277", 537 | "name": "control", 538 | "func": "if (msg.topic === \"gate\") {\n context.pass = (msg.payload === true) ? true : false;\n global.set(\"control\", context.pass);\n return null;\n}\nif (context.pass) {\n return msg;\n}\nreturn null;", 539 | "outputs": 1, 540 | "noerr": 0, 541 | "initialize": "", 542 | "finalize": "", 543 | "x": 310, 544 | "y": 300, 545 | "wires": [ 546 | [ 547 | "e2b7dec9.cfb4", 548 | "22c0bacc.5c2df6", 549 | "b4177b1d.a5f0b8", 550 | "1f165dbf.a39cb2", 551 | "636bbabe.171a84" 552 | ] 553 | ] 554 | }, 555 | { 556 | "id": "4befd78.7f55828", 557 | "type": "ui_slider", 558 | "z": "5d3f7c11.023534", 559 | "name": "Min", 560 | "label": "Min", 561 | "tooltip": "Minimum value of air humidity", 562 | "group": "856d803c.8b0cc", 563 | "order": 1, 564 | "width": 0, 565 | "height": 0, 566 | "passthru": true, 567 | "outs": "all", 568 | "topic": "", 569 | "min": 0, 570 | "max": "100", 571 | "step": 1, 572 | "x": 90, 573 | "y": 80, 574 | "wires": [["8baae11d.e51f8", "fde2eb98.eee518"]] 575 | }, 576 | { 577 | "id": "1ac7bd1.46aae43", 578 | "type": "ui_slider", 579 | "z": "5d3f7c11.023534", 580 | "name": "Max", 581 | "label": "Max", 582 | "tooltip": "Maximum value of air humidity", 583 | "group": "856d803c.8b0cc", 584 | "order": 3, 585 | "width": 0, 586 | "height": 0, 587 | "passthru": true, 588 | "outs": "all", 589 | "topic": "", 590 | "min": 0, 591 | "max": "100", 592 | "step": 1, 593 | "x": 90, 594 | "y": 200, 595 | "wires": [["ba3e7660.b71498", "1b3d24ba.a7f7fb"]] 596 | }, 597 | { 598 | "id": "8baae11d.e51f8", 599 | "type": "ui_text", 600 | "z": "5d3f7c11.023534", 601 | "group": "856d803c.8b0cc", 602 | "order": 2, 603 | "width": 0, 604 | "height": 0, 605 | "name": "Value", 606 | "label": "Value:", 607 | "format": "{{msg.payload}}", 608 | "layout": "row-spread", 609 | "x": 250, 610 | "y": 80, 611 | "wires": [] 612 | }, 613 | { 614 | "id": "ba3e7660.b71498", 615 | "type": "ui_text", 616 | "z": "5d3f7c11.023534", 617 | "group": "856d803c.8b0cc", 618 | "order": 4, 619 | "width": 0, 620 | "height": 0, 621 | "name": "Value", 622 | "label": "Value:", 623 | "format": "{{msg.payload}}", 624 | "layout": "row-spread", 625 | "x": 250, 626 | "y": 200, 627 | "wires": [] 628 | }, 629 | { 630 | "id": "fde2eb98.eee518", 631 | "type": "function", 632 | "z": "5d3f7c11.023534", 633 | "name": "minValue", 634 | "func": "flow.set(\"airHumidityMin\", msg.payload);\nreturn msg;", 635 | "outputs": 1, 636 | "noerr": 0, 637 | "initialize": "", 638 | "finalize": "", 639 | "x": 260, 640 | "y": 140, 641 | "wires": [["c620f442.386f18"]] 642 | }, 643 | { 644 | "id": "1b3d24ba.a7f7fb", 645 | "type": "function", 646 | "z": "5d3f7c11.023534", 647 | "name": "maxValue", 648 | "func": "flow.set(\"airHumidityMax\", msg.payload);\nreturn msg;", 649 | "outputs": 1, 650 | "noerr": 0, 651 | "initialize": "", 652 | "finalize": "", 653 | "x": 260, 654 | "y": 260, 655 | "wires": [["c620f442.386f18"]] 656 | }, 657 | { 658 | "id": "c620f442.386f18", 659 | "type": "function", 660 | "z": "5d3f7c11.023534", 661 | "name": "airHumidity", 662 | "func": "if (global.get(\"control\") === true) {\n let min = flow.get(\"airHumidityMin\");\n let max = flow.get(\"airHumidityMax\");\n let airHumidity = (Math.random() * (max - min) + min).toFixed(2);\n global.set(\"airHumidity\", airHumidity);\n msg.payload = airHumidity;\n return msg;\n}\nelse {\n return null;\n}", 663 | "outputs": 1, 664 | "noerr": 0, 665 | "initialize": "", 666 | "finalize": "", 667 | "x": 470, 668 | "y": 180, 669 | "wires": [["1b3ce38d.277eac", "ffda1a6.b3b41e8", "ed27784e.86a9d8"]] 670 | }, 671 | { 672 | "id": "1b3ce38d.277eac", 673 | "type": "ui_gauge", 674 | "z": "5d3f7c11.023534", 675 | "name": "airHumidityReading", 676 | "group": "856d803c.8b0cc", 677 | "order": 5, 678 | "width": 0, 679 | "height": 0, 680 | "gtype": "gage", 681 | "title": "%", 682 | "label": "%", 683 | "format": "{{value}}", 684 | "min": 0, 685 | "max": "100", 686 | "colors": ["#00b500", "#e6e600", "#ca3838"], 687 | "seg1": "", 688 | "seg2": "", 689 | "x": 730, 690 | "y": 180, 691 | "wires": [] 692 | }, 693 | { 694 | "id": "ffda1a6.b3b41e8", 695 | "type": "ui_chart", 696 | "z": "5d3f7c11.023534", 697 | "name": "airHumidityChart", 698 | "group": "856d803c.8b0cc", 699 | "order": 6, 700 | "width": 0, 701 | "height": 0, 702 | "label": "Air humidity last minute", 703 | "chartType": "line", 704 | "legend": "false", 705 | "xformat": "HH:mm:ss", 706 | "interpolate": "linear", 707 | "nodata": "Awaiting new data", 708 | "dot": true, 709 | "ymin": "0", 710 | "ymax": "100", 711 | "removeOlder": 1, 712 | "removeOlderPoints": "", 713 | "removeOlderUnit": "60", 714 | "cutout": 0, 715 | "useOneColor": false, 716 | "useUTC": false, 717 | "colors": [ 718 | "#1f77b4", 719 | "#aec7e8", 720 | "#ff7f0e", 721 | "#2ca02c", 722 | "#98df8a", 723 | "#d62728", 724 | "#ff9896", 725 | "#9467bd", 726 | "#c5b0d5" 727 | ], 728 | "outputs": 1, 729 | "x": 730, 730 | "y": 260, 731 | "wires": [[]] 732 | }, 733 | { 734 | "id": "182fcb04.d29485", 735 | "type": "ui_slider", 736 | "z": "f9d383cb.41058", 737 | "name": "Min", 738 | "label": "Min", 739 | "tooltip": "Minimum value of soil pH", 740 | "group": "99a1466b.ac8278", 741 | "order": 1, 742 | "width": 0, 743 | "height": 0, 744 | "passthru": true, 745 | "outs": "all", 746 | "topic": "", 747 | "min": 0, 748 | "max": "100", 749 | "step": 1, 750 | "x": 90, 751 | "y": 80, 752 | "wires": [["438558f7.43fa58", "59a3bae8.75fab4"]] 753 | }, 754 | { 755 | "id": "20e93046.90f84", 756 | "type": "ui_slider", 757 | "z": "f9d383cb.41058", 758 | "name": "Max", 759 | "label": "Max", 760 | "tooltip": "Maximum value of soil pH", 761 | "group": "99a1466b.ac8278", 762 | "order": 3, 763 | "width": 0, 764 | "height": 0, 765 | "passthru": true, 766 | "outs": "all", 767 | "topic": "", 768 | "min": 0, 769 | "max": "100", 770 | "step": 1, 771 | "x": 90, 772 | "y": 200, 773 | "wires": [["69c13815.f100c8", "5ca1b6da.29b658"]] 774 | }, 775 | { 776 | "id": "438558f7.43fa58", 777 | "type": "ui_text", 778 | "z": "f9d383cb.41058", 779 | "group": "99a1466b.ac8278", 780 | "order": 2, 781 | "width": 0, 782 | "height": 0, 783 | "name": "Value", 784 | "label": "Value:", 785 | "format": "{{msg.payload}}", 786 | "layout": "row-spread", 787 | "x": 250, 788 | "y": 80, 789 | "wires": [] 790 | }, 791 | { 792 | "id": "69c13815.f100c8", 793 | "type": "ui_text", 794 | "z": "f9d383cb.41058", 795 | "group": "99a1466b.ac8278", 796 | "order": 4, 797 | "width": 0, 798 | "height": 0, 799 | "name": "Value", 800 | "label": "Value:", 801 | "format": "{{msg.payload}}", 802 | "layout": "row-spread", 803 | "x": 250, 804 | "y": 200, 805 | "wires": [] 806 | }, 807 | { 808 | "id": "59a3bae8.75fab4", 809 | "type": "function", 810 | "z": "f9d383cb.41058", 811 | "name": "minValue", 812 | "func": "flow.set(\"soilpHMin\", msg.payload);\nreturn msg;", 813 | "outputs": 1, 814 | "noerr": 0, 815 | "initialize": "", 816 | "finalize": "", 817 | "x": 260, 818 | "y": 140, 819 | "wires": [["a841f15a.dfbdf"]] 820 | }, 821 | { 822 | "id": "5ca1b6da.29b658", 823 | "type": "function", 824 | "z": "f9d383cb.41058", 825 | "name": "maxValue", 826 | "func": "flow.set(\"soilpHMax\", msg.payload);\nreturn msg;", 827 | "outputs": 1, 828 | "noerr": 0, 829 | "initialize": "", 830 | "finalize": "", 831 | "x": 260, 832 | "y": 260, 833 | "wires": [["a841f15a.dfbdf"]] 834 | }, 835 | { 836 | "id": "a841f15a.dfbdf", 837 | "type": "function", 838 | "z": "f9d383cb.41058", 839 | "name": "soilpH", 840 | "func": "if (global.get(\"control\") === true) {\n let min = flow.get(\"soilpHMin\");\n let max = flow.get(\"soilpHMax\");\n let soilpH = (Math.random() * (max - min) + min).toFixed(2);\n global.set(\"soilpH\", soilpH);\n msg.payload = soilpH;\n return msg;\n}\nelse {\n return null;\n}", 841 | "outputs": 1, 842 | "noerr": 0, 843 | "initialize": "", 844 | "finalize": "", 845 | "x": 450, 846 | "y": 180, 847 | "wires": [["d342e64f.727438", "6d157a2c.bf8b94", "bdca0114.d69de"]] 848 | }, 849 | { 850 | "id": "d342e64f.727438", 851 | "type": "ui_gauge", 852 | "z": "f9d383cb.41058", 853 | "name": "soilpHReading", 854 | "group": "99a1466b.ac8278", 855 | "order": 5, 856 | "width": 0, 857 | "height": 0, 858 | "gtype": "gage", 859 | "title": "pH", 860 | "label": "pH", 861 | "format": "{{value}}", 862 | "min": 0, 863 | "max": "100", 864 | "colors": ["#00b500", "#e6e600", "#ca3838"], 865 | "seg1": "", 866 | "seg2": "", 867 | "x": 720, 868 | "y": 180, 869 | "wires": [] 870 | }, 871 | { 872 | "id": "6d157a2c.bf8b94", 873 | "type": "ui_chart", 874 | "z": "f9d383cb.41058", 875 | "name": "soilpHChart", 876 | "group": "99a1466b.ac8278", 877 | "order": 6, 878 | "width": 0, 879 | "height": 0, 880 | "label": "Soil pH last minute", 881 | "chartType": "line", 882 | "legend": "false", 883 | "xformat": "HH:mm:ss", 884 | "interpolate": "linear", 885 | "nodata": "Awaiting new data", 886 | "dot": true, 887 | "ymin": "0", 888 | "ymax": "100", 889 | "removeOlder": 1, 890 | "removeOlderPoints": "", 891 | "removeOlderUnit": "60", 892 | "cutout": 0, 893 | "useOneColor": false, 894 | "useUTC": false, 895 | "colors": [ 896 | "#1f77b4", 897 | "#aec7e8", 898 | "#ff7f0e", 899 | "#2ca02c", 900 | "#98df8a", 901 | "#d62728", 902 | "#ff9896", 903 | "#9467bd", 904 | "#c5b0d5" 905 | ], 906 | "outputs": 1, 907 | "x": 710, 908 | "y": 260, 909 | "wires": [[]] 910 | }, 911 | { 912 | "id": "41bf3400.90221c", 913 | "type": "ui_slider", 914 | "z": "7a111b85.eca174", 915 | "name": "Min", 916 | "label": "Min", 917 | "tooltip": "Minimum value of soil salinity", 918 | "group": "bc339738.e6a1e8", 919 | "order": 1, 920 | "width": 0, 921 | "height": 0, 922 | "passthru": true, 923 | "outs": "all", 924 | "topic": "", 925 | "min": 0, 926 | "max": "100", 927 | "step": 1, 928 | "x": 90, 929 | "y": 80, 930 | "wires": [["fdf0cc7c.4ecee", "282064d6.5f80bc"]] 931 | }, 932 | { 933 | "id": "1ffabc67.81cd24", 934 | "type": "ui_slider", 935 | "z": "7a111b85.eca174", 936 | "name": "Max", 937 | "label": "Max", 938 | "tooltip": "Maximum value of soil salinity", 939 | "group": "bc339738.e6a1e8", 940 | "order": 3, 941 | "width": 0, 942 | "height": 0, 943 | "passthru": true, 944 | "outs": "all", 945 | "topic": "", 946 | "min": 0, 947 | "max": "100", 948 | "step": 1, 949 | "x": 90, 950 | "y": 200, 951 | "wires": [["bf135961.f055d8", "3c191757.18a9c8"]] 952 | }, 953 | { 954 | "id": "fdf0cc7c.4ecee", 955 | "type": "ui_text", 956 | "z": "7a111b85.eca174", 957 | "group": "bc339738.e6a1e8", 958 | "order": 2, 959 | "width": 0, 960 | "height": 0, 961 | "name": "Value", 962 | "label": "Value:", 963 | "format": "{{msg.payload}}", 964 | "layout": "row-spread", 965 | "x": 250, 966 | "y": 80, 967 | "wires": [] 968 | }, 969 | { 970 | "id": "bf135961.f055d8", 971 | "type": "ui_text", 972 | "z": "7a111b85.eca174", 973 | "group": "bc339738.e6a1e8", 974 | "order": 4, 975 | "width": 0, 976 | "height": 0, 977 | "name": "Value", 978 | "label": "Value:", 979 | "format": "{{msg.payload}}", 980 | "layout": "row-spread", 981 | "x": 250, 982 | "y": 200, 983 | "wires": [] 984 | }, 985 | { 986 | "id": "282064d6.5f80bc", 987 | "type": "function", 988 | "z": "7a111b85.eca174", 989 | "name": "minValue", 990 | "func": "flow.set(\"soilSalinityMin\", msg.payload);\nreturn msg;", 991 | "outputs": 1, 992 | "noerr": 0, 993 | "initialize": "", 994 | "finalize": "", 995 | "x": 260, 996 | "y": 140, 997 | "wires": [["578fce88.15de5"]] 998 | }, 999 | { 1000 | "id": "3c191757.18a9c8", 1001 | "type": "function", 1002 | "z": "7a111b85.eca174", 1003 | "name": "maxValue", 1004 | "func": "flow.set(\"soilSalinityMax\", msg.payload);\nreturn msg;", 1005 | "outputs": 1, 1006 | "noerr": 0, 1007 | "initialize": "", 1008 | "finalize": "", 1009 | "x": 260, 1010 | "y": 260, 1011 | "wires": [["578fce88.15de5"]] 1012 | }, 1013 | { 1014 | "id": "578fce88.15de5", 1015 | "type": "function", 1016 | "z": "7a111b85.eca174", 1017 | "name": "soilSalinity", 1018 | "func": "if (global.get(\"control\") === true) {\n let min = flow.get(\"soilSalinityMin\");\n let max = flow.get(\"soilSalinityMax\");\n let soilSalinity = (Math.random() * (max - min) + min).toFixed(2);\n global.set(\"soilSalinity\", soilSalinity);\n msg.payload = soilSalinity;\n return msg;\n}\nelse {\n return null;\n}", 1019 | "outputs": 1, 1020 | "noerr": 0, 1021 | "initialize": "", 1022 | "finalize": "", 1023 | "x": 470, 1024 | "y": 180, 1025 | "wires": [["42d8c053.597ff", "5aa01ca0.9391c4", "f33a2102.a728"]] 1026 | }, 1027 | { 1028 | "id": "42d8c053.597ff", 1029 | "type": "ui_gauge", 1030 | "z": "7a111b85.eca174", 1031 | "name": "soilSalinityReading", 1032 | "group": "bc339738.e6a1e8", 1033 | "order": 5, 1034 | "width": 0, 1035 | "height": 0, 1036 | "gtype": "gage", 1037 | "title": "mS/cm", 1038 | "label": "mS/cm", 1039 | "format": "{{value}}", 1040 | "min": 0, 1041 | "max": "100", 1042 | "colors": ["#00b500", "#e6e600", "#ca3838"], 1043 | "seg1": "", 1044 | "seg2": "", 1045 | "x": 730, 1046 | "y": 180, 1047 | "wires": [] 1048 | }, 1049 | { 1050 | "id": "5aa01ca0.9391c4", 1051 | "type": "ui_chart", 1052 | "z": "7a111b85.eca174", 1053 | "name": "soilSalinityChart", 1054 | "group": "bc339738.e6a1e8", 1055 | "order": 6, 1056 | "width": 0, 1057 | "height": 0, 1058 | "label": "Soil salinity last minute", 1059 | "chartType": "line", 1060 | "legend": "false", 1061 | "xformat": "HH:mm:ss", 1062 | "interpolate": "linear", 1063 | "nodata": "Awaiting new data", 1064 | "dot": true, 1065 | "ymin": "0", 1066 | "ymax": "100", 1067 | "removeOlder": 1, 1068 | "removeOlderPoints": "", 1069 | "removeOlderUnit": "60", 1070 | "cutout": 0, 1071 | "useOneColor": false, 1072 | "useUTC": false, 1073 | "colors": [ 1074 | "#1f77b4", 1075 | "#aec7e8", 1076 | "#ff7f0e", 1077 | "#2ca02c", 1078 | "#98df8a", 1079 | "#d62728", 1080 | "#ff9896", 1081 | "#9467bd", 1082 | "#c5b0d5" 1083 | ], 1084 | "outputs": 1, 1085 | "x": 720, 1086 | "y": 260, 1087 | "wires": [[]] 1088 | }, 1089 | { 1090 | "id": "2111e35.d18c81c", 1091 | "type": "ui_slider", 1092 | "z": "41719d6c.3cfb44", 1093 | "name": "Min", 1094 | "label": "Min", 1095 | "tooltip": "Minimum value of soil moisture", 1096 | "group": "b9c3ab84.f017f8", 1097 | "order": 1, 1098 | "width": 0, 1099 | "height": 0, 1100 | "passthru": true, 1101 | "outs": "all", 1102 | "topic": "", 1103 | "min": 0, 1104 | "max": "100", 1105 | "step": 1, 1106 | "x": 90, 1107 | "y": 80, 1108 | "wires": [["8167486c.537088", "f1cf97bd.f58b08"]] 1109 | }, 1110 | { 1111 | "id": "b69c67dc.a3f5e8", 1112 | "type": "ui_slider", 1113 | "z": "41719d6c.3cfb44", 1114 | "name": "Max", 1115 | "label": "Max", 1116 | "tooltip": "Maximum value of soil moisture", 1117 | "group": "b9c3ab84.f017f8", 1118 | "order": 3, 1119 | "width": 0, 1120 | "height": 0, 1121 | "passthru": true, 1122 | "outs": "all", 1123 | "topic": "", 1124 | "min": 0, 1125 | "max": "100", 1126 | "step": 1, 1127 | "x": 90, 1128 | "y": 200, 1129 | "wires": [["ae5b6533.924748", "8bb90da8.cfe89"]] 1130 | }, 1131 | { 1132 | "id": "8167486c.537088", 1133 | "type": "ui_text", 1134 | "z": "41719d6c.3cfb44", 1135 | "group": "b9c3ab84.f017f8", 1136 | "order": 2, 1137 | "width": 0, 1138 | "height": 0, 1139 | "name": "Value", 1140 | "label": "Value:", 1141 | "format": "{{msg.payload}}", 1142 | "layout": "row-spread", 1143 | "x": 250, 1144 | "y": 80, 1145 | "wires": [] 1146 | }, 1147 | { 1148 | "id": "ae5b6533.924748", 1149 | "type": "ui_text", 1150 | "z": "41719d6c.3cfb44", 1151 | "group": "b9c3ab84.f017f8", 1152 | "order": 4, 1153 | "width": 0, 1154 | "height": 0, 1155 | "name": "Value", 1156 | "label": "Value:", 1157 | "format": "{{msg.payload}}", 1158 | "layout": "row-spread", 1159 | "x": 250, 1160 | "y": 200, 1161 | "wires": [] 1162 | }, 1163 | { 1164 | "id": "f1cf97bd.f58b08", 1165 | "type": "function", 1166 | "z": "41719d6c.3cfb44", 1167 | "name": "minValue", 1168 | "func": "flow.set(\"soilMoistureMin\", msg.payload);\nreturn msg;", 1169 | "outputs": 1, 1170 | "noerr": 0, 1171 | "initialize": "", 1172 | "finalize": "", 1173 | "x": 260, 1174 | "y": 140, 1175 | "wires": [["66d8b839.f565a8"]] 1176 | }, 1177 | { 1178 | "id": "8bb90da8.cfe89", 1179 | "type": "function", 1180 | "z": "41719d6c.3cfb44", 1181 | "name": "maxValue", 1182 | "func": "flow.set(\"soilMoistureMax\", msg.payload);\nreturn msg;", 1183 | "outputs": 1, 1184 | "noerr": 0, 1185 | "initialize": "", 1186 | "finalize": "", 1187 | "x": 260, 1188 | "y": 260, 1189 | "wires": [["66d8b839.f565a8"]] 1190 | }, 1191 | { 1192 | "id": "66d8b839.f565a8", 1193 | "type": "function", 1194 | "z": "41719d6c.3cfb44", 1195 | "name": "soilMoisture", 1196 | "func": "if (global.get(\"control\") === true) {\n let min = flow.get(\"soilMoistureMin\");\n let max = flow.get(\"soilMoistureMax\");\n let soilMoisture = (Math.random() * (max - min) + min).toFixed(2);\n global.set(\"soilMoisture\", soilMoisture);\n msg.payload = soilMoisture;\n return msg;\n}\nelse {\n return null;\n}", 1197 | "outputs": 1, 1198 | "noerr": 0, 1199 | "initialize": "", 1200 | "finalize": "", 1201 | "x": 470, 1202 | "y": 180, 1203 | "wires": [["a0795cf.c2a64a", "4f0a0648.5b31a8", "d0abdcdc.837d"]] 1204 | }, 1205 | { 1206 | "id": "a0795cf.c2a64a", 1207 | "type": "ui_gauge", 1208 | "z": "41719d6c.3cfb44", 1209 | "name": "soilMoistureReading", 1210 | "group": "b9c3ab84.f017f8", 1211 | "order": 5, 1212 | "width": 0, 1213 | "height": 0, 1214 | "gtype": "gage", 1215 | "title": "%", 1216 | "label": "%", 1217 | "format": "{{value}}", 1218 | "min": 0, 1219 | "max": "100", 1220 | "colors": ["#00b500", "#e6e600", "#ca3838"], 1221 | "seg1": "", 1222 | "seg2": "", 1223 | "x": 740, 1224 | "y": 180, 1225 | "wires": [] 1226 | }, 1227 | { 1228 | "id": "4f0a0648.5b31a8", 1229 | "type": "ui_chart", 1230 | "z": "41719d6c.3cfb44", 1231 | "name": "soilMoistureChart", 1232 | "group": "b9c3ab84.f017f8", 1233 | "order": 6, 1234 | "width": 0, 1235 | "height": 0, 1236 | "label": "Soil moisture last minute", 1237 | "chartType": "line", 1238 | "legend": "false", 1239 | "xformat": "HH:mm:ss", 1240 | "interpolate": "linear", 1241 | "nodata": "Awaiting new data", 1242 | "dot": true, 1243 | "ymin": "0", 1244 | "ymax": "100", 1245 | "removeOlder": 1, 1246 | "removeOlderPoints": "", 1247 | "removeOlderUnit": "60", 1248 | "cutout": 0, 1249 | "useOneColor": false, 1250 | "useUTC": false, 1251 | "colors": [ 1252 | "#1f77b4", 1253 | "#aec7e8", 1254 | "#ff7f0e", 1255 | "#2ca02c", 1256 | "#98df8a", 1257 | "#d62728", 1258 | "#ff9896", 1259 | "#9467bd", 1260 | "#c5b0d5" 1261 | ], 1262 | "outputs": 1, 1263 | "x": 730, 1264 | "y": 260, 1265 | "wires": [[]] 1266 | }, 1267 | { 1268 | "id": "13b9c3ef.f5db2c", 1269 | "type": "function", 1270 | "z": "7f15f7f9.621a48", 1271 | "name": "airTemperatureMsg", 1272 | "func": "if (global.get(\"control\") === true) {\n let timestamp = Date.now();\n let airTemperature = global.get(\"airTemperature\");\n let payload = {\n [timestamp]: airTemperature,\n };\n msg.payload = payload;\n return msg;\n}\nelse {\n return null;\n}", 1273 | "outputs": 1, 1274 | "noerr": 0, 1275 | "initialize": "", 1276 | "finalize": "", 1277 | "x": 730, 1278 | "y": 340, 1279 | "wires": [[]] 1280 | }, 1281 | { 1282 | "id": "ed27784e.86a9d8", 1283 | "type": "function", 1284 | "z": "5d3f7c11.023534", 1285 | "name": "airHumidityMsg", 1286 | "func": "if (global.get(\"control\") === true) {\n let timestamp = Date.now();\n let airHumidity = global.get(\"airHumidity\");\n let payload = {\n [timestamp]: airHumidity,\n };\n msg.payload = payload;\n return msg;\n}\nelse {\n return null;\n}", 1287 | "outputs": 1, 1288 | "noerr": 0, 1289 | "initialize": "", 1290 | "finalize": "", 1291 | "x": 720, 1292 | "y": 340, 1293 | "wires": [[]] 1294 | }, 1295 | { 1296 | "id": "d0abdcdc.837d", 1297 | "type": "function", 1298 | "z": "41719d6c.3cfb44", 1299 | "name": "soilMoistureMsg", 1300 | "func": "if (global.get(\"control\") === true) {\n let timestamp = Date.now();\n let soilMoisture = global.get(\"soilMoisture\");\n let payload = {\n [timestamp]: soilMoisture,\n };\n msg.payload = payload;\n return msg;\n}\nelse {\n return null;\n}", 1301 | "outputs": 1, 1302 | "noerr": 0, 1303 | "initialize": "", 1304 | "finalize": "", 1305 | "x": 720, 1306 | "y": 340, 1307 | "wires": [[]] 1308 | }, 1309 | { 1310 | "id": "bdca0114.d69de", 1311 | "type": "function", 1312 | "z": "f9d383cb.41058", 1313 | "name": "soilpHMsg", 1314 | "func": "if (global.get(\"control\") === true) {\n let timestamp = Date.now();\n let soilpH = global.get(\"soilpH\");\n let payload = {\n [timestamp]: soilpH,\n };\n msg.payload = payload;\n return msg;\n}\nelse {\n return null;\n}", 1315 | "outputs": 1, 1316 | "noerr": 0, 1317 | "initialize": "", 1318 | "finalize": "", 1319 | "x": 710, 1320 | "y": 340, 1321 | "wires": [[]] 1322 | }, 1323 | { 1324 | "id": "f33a2102.a728", 1325 | "type": "function", 1326 | "z": "7a111b85.eca174", 1327 | "name": "soilSalinityMsg", 1328 | "func": "if (global.get(\"control\") === true) {\n let timestamp = Date.now();\n let soilSalinity = global.get(\"soilSalinity\");\n let payload = {\n [timestamp]: soilSalinity,\n };\n msg.payload = payload;\n return msg;\n}\nelse {\n return null;\n}", 1329 | "outputs": 1, 1330 | "noerr": 0, 1331 | "initialize": "", 1332 | "finalize": "", 1333 | "x": 720, 1334 | "y": 340, 1335 | "wires": [[]] 1336 | }, 1337 | { 1338 | "id": "7c8b78a0.1d4308", 1339 | "type": "debug", 1340 | "z": "bb155f83.a4277", 1341 | "name": "debug", 1342 | "active": true, 1343 | "tosidebar": true, 1344 | "console": false, 1345 | "tostatus": false, 1346 | "complete": "payload", 1347 | "targetType": "msg", 1348 | "statusVal": "", 1349 | "statusType": "auto", 1350 | "x": 890, 1351 | "y": 300, 1352 | "wires": [] 1353 | }, 1354 | { 1355 | "id": "59fd8bd1.dc7b84", 1356 | "type": "addFirebase", 1357 | "z": "bb155f83.a4277", 1358 | "firebaseCertificate": "", 1359 | "client_email": "", 1360 | "private_key": "", 1361 | "data": "", 1362 | "childpath": "", 1363 | "propertyType": "str", 1364 | "method": "update", 1365 | "newchildpath": "", 1366 | "x": 710, 1367 | "y": 460, 1368 | "wires": [["7c8b78a0.1d4308"]] 1369 | }, 1370 | { 1371 | "id": "4085dcbe.3c7024", 1372 | "type": "addFirebase", 1373 | "z": "bb155f83.a4277", 1374 | "firebaseCertificate": "", 1375 | "client_email": "", 1376 | "private_key": "", 1377 | "data": "", 1378 | "childpath": "", 1379 | "propertyType": "str", 1380 | "method": "update", 1381 | "newchildpath": "", 1382 | "x": 710, 1383 | "y": 380, 1384 | "wires": [["7c8b78a0.1d4308"]] 1385 | }, 1386 | { 1387 | "id": "fe4fd7ce.70c838", 1388 | "type": "addFirebase", 1389 | "z": "bb155f83.a4277", 1390 | "firebaseCertificate": "", 1391 | "client_email": "", 1392 | "private_key": "", 1393 | "data": "", 1394 | "childpath": "", 1395 | "propertyType": "str", 1396 | "method": "update", 1397 | "newchildpath": "", 1398 | "x": 710, 1399 | "y": 140, 1400 | "wires": [["7c8b78a0.1d4308"]] 1401 | }, 1402 | { 1403 | "id": "663e13b2.82511c", 1404 | "type": "addFirebase", 1405 | "z": "bb155f83.a4277", 1406 | "firebaseCertificate": "", 1407 | "client_email": "", 1408 | "private_key": "", 1409 | "data": "", 1410 | "childpath": "", 1411 | "propertyType": "str", 1412 | "method": "update", 1413 | "newchildpath": "", 1414 | "x": 710, 1415 | "y": 220, 1416 | "wires": [["7c8b78a0.1d4308"]] 1417 | } 1418 | ] 1419 | --------------------------------------------------------------------------------