This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm whether you accept or reject these cookies being set.

A cookie will be stored in your browser regardless of choice to prevent you being asked this question again. You will be able to change your cookie settings at any time using the link in the footer.

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Also send I2C sensor data to Node-Red so ALL instruments show on the dashboard
#1
Hello all, long overwhelming message coming up.. Hopefully Node-Red is my way out

(If you feel like TL-DR, the important questions are in bold)

So in the past few weeks, I have read so many websites about concepts, communication protocols, documentation and I still don't understand 90% of what people are talking about on this forum, or what OP does "exactly".. I don't get it, I'm a software engineer and I feel stupid haha! Everybody seems to understand perfectly what spaghetti all these protocols and terms build togheter: MQTT, i2C, NMEA0183, NME2000, 1W, SPI, Signal K, Serial, GPIO, kplex. They all seem interconnected but I fail to see the big picture, where all the data passes by, even with the documentation workflow image, plus many of the pages about the things I don't understand like MQTT and SPI are empty in both old and new docs.

So anyways, I managed to make our analog oil pressure sensors work with an Arduino Uno board I had lying around and send it over I2C to OpenPlotter, until I realized that you can only add sensors that were pre-configured in OpenPlotter, not custom sensors. So I cloned the OP repo and searched in the code where that list was to configure my own I2C sensor in the files (add_i2c.py, openplotter.py, the .pypilot/RTIMULib files) until I realized that thers's no way the devs wanted it to be that complicated.

Then I read this thread about someone trying to send data via I2C from Arduino Uno to RPi with the same problem as mine:
http://forum.openmarine.net/showthread.p...hlight=i2c
And most people seem to say that Node-Red is the solution (I avoided it until now since I thought it was a programming language for kids like scracth hahaha). Is there a way however to send the I2C data to Node-Red somehow? If I can get the oil pressure on a dashboard there, AND other I2C (like the BMP180) sensors to all display there without having to use the Signal K instruments panel, it would be awesome! If there's an obvious solution to only use Node-red for everything, please point me in the right direction and I'll do my homework and read the docs, as long as I stop going in circles!

