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
UDP Issues - UDP message to SignalK from ESP8266
#1
Hi,
struggling along with SignalK and sensors. I changed from Arduino to ESP8286 wanting to reduce cabling on our boat and go for WiFi instead.

I have an ESP8286 sketch that meassures a voltage and packs this into an SignalK message to send to the SignalK server on my OpenPlotter RPI.
In the SignalK Diagnostics it doesn't show up using UDP port 55557 so I started to debug.

- First I used netcat on my RPI (with another UDP port as 55557 is in use - I assume by the SignalK server. I used 9993....) and netcat then nicely displays the JSON data as I assume SignalK wants it.

- Then I used netcat (again on my RPI) and send the same JSON message (copied from the first try) with UDP to port 55557 and then it shows up nicely in SignalK diagnostics....

Is there some sort of SignalK definition I have to do to allow other IP addresses to send UDP messages  to the SignalK server as it works nicely from netcat (on localhost)???

Can't figure this one out - anyone having some insights??? Huh

The code I use (obvioulsy with my current SSID and pwd) 
/Lars

Code:
/********************************************************************************
*
* Sending UDP messages to the OpenPlotter SignalK server using the ESP8266
* and WiFi in an IoT approach
*
* Adopted from Ole W. Saastad, 15th Oct 2017.
* https://sites.google.com/site/olewsaa/yacht-server-with-raspberry
* https://github.com/olewsaa/Yacht-computer
*
* V 0.1 - 2018-02-07 - LD - Initial version, working with netcat but not to
*                           SignalK server directly
* *******************************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "MySSID";
const char* password = "MyPwd";
const uint16_t SK_port = 55557;
//const uint16_t SK_port = 9933; // Used when testing with netcat (nc -ul 9933) on RPI
const char * SK_host = "192.168.1.89"; // RPI 3 with OpenPlotter

WiFiUDP Udp;

void setup() {
 Serial.begin(38400);
 delay(10);
 pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output

 // Connect to WiFi network
 Serial.println();
 Serial.println();
 Serial.print("Connecting to ");
 Serial.println(ssid);

 WiFi.mode(WIFI_STA);
 WiFi.begin(ssid, password);

 while (WiFi.status() != WL_CONNECTED) {
   delay(500);
   Serial.print(".");
 }
 Serial.println("");
 Serial.println("WiFi connected");
 Serial.println("IP address: ");
 Serial.println(WiFi.localIP());
 delay(500);
 Udp.begin(SK_port);
} /* End setup */

void loop() {
 double U;
 int val;
 char Us[6];
 String cmd;

 val = analogRead(A0); // Read the analog input on the ESP2866.
 U = ((double)val / (double)1023.0) * 19.576; // Calibrated using a multimeter, check this value carefully.
 dtostrf(U, 3, 2, Us);
 
 cmd =  "{\"updates\": [{\"$source\": \"ESP8266\",\"values\":[ {\"path\":\"electrical.service.voltage\",\"value\":";
 cmd += Us; cmd += "}]}]}\0"; // Not sure if NULL is needed or not, but it's good custom to terminate with NULL:

 digitalWrite(LED_BUILTIN, LOW); // Turn the LED on while we transfer the data.
 // onvert from String to character array as Udp.write will not accept string type argument.
 char cmd2[cmd.length() + 1]; // Counting from zero, add one.
 strncpy(cmd2, cmd.c_str(), sizeof(cmd2)); // Convert to char array as Udp.write don't accept strings
 
 Udp.beginPacket(SK_host, SK_port); // Connect to to server and prepare for UDP transfer.
 Udp.write(cmd2); // Send the message to the SignalK server.
 Udp.endPacket(); // End the connection.
 Serial.println(cmd2); Serial.print(" Message length is: "); Serial.println(sizeof(cmd2));

 digitalWrite(LED_BUILTIN, HIGH);  // Turn the LED off by making the voltage HIGH.

 Serial.println("wait 2 sec...");
 delay(2000);
}  /* End infinite loop */

BTW, I'm using the lates (current) version of openplotter....

I tried by piping the input i'm reading from port 9933 to port 55557
nc -ul 9933 | nc-4u -w1 192.168.1.89 55557

but nothing shows up in SignalK diagnostics...