I've seen amazing Code-Red dashboard in the forums like these:
http://forum.openmarine.net/showthread.php?tid=1087
And this one (Unfortunately using MQTT that I don't undersand):
http://www.ybw.com/forums/showthread.php...d-node-red
and now I really want to use it, I got some great tutorial videos and links so I'll go read this tomorrow.

In the meantime, can someone also answer these questions please:
-Is it possible to send I2C data to Node-Red? I liked i2C because I can just connect the Arduino Uno to SCL and SDA, without needing a level shifter or resistance + no need for a USB hub (as I can't get one now far from a decent town). Not sure if I'm supposed to use something like this:
https://github.com/SignalK/node-red-embedded

-Am I supposed to send the i2C sensor data over NMEA using the generator somehow? It seems like it's only pre-generated sentences with specific sensors, nothing custom.

-Can OpenCPN display other data than NMEA? For example i2C, Serial or GPIO sensors, I guess by using plugins like "Dashboard"?

Thanks for reading all this and enduring my confusing post XD I feel like I can't see the easy way out in front of me, just like this picture XD
Reply
#2
example import clipboard opencpn is limited to a few things it can display you can use dashboard in NR

Code:
[{"id":"d75f9eeb.e9af2","type":"websocket in","z":"82321e4.b0af8e","name":"ws","server":"41d6b650.f16a38","client":"","x":50,"y":620,"wires":[["83969d8.a84d66","c5c9eb43.d8f238","38780251.f951ae","ba58bc65.7efb9","e81cb99d.1966d8"]]},{"id":"83969d8.a84d66","type":"jsonpath","z":"82321e4.b0af8e","expression":"$.updates..values[*]","split":false,"name":"Signal K delta values","x":240,"y":620,"wires":[["770e578d.94a6d8"]]},{"id":"770e578d.94a6d8","type":"function","z":"82321e4.b0af8e","name":"merge values","func":"var paths={};\nvar arrayLength = msg.payload.length;\nfor (var i = 0; i < arrayLength; i++) {\n    paths[msg.payload[i].path]=msg.payload[i].value;\n}\nmsg.payload = paths;\nreturn msg;","outputs":1,"noerr":0,"x":440,"y":620,"wires":[["abaad182.6b541","4647605c.f27e1","94c51894.715fe8","b2490678.59dba8","a2c7a150.6c2af","963a6ecd.eb9f2","b1b1f8ee.678498","8e6844de.9733a8","28f5b60f.9eb77a","1d6e8fe5.f399d","4b42071a.e35c88","a26efae0.3bb758","ec450371.3822a"]]},{"id":"11507251.ffafbe","type":"ui_template","z":"82321e4.b0af8e","group":"1e14c235.4fc26e","name":"Tempin","order":3,"width":"3","height":"6","format":"<script src=\"/myjs/tween-min.js\"></script>\n<script src=\"/myjs/steelseries-min.js\"></script>\n<script>\nvar tempout;\n    (function(scope){ \n        scope.$watch('msg', function(msg) {\n           if (typeof(msg.value) != \"undefined\") tempout.setValueAnimated(msg.value);\n           //if (typeof(msg.threshold) != \"undefined\") radial4.setThreshold(msg.threshold);\n          // if (typeof(msg.odo) != \"undefined\")radial4.setOdoValue(msg.odo);  \n           //if (typeof(msg.userLed) != \"undefined\") radial4.setUserLedOnOff(msg.userLed);  \n          // if (typeof(msg.trend) != \"undefined\")\n            {\n               // if (msg.trend==1)     radial4.setTrend(steelseries.TrendState.UP);\n                //if (msg.trend==0)     radial4.setTrend(steelseries.TrendState.STEADY);\n               // if (msg.trend==-1)    radial4.setTrend(steelseries.TrendState.DOWN);\n               // if (msg.trend==-2)    radial4.setTrend(steelseries.TrendState.OFF);\n            }\n        });\n    })(scope);\n\n    var sections = [steelseries.Section(0, 25, 'rgba(0, 0, 220, 0.3)'),\n                        steelseries.Section(25, 50, 'rgba(0, 220, 0, 0.3)'),\n                        steelseries.Section(50, 75, 'rgba(220, 220, 0, 0.3)') ],\n\n            // Define one area\n    areas = [steelseries.Section(75, 100, 'rgba(220, 0, 0, 0.3)')],\n\n    tempout = new steelseries.Linear('tempout', {\n            gaugeType: steelseries.GaugeType.TYPE2,\n            width: 140,\n            height: 300,\n            //size: 292,\n            section: sections,\n            area: areas,\n            titleString: \"Inside\",\n            unitString: \"Degrees F\",\n            threshold: 80,\n            lcdVisible: true,\n           \n            //thresholdRising: false,\n           // userLedVisible: true,\n           // useOdometer: true,\n          //  lcdVisible: true,\n           // trendVisible: true\n        });\n                        \n    tempout.setFrameDesign(steelseries.FrameDesign.BRASS);\n    tempout.setValueAnimated(0);\n    tempout.setPointerType(steelseries.PointerType.TYPE9);\n   // radial4.setThreshold(50);\n    //radial4.blinkUserLed(0);\n   // radial4.setOdoValue(0);\n\n\n</script>\n\n<canvas id=\"tempout\" width=\"140\" height=\"300\"></canvas>\n","storeOutMessages":true,"fwdInMessages":true,"x":1198.0003967285156,"y":588.0000686645508,"wires":[[]]},{"id":"28f5b60f.9eb77a","type":"function","z":"82321e4.b0af8e","name":"Water Temp","func":"var signalk_key=\"environment.water.temperature\";\n\nif(msg.payload.hasOwnProperty(signalk_key)){\n    msg.payload=msg.payload[signalk_key];\n    return msg;\n    \n\n}","outputs":1,"noerr":0,"x":639,"y":563.000002861023,"wires":[["ece38a60.7f99c8"]]},{"id":"ee83bd35.bdac9","type":"function","z":"82321e4.b0af8e","name":"","func":"msg.value=msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":976.000057220459,"y":588.0000066757202,"wires":[["11507251.ffafbe"]]},{"id":"ece38a60.7f99c8","type":"function","z":"82321e4.b0af8e","name":"K to F","func":"var temp = msg.payload;\n\nvalue = (temp * 9.0) / 5.0 - 459.67; \nmsg.payload=value;\nreturn msg; ","outputs":1,"noerr":0,"x":779,"y":563.000002861023,"wires":[[]]},{"id":"1d6e8fe5.f399d","type":"function","z":"82321e4.b0af8e","name":"cabin pres","func":"var signalk_key=\"environment.outside.pressure\";\n\nif(msg.payload.hasOwnProperty(signalk_key)){\n    msg.payload=msg.payload[signalk_key];\n    return msg;\n    \n\n}","outputs":1,"noerr":0,"x":639,"y":603.000002861023,"wires":[["cffed0ba.ba82b"]]},{"id":"cffed0ba.ba82b","type":"ui_chart","z":"82321e4.b0af8e","name":"","group":"1e14c235.4fc26e","order":2,"width":0,"height":0,"label":"cabin pres","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"604800","cutout":0,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"x":799,"y":603.000002861023,"wires":[[],[]]},{"id":"4b42071a.e35c88","type":"function","z":"82321e4.b0af8e","name":"cabin temp","func":"var signalk_key=\"environment.inside.mainCabin.temperature\";\n\nif(msg.payload.hasOwnProperty(signalk_key)){\n    msg.payload=msg.payload[signalk_key];\n    return msg;\n    \n\n}","outputs":1,"noerr":0,"x":639,"y":643.000002861023,"wires":[["ee81c52e.60bd18"]]},{"id":"5f3ba447.cc53ec","type":"ui_chart","z":"82321e4.b0af8e","name":"cabin temp","group":"1e14c235.4fc26e","order":1,"width":0,"height":0,"label":"cabin temp","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"x":1075.1666870117188,"y":643.0000114440918,"wires":[[],[]]},{"id":"ee81c52e.60bd18","type":"function","z":"82321e4.b0af8e","name":"K to F","func":"var temp = msg.payload;\n\nvalue = (temp * 9.0) / 5.0 - 459.67; \nmsg.payload=value;\nreturn msg; ","outputs":1,"noerr":0,"x":781,"y":643.3333387374878,"wires":[["5f3ba447.cc53ec","ee83bd35.bdac9"]]},{"id":"a26efae0.3bb758","type":"function","z":"82321e4.b0af8e","name":"float","func":"var signalk_key=\"sensors.floatswitch\";\n\nif(msg.payload.hasOwnProperty(signalk_key)){\n    msg.payload=msg.payload[signalk_key];\n    return msg;\n    \n\n}","outputs":1,"noerr":0,"x":630,"y":681,"wires":[["c19bf413.43a098"]]},{"id":"41d6b650.f16a38","type":"websocket-listener","z":"","path":"ws://localhost:3000/signalk/v1/stream","wholemsg":"false"},{"id":"1e14c235.4fc26e","type":"ui_group","z":"","name":"ENVIRONMENT","tab":"8b452ef1.b3d38","order":1,"disp":true,"width":"6"},{"id":"8b452ef1.b3d38","type":"ui_tab","z":"","name":"Tab 2","icon":"dashboard","order":2}]
Reply
#3
(2018-11-07, 03:31 PM)NaturalBornCamper Wrote: So anyways, I managed to make our analog oil pressure sensors work with an Arduino Uno board I had lying around and send it over I2C to OpenPlotter, until I realized that you can only add sensors that were pre-configured in OpenPlotter, 

You can send the data direct to signalk over serial from the arduino, like this - 
Code:
#include "ArduinoJson.h"
int LED_pin = 2;


void setup() {
 // put your setup code here, to run once:
 Serial.begin(4800);

// Serial.println("Starting Up, Please Wait...");
 // initialize digital pin LED_BUILTIN as an output.
 pinMode(LED_pin, OUTPUT);
}

void loop() {
 // put your main code here, to run repeatedly:

 int randon_num = random(1, 300);
 sendSigK("mytest.test.test", randon_num);
 
 int state = digitalRead(LED_pin);
 digitalWrite(LED_pin, !state);
 delay(2000);

}



void sendSigK(String sigKey, float data) {    //    send SigK


 DynamicJsonBuffer jsonBuffer;
 String deltaText;

 //  build delta message
 JsonObject& delta = jsonBuffer.createObject();

 //updated array
 JsonArray& updatesArr = delta.createNestedArray("updates");
 JsonObject& thisUpdate = updatesArr.createNestedObject();   //Json Object nested inside delta [...
 JsonArray& values = thisUpdate.createNestedArray("values"); // Values array nested in delta[ values....
 JsonObject& thisValue = values.createNestedObject();
 thisValue["path"] = sigKey;
 thisValue["value"] = data;

 thisUpdate["Source"] = "ESP11";
 delta.printTo(Serial);
 Serial.println();
}

Then you need to add this to   /home/pi/.signalk/settings.json - underneath the lines >
 },
  "loggingDirectory": "/home/pi/Logs",
  "mdns": false,
  "pipedProviders": [
Code:
{
      "enabled": true,
     "id": "nmeaFromFile",
     "pipeElements": [
       {
         "type": "providers/serialport",
         "options": {
           "device": "/dev/ttyUSB2",
           "baudrate": 4800,
           "toStdout": ["nmea0183out1", "nmea0183out2"]
         },
         "optionMappings": [
           {
             "fromAppProperty": "argv.nmeadevice",
             "toOption": "device"
           },

           {
             "fromAppProperty": "argv.nmeabaudrate",
             "toOption": "baudrate"
           }
         ]
       },
       {
         "type": "providers/from_json",
         "options": {
           "sentenceEvent": "nmea0183in1"
         },
         "optionMappings": [
           {
             "fromAppProperty": "selfId",
             "toOption": "selfId"
           },
           {
             "fromAppProperty": "selfType",
             "toOption": "selfType"
           }
         ]
       }
     ]
   },

Then it should be added as signalk. Opencpn only see NMEA data so you'll need to convert it to NMEA it you want to see the data in that prog.
Reply
#4
(2018-11-08, 01:59 PM)jim321 Wrote: example import clipboard  opencpn is limited to a few things it can display you can use dashboard in NR

Code:
[{"id":"d75f9eeb.e9af2","type":"websocket in","z":"82321e4.b0af8e","name":"ws","server":"41d6b650.f16a38","client":"","x":50,"y":620,"wires":[["83969d8.a84d66","c5c9eb43.d8f238","38780251.f951ae","ba58bc65.7efb9","e81cb99d.1966d8"]]},{"id":"83969d8.a84d66","type":"jsonpath","z":"82321e4.b0af8e","expression":"$.updates..values[*]","split":false,"name":"Signal K delta values","x":240,"y":620,"wires":[["770e578d.94a6d8"]]},{"id":"770e578d.94a6d8","type":"function","z":"82321e4.b0af8e","name":"merge values","func":"var paths={};\nvar arrayLength = msg.payload.length;\nfor (var i = 0; i < arrayLength; i++) {\n    paths[msg.payload[i].path]=msg.payload[i].value;\n}\nmsg.payload = paths;\nreturn msg;","outputs":1,"noerr":0,"x":440,"y":620,"wires":[["abaad182.6b541","4647605c.f27e1","94c51894.715fe8","b2490678.59dba8","a2c7a150.6c2af","963a6ecd.eb9f2","b1b1f8ee.678498","8e6844de.9733a8","28f5b60f.9eb77a","1d6e8fe5.f399d","4b42071a.e35c88","a26efae0.3bb758","ec450371.3822a"]]},{"id":"11507251.ffafbe","type":"ui_template","z":"82321e4.b0af8e","group":"1e14c235.4fc26e","name":"Tempin","order":3,"width":"3","height":"6","format":"<script src=\"/myjs/tween-min.js\"></script>\n<script src=\"/myjs/steelseries-min.js\"></script>\n<script>\nvar tempout;\n    (function(scope){ \n        scope.$watch('msg', function(msg) {\n           if (typeof(msg.value) != \"undefined\") tempout.setValueAnimated(msg.value);\n           //if (typeof(msg.threshold) != \"undefined\") radial4.setThreshold(msg.threshold);\n          // if (typeof(msg.odo) != \"undefined\")radial4.setOdoValue(msg.odo);  \n           //if (typeof(msg.userLed) != \"undefined\") radial4.setUserLedOnOff(msg.userLed);  \n          // if (typeof(msg.trend) != \"undefined\")\n            {\n               // if (msg.trend==1)     radial4.setTrend(steelseries.TrendState.UP);\n                //if (msg.trend==0)     radial4.setTrend(steelseries.TrendState.STEADY);\n               // if (msg.trend==-1)    radial4.setTrend(steelseries.TrendState.DOWN);\n               // if (msg.trend==-2)    radial4.setTrend(steelseries.TrendState.OFF);\n            }\n        });\n    })(scope);\n\n    var sections = [steelseries.Section(0, 25, 'rgba(0, 0, 220, 0.3)'),\n                        steelseries.Section(25, 50, 'rgba(0, 220, 0, 0.3)'),\n                        steelseries.Section(50, 75, 'rgba(220, 220, 0, 0.3)') ],\n\n            // Define one area\n    areas = [steelseries.Section(75, 100, 'rgba(220, 0, 0, 0.3)')],\n\n    tempout = new steelseries.Linear('tempout', {\n            gaugeType: steelseries.GaugeType.TYPE2,\n            width: 140,\n            height: 300,\n            //size: 292,\n            section: sections,\n            area: areas,\n            titleString: \"Inside\",\n            unitString: \"Degrees F\",\n            threshold: 80,\n            lcdVisible: true,\n           \n            //thresholdRising: false,\n           // userLedVisible: true,\n           // useOdometer: true,\n          //  lcdVisible: true,\n           // trendVisible: true\n        });\n                        \n    tempout.setFrameDesign(steelseries.FrameDesign.BRASS);\n    tempout.setValueAnimated(0);\n    tempout.setPointerType(steelseries.PointerType.TYPE9);\n   // radial4.setThreshold(50);\n    //radial4.blinkUserLed(0);\n   // radial4.setOdoValue(0);\n\n\n</script>\n\n<canvas id=\"tempout\" width=\"140\" height=\"300\"></canvas>\n","storeOutMessages":true,"fwdInMessages":true,"x":1198.0003967285156,"y":588.0000686645508,"wires":[[]]},{"id":"28f5b60f.9eb77a","type":"function","z":"82321e4.b0af8e","name":"Water Temp","func":"var signalk_key=\"environment.water.temperature\";\n\nif(msg.payload.hasOwnProperty(signalk_key)){\n    msg.payload=msg.payload[signalk_key];\n    return msg;\n    \n\n}","outputs":1,"noerr":0,"x":639,"y":563.000002861023,"wires":[["ece38a60.7f99c8"]]},{"id":"ee83bd35.bdac9","type":"function","z":"82321e4.b0af8e","name":"","func":"msg.value=msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":976.000057220459,"y":588.0000066757202,"wires":[["11507251.ffafbe"]]},{"id":"ece38a60.7f99c8","type":"function","z":"82321e4.b0af8e","name":"K to F","func":"var temp = msg.payload;\n\nvalue = (temp * 9.0) / 5.0 - 459.67; \nmsg.payload=value;\nreturn msg; ","outputs":1,"noerr":0,"x":779,"y":563.000002861023,"wires":[[]]},{"id":"1d6e8fe5.f399d","type":"function","z":"82321e4.b0af8e","name":"cabin pres","func":"var signalk_key=\"environment.outside.pressure\";\n\nif(msg.payload.hasOwnProperty(signalk_key)){\n    msg.payload=msg.payload[signalk_key];\n    return msg;\n    \n\n}","outputs":1,"noerr":0,"x":639,"y":603.000002861023,"wires":[["cffed0ba.ba82b"]]},{"id":"cffed0ba.ba82b","type":"ui_chart","z":"82321e4.b0af8e","name":"","group":"1e14c235.4fc26e","order":2,"width":0,"height":0,"label":"cabin pres","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"604800","cutout":0,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"x":799,"y":603.000002861023,"wires":[[],[]]},{"id":"4b42071a.e35c88","type":"function","z":"82321e4.b0af8e","name":"cabin temp","func":"var signalk_key=\"environment.inside.mainCabin.temperature\";\n\nif(msg.payload.hasOwnProperty(signalk_key)){\n    msg.payload=msg.payload[signalk_key];\n    return msg;\n    \n\n}","outputs":1,"noerr":0,"x":639,"y":643.000002861023,"wires":[["ee81c52e.60bd18"]]},{"id":"5f3ba447.cc53ec","type":"ui_chart","z":"82321e4.b0af8e","name":"cabin temp","group":"1e14c235.4fc26e","order":1,"width":0,"height":0,"label":"cabin temp","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"x":1075.1666870117188,"y":643.0000114440918,"wires":[[],[]]},{"id":"ee81c52e.60bd18","type":"function","z":"82321e4.b0af8e","name":"K to F","func":"var temp = msg.payload;\n\nvalue = (temp * 9.0) / 5.0 - 459.67; \nmsg.payload=value;\nreturn msg; ","outputs":1,"noerr":0,"x":781,"y":643.3333387374878,"wires":[["5f3ba447.cc53ec","ee83bd35.bdac9"]]},{"id":"a26efae0.3bb758","type":"function","z":"82321e4.b0af8e","name":"float","func":"var signalk_key=\"sensors.floatswitch\";\n\nif(msg.payload.hasOwnProperty(signalk_key)){\n    msg.payload=msg.payload[signalk_key];\n    return msg;\n    \n\n}","outputs":1,"noerr":0,"x":630,"y":681,"wires":[["c19bf413.43a098"]]},{"id":"41d6b650.f16a38","type":"websocket-listener","z":"","path":"ws://localhost:3000/signalk/v1/stream","wholemsg":"false"},{"id":"1e14c235.4fc26e","type":"ui_group","z":"","name":"ENVIRONMENT","tab":"8b452ef1.b3d38","order":1,"disp":true,"width":"6"},{"id":"8b452ef1.b3d38","type":"ui_tab","z":"","name":"Tab 2","icon":"dashboard","order":2}]
[*]

This is working!! I can't believe it!!

Thanks for that, and sorry for the slow answer, we were out at sea with no internet. Then when I saw the block of code, I had no idea what I was supposed to do with it and didn't want to answer with a stupid post so I read some Node-Red documentation before then imported your code Smile

I played around with it a bit and this is very much straightforward and easy to use once I saw a working example, I wish this was in the docs, it would have saved me a lot of time, you're amazing, friend! I'm loving Node-Red so far and will play with it a lot more, especially now that I know we can just poll the Signal K server like this hehe.

(2018-11-09, 01:19 PM)PaddyB Wrote:
(2018-11-07, 03:31 PM)NaturalBornCamper Wrote: So anyways, I managed to make our analog oil pressure sensors work with an Arduino Uno board I had lying around and send it over I2C to OpenPlotter, until I realized that you can only add sensors that were pre-configured in OpenPlotter, 

You can send the data direct to signalk over serial from the arduino, like this - 
Code:
#include "ArduinoJson.h"
int LED_pin = 2;


void setup() {
 // put your setup code here, to run once:
 Serial.begin(4800);

// Serial.println("Starting Up, Please Wait...");
 // initialize digital pin LED_BUILTIN as an output.
 pinMode(LED_pin, OUTPUT);
}

void loop() {
 // put your main code here, to run repeatedly:

 int randon_num = random(1, 300);
 sendSigK("mytest.test.test", randon_num);
 
 int state = digitalRead(LED_pin);
 digitalWrite(LED_pin, !state);
 delay(2000);

}



void sendSigK(String sigKey, float data) {    //    send SigK


 DynamicJsonBuffer jsonBuffer;
 String deltaText;

 //  build delta message
 JsonObject& delta = jsonBuffer.createObject();

 //updated array
 JsonArray& updatesArr = delta.createNestedArray("updates");
 JsonObject& thisUpdate = updatesArr.createNestedObject();   //Json Object nested inside delta [...
 JsonArray& values = thisUpdate.createNestedArray("values"); // Values array nested in delta[ values....
 JsonObject& thisValue = values.createNestedObject();
 thisValue["path"] = sigKey;
 thisValue["value"] = data;

 thisUpdate["Source"] = "ESP11";
 delta.printTo(Serial);
 Serial.println();
}

Then you need to add this to   /home/pi/.signalk/settings.json - underneath the lines >
 },
  "loggingDirectory": "/home/pi/Logs",
  "mdns": false,
  "pipedProviders": [
Code:
{
      "enabled": true,
     "id": "nmeaFromFile",
     "pipeElements": [
       {
         "type": "providers/serialport",
         "options": {
           "device": "/dev/ttyUSB2",
           "baudrate": 4800,
           "toStdout": ["nmea0183out1", "nmea0183out2"]
         },
         "optionMappings": [
           {
             "fromAppProperty": "argv.nmeadevice",
             "toOption": "device"
           },

           {
             "fromAppProperty": "argv.nmeabaudrate",
             "toOption": "baudrate"
           }
         ]
       },
       {
         "type": "providers/from_json",
         "options": {
           "sentenceEvent": "nmea0183in1"
         },
         "optionMappings": [
           {
             "fromAppProperty": "selfId",
             "toOption": "selfId"
           },
           {
             "fromAppProperty": "selfType",
             "toOption": "selfType"
           }
         ]
       }
     ]
   },

Then it should be added as signalk. Opencpn only see NMEA data so you'll need to convert it to NMEA it you want to see the data in that prog.

Thanks for that!

I ended up using Node-Red and all is well, however I didn't know you could inject json into signal K like this, it would have saved me a lot of headaches if I had know it was possible before. I will definitely refer to your code as I am getting some serial data from another pin that I read in Python and I need to send it over to Signal K, so I'll very possibly be using this method!!
Reply
#5
Sending data ... IMO Everything can be routed to SK Some data is best sent as NMEA ie gps, Wind to allow OCPN or other apps pypilot. But in the end it should be in SignalK. Other MCU's Make it possible to extend this.I have had issues with Node-Red but that was a while ago. That said I think NodeRed Rocks displaying data and is very easy to interface with SignalK. I had Problems with resources, stability, and lag.
Mission critical stuff needs to be tested.
Here are a few crude methods of writing and read data to SK and NMEA.
Reading all the docs helps:}
I am not a very skilled coder but I can make it work.
 The difference with boats from IOT is most of time we are reading and reacting to data is much faster.
Your house does not move.
Also your life/comfort of your crew may depend on boat systems working properly...
Code:
import socket
 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 SignalK = '{"updates":[{"$source":"OPserial.epsolar","timestamp":"'+str(timestamp)+'","values":['
 SignalK += ',{"path": "electrical.solar.'+str(unitid)+'.controllerMode","value":"'+str(schgmode)+'"}'
 SignalK += ',{"path": "electrical.batteries.'+str(unitid)+'.temperature","value":'+str(batTemp)+'}'
 SignalK += ',{"path": "electrical.batteries.'+str(unitid)+'.temperature.faultUpper","value":'+str(batwarnupperTemp)+'}'
 SignalK += ',{"path": "electrical.batteries.'+str(unitid)+'.temperature.faultLower","value":'+str(batwarnlowerTemp)+'}'
 SignalK += ',{"path": "electrical.batteries.'+str(unitid)+'.capacity.stateOfCharge","value":'+str(soc)+'}'
 SignalK += ']}]}\n'
 sock.sendto(SignalK, ('localhost', 55559))

Code:
char buf3 [128];

     snprintf(buf3, sizeof buf3, "{\"updates\":[{ \"$source\": \"OPwifi.masthead\",\"values\":[{\"path\": \"navigation.lights\",\"value\":\"%s\" }]}]}\n", lightstate);

     udp.beginPacket(udpAddress, 55561);
     udp.printf(buf3);
     Serial.println(buf3);
     udp.endPacket();
and yet another example of getting 1 key value for a esp32 via wifi.

Code:
if (dt >= 1000) { // output every 1s
   last_time += 1000;
   if ((WiFi.status() == WL_CONNECTED)) { //Check the current connection status
     //WiFiClient client;
     HTTPClient http;
     http.begin("http://192.168.1.7:3000/signalk/v1/api/vessels/self/sensors/anchorLight"); //Specify the URL
     int httpCode = http.GET();                                        //Make the request
     char lightstate[10];
     if (httpCode > 0) { //Check for the returning code
       String payload = http.getString();
       StaticJsonBuffer<500> jsonBuffer;
       JsonObject& root = jsonBuffer.parseObject(payload);
       http.end(); //Free the resources
       int light = root["value"];
       //Serial.println(light);
       if (light == lastlight) {
         return;
       }
       if (light == 1) {
         digitalWrite (ALT_PIN, HIGH);  // turn on the LED
         lastlight = light;
         // Serial.println(light);
         //lights = "anchored";
         strcpy(lightstate, "anchored");
       } else if  (light == 0) {
         digitalWrite (ALT_PIN, LOW);  // turn off the LED
         lastlight = light;
         //lights = "Off";
         strcpy(lightstate, "Off");
       } else {
         Serial.println("Fail");
       }
       //http.end(); //Free the resources
       //return;
     } else {
       Serial.println("get http failed");
     }
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)