I'm sure there is something very basic I'm doing wrong but I fail to figure out what....
/Lars
Reply
#2
Hi, I think ESP8266 is an excellent piece of hardware for designing simple projects. Firstly, you have to set up at the PC terminal by using network debugging tools, then ESP8266 UDP test will be sent to ESP8266 UDP port. When the UDP data are received by ESP8266, the same message will be sent to the PC terminal, too. It helps me very much to solve my doubt on working of UDP and its issues.
Reply
#3
I've got it working here just with  dummy message, actually 2 of esp8266 sending SOG & COG messages. 

Code is just a messy try out but works this end. The code can be uploaded over the air as well, no need to plug into the 8266 - upload over wifi, really handy. 
http://esp8266.github.io/Arduino/version...dates.html

Another way to go is to use easyesp and send the data as MQTT which openplotter can then map to a signalk update. 

Code:
#include <ESP8266WiFi.h>

#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

const char* ssid = "openplotter";
const char* password = "12345678";

unsigned int localPort = 55557;      //  port to  send  UDP packets



// A UDP instance to let us send and receive packets over UDP
WiFiUDP Udp;

void setup() {
 Serial.begin(115200);
 Serial.println("Booting");
 WiFi.mode(WIFI_STA);
 WiFi.begin(ssid, password);
 while (WiFi.waitForConnectResult() != WL_CONNECTED) {
   Serial.println("Connection Failed! Rebooting...");
   delay(5000);
   ESP.restart();
 }

 // Port defaults to 8266
 // ArduinoOTA.setPort(8266);

 // Hostname defaults to esp8266-[ChipID]
 // ArduinoOTA.setHostname("myesp8266");

 // No authentication by default
 // ArduinoOTA.setPassword("admin");

 // Password can be set with it's md5 value as well
 // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
 // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

 ArduinoOTA.onStart([]() {
   String type;
   if (ArduinoOTA.getCommand() == U_FLASH)
     type = "sketch";
   else // U_SPIFFS
     type = "filesystem";

   // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
   Serial.println("Start updating " + type);
 });
 ArduinoOTA.onEnd([]() {
   Serial.println("\nEnd");
 });
 ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
   Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
 });
 ArduinoOTA.onError([](ota_error_t error) {
   Serial.printf("Error[%u]: ", error);
   if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
   else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
   else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
   else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
   else if (error == OTA_END_ERROR) Serial.println("End Failed");
 });
 ArduinoOTA.begin();
 Serial.println("Ready");
 Serial.print("IP address: ");
 Serial.println(WiFi.localIP());
 Udp.begin(localPort);
 pinMode(2, OUTPUT);
}

void loop() {
 ArduinoOTA.handle();
 
 digitalWrite(2, HIGH); // turn the LED on (HIGH is the voltage level)
 delay(500); // wait for 1/2 second
 digitalWrite(2, LOW); // turn the LED off by making the voltage LOW
 delay(1000);

 
 int value = random(20);  // create a random vaue between 0 and 20 to simulate SOG
 String tempString = "{\"updates\": [{\"$source\": \"OPsimulation\",\"values\":[ {\"path\":\"navigation.courseOverGroundTrue\",\"value\":\"";   //  create 1st part of signalk string
     
 tempString += String(value);  //add simulated SOG to string
 tempString += "\"}]}]}\n" ;   // finish the signelK string

 char  replyPacekt[tempString.length()+1] ;  //initialise char array for UDP

 tempString.toCharArray(replyPacekt, tempString.length()+1);   // add the signalk string to char array


// send the char array as UDP
 IPAddress  ip = IPAddress(10,10,10,1);
 Udp.beginPacket(ip, localPort);    //signalk server on Pi listens on 10.10.10.1 port 55557
 Udp.write(replyPacekt);
 Udp.endPacket();

}
Reply
#4
FYI:

After an Problem where i only got the first Sentence out of my UDP Stream with the
normal Netcat:
$ nc -ul portnumber

found this solution by adding an timeout 1sek:
$ nc -kluvw 1 xxx.xxx.xxx.255 portnumber
or
$ nc -kluvw 1 portnumber
(if you are on the same host)

why i did this? I found these NMEA Strings from my UBLOX-7 USB Stick.
Pretty shure they are new, never saw these before....

$IIHDG,356.26,,,,*7D
$IIZDA,120111.020,29,04,2020,,*4E
$GPVTG,,T,,M,0.028,N,0.052,K,A*2E
$GPGGA,120111.00,4818.36018,N,01418.21870,E,1,06,1.65,250.8,M,43.9,M,,*52
$GPGSA,A,3,12,25,14,02,26,31,,,,,,,2.62,1.65,2.04*05
$GPGSV,4,1,13,02,31,051,39,05,06,095,,06,07,032,09,12,36,100,20*73
$GPGSV,4,2,13,14,18,260,36,18,17,180,14,21,15,188,,24,00,158,*7F
$GPGSV,4,3,13,25,69,094,20,26,11,292,20,29,77,241,10,31,44,298,45*79
$GPGSV,4,4,13,32,08,238,15*4F
$GPGLL,4818.36018,N,01418.21870,E,120111.00,A,A*62
$GPTXT,01,01,01,NMEA unknown msg*58
$GPTXT,01,01,01,NMEA unknown msg*58
$GPTXT,01,01,01,NMEA unknown msg*58
$GPTXT,01,01,01,NMEA unknown msg*58
$GPTXT,01,01,01,NMEA unknown msg*58
$GPTXT,01,01,01,NMEA unknown msg*58
$GPTXT,01,01,01,NMEA unknown msg*58
$GPTXT,01,01,01,NMEA unknown msg*58
$GPTXT,01,01,01,NMEA unknown msg*58
$GPTXT,01,01,01,NMEA unknown msg*58
$GPTXT,01,01,01,NMEA unknown msg*58


Checksums are fine, the Position takes longer in my opinion. Has someone a Clue on this?

Holger
Reply
#5
Hello Openskippers

just found an solution in the web:

The GPS makes an internal echo, to disable use an one shot command line:
/bin/stty -F /dev/ttyOP_gps -echo

or better put an service daemon to the right places....
https://raspberrypi.stackexchange.com/qu...gps-module

from the vendor comes this:
https://portal.u-blox.com/s/question/0D5...sg-meaning



But this is all workaround, so do it correct the OpenPlotter way.

Lets use the allready installed App GPSD:

Configure "use GPSD" and not the "signalk serial" connection in "Serial App".
In SignalK Server make an new NMEA Connection with "NMEA 0183 Source" GPSD and host "localhost" and port "2947" to get gps into SK.

Voiallah, {SIC}
all is working perfect, the specialized GPSD application also has an nice Command line:
$ gpsmon

and my internal UDP Stream works again (your port may be be different)
$ nc -kluvw 1 55550
$IIZDA,133326.020,29,04,2020,,*4A
$GPVTG,,T,,M,0.731,N,1.354,K,A*25
$GPGGA,133326.00,4818.34802,N,01418.21071,E,1,07,1.33,316.4,M,43.9,M,,*53
$GPGSA,A,3,29,18,21,31,26,25,16,,,,,,2.41,1.33,2.01*00
$GPGSV,3,1,12,04,03,317,,05,20,057,23,09,00,348,,12,01,124,*7D
$GPGSV,3,2,12,16,17,303,23,18,61,169,22,20,02,165,,21,59,184,22*7B
$GPGSV,3,3,12,25,30,129,17,26,49,300,29,29,60,060,20,31,44,238,13*73
$GPGLL,4818.34802,N,01418.21071,E,133326.00,A,A*6E
$IIMMB,28.8504,I,0.9770,B*73

CIAO,
Holger
Reply
#6
The version 1.x of OpenPlotter used the port 55557 as UDP port for SignalK. In the new version there is no UDP port set up at 55557.
Opening the signalK web interface, localhost:3000 and selecting the left side menu at Server and Connections it's possible to add 
a new source. In my case ID=OrangePi, UDP, port 55557 and no self mapping. Press apply and it's all back where it used to be in the 
old version.  

The version 2 now uses port 55557 and  a simple python script like this can test the connectivity:

#!/usr/bin/env python
import time, socket
# Initiate socket 
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# socket.AF_INET is  Internet
# socket.SOCK_DGRAM) is  UDP

print("Trying to send values to SignalK")
while True:
    t=input("Please enter a number: ")
    x = float(t)
    SignalK='{"updates": [{"$source": "OrangePi","values":[ {"path":"OrangePi.signalK.manual","value":'+format(x,'5.3f')+'}]}]}'
    print(SignalK)
    sock.sendto(SignalK, ('192.168.1.169', 55557))
   

In my ideal boat there should only be cables for 12V, all signal cables should be replaced by wireless communication, 
SignalK is step in the right direction.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)