OpenMarine

Full Version: UDP MQTT to Openplotter with ESP32
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2 3
Hi all

I'm building my own wind sensor (anemometer) and I want to use an ESP32 to send the signal over WIFI.

First I tried the MQTT but I don't understand the openplotter part of that with username/password etc, so I decided the go the easier way and use UDP.

I used Arduino IDE and send my code to the ESP via serial:

Code:
/*
 *  This sketch sends random data over UDP on a ESP32 device
 *
 */
#include <WiFi.h>
#include <WiFiUdp.h>

// WiFi network name and password:
const char * networkName = ".............";
const char * networkPswd = "..............";

//IP address to send UDP data to:
// either use the ip address of the server or 
// a network broadcast address
const char * udpAddress = "10.10.10.133";
const int udpPort = 3333;

//Are we currently connected?
boolean connected = false;

//The udp library class
WiFiUDP udp;

void setup(){
  // Initilize hardware serial:
  Serial.begin(115200);
  
  //Connect to the WiFi network
  connectToWiFi(networkName, networkPswd);
}

void loop(){
  //only send data when connected
  if(connected){
    //Send a packet
    udp.beginPacket(udpAddress,udpPort);
    udp.printf("Seconds since boot: %lu", millis()/1000);
    udp.endPacket();
  }
  //Wait for 1 second
  delay(1000);
}

void connectToWiFi(const char * ssid, const char * pwd){
  Serial.println("Connecting to WiFi network: " + String(ssid));

  // delete old config
  WiFi.disconnect(true);
  //register event handler
  WiFi.onEvent(WiFiEvent);
  
  //Initiate connection
  WiFi.begin(ssid, pwd);

  Serial.println("Waiting for WIFI connection...");
}

//wifi event handler
void WiFiEvent(WiFiEvent_t event){
    switch(event) {
      case SYSTEM_EVENT_STA_GOT_IP:
          //When connected set 
          Serial.print("WiFi connected! IP address: ");
          Serial.println(WiFi.localIP());  
          //initializes the UDP state
          //This initializes the transfer buffer
          udp.begin(WiFi.localIP(),udpPort);
          connected = true;
          break;
      case SYSTEM_EVENT_STA_DISCONNECTED:
          Serial.println("WiFi lost connection");
          connected = false;
          break;
      default: break;
    }
}

where I have inserted my wifi and password instead of "........" and through serial monitor I can see that it has successfully connected to the Raspberry network.

In Openplotter under KPLEX I added UDP 10.10.10.133 port 3333 but it does not seem to work. Any ideas ?

Kind Regards,
Peter
(2020-11-09, 03:57 PM)Peter— Wrote: [ -> ] Any ideas ?

I have similar sending various sensor data, but sending it as signalk.  Now on micropython but before used this on the arduino ide >>

Code:
//                     send signalk data over UDP
//      *******************************************************
void sendSigK(String sigKey, float data)
{

 if (sendSig_Flag == 1)
 {
   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"] = "ESP32";

   // Send UDP packet
   Udp.beginPacket(remoteIp, remotePort);
   delta.printTo(Udp);
   Udp.println();
   Udp.endPacket();
   delta.printTo(Serial);
   Serial.println();
 }


Micropython here if you want a look (or a play) 
https://github.com/boatybits/boatymonpy
Still a work in progress but what there is works Smile
So when you say send it to signalK do you mean 10.10.10.1:3000 ("hostip":3000) then? I tried that but it will does not work. Is there something wrong in my code I don't get it ? (your code is pretty similar). Is there a good guide on this somewhere?

I would love to use micropython but I don't fully understand it yet. Could you give a high level overview of what your *.py scripts do?

I see your boot.py points at webrepl and already there I'm lost. If your boot doesn't point at your main.py how does it get executed then? Also, do you use MQTT or UDP? And does it go through the internet or local wifi?

I just want to be able to establish the connections, the programming of the sensors should be easy. I just don't understand how to commination work and have never programmed it before...

Kind Regards,
Peter

I now changed the code to the following:

Code:
#include "WiFi.h"
#include "AsyncUDP.h"

const char * ssid = "............";
const char * password = "...................";

AsyncUDP udp;

void setup()
{
   Serial.begin(115200);
   WiFi.mode(WIFI_STA);
   WiFi.begin(ssid, password);
   if (WiFi.waitForConnectResult() != WL_CONNECTED) {
       Serial.println("WiFi Failed");
       while(1) {
           delay(1000);
       }
   }
   if(udp.connect(IPAddress(10,10,10,1), 3333)) {
       Serial.println("UDP connected");
       udp.onPacket([](AsyncUDPPacket packet) {
           Serial.print("UDP Packet Type: ");
           Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast");
           Serial.print(", From: ");
           Serial.print(packet.remoteIP());
           Serial.print(":");
           Serial.print(packet.remotePort());
           Serial.print(", To: ");
           Serial.print(packet.localIP());
           Serial.print(":");
           Serial.print(packet.localPort());
           Serial.print(", Length: ");
           Serial.print(packet.length());
           Serial.print(", Data: ");
           Serial.write(packet.data(), packet.length());
           Serial.println();
           //reply to the client
           packet.printf("Got %u bytes of data", packet.length());
       });
       //Send unicast
       udp.print("Hello Server!");
   }
}

void loop()
{
   delay(5000);
   //Send broadcast on port 3333
   udp.broadcastTo("this is now working", 3333);
   Serial.println("Sending packages....");
}

If I open a terminal on my PI and write:
Code:
netcat -ul 3333

Then I pickup the message from my client (the ESP32) - so that is working which is great.

Now, why the h*** can I not pick up this message using KPLEX? And how do I send it to signalK? And finally, how do I get it into OpenCPN as a wind measurement?

Kind Regards,
Peter
Updated my loop function should anyone be interested. The udp.print can send numbers - here it sends the time in seconds since it was turned on - every second...

Code:
void loop()
{
   delay(1000);
   //Send broadcast on port 3000
//    udp.broadcastTo("this is now working", 3000);
   Serial.println("Sending packages....    ");
   Serial.println(millis()/1000);
   udp.print(millis()/1000);
}
Now I know how to send the data - but how do I get it into SignalK or OpenCPN is the big question...
Okay I've been looking at this all evening and its just absolute horse-crap OMG something that simple has to be so difficult what a BS.

Anyhow, here is a reference: 
I'll see if I can get these modules on the ESP32 and maybe get it talking with the SignalK software.

At least I got the UDP working so that a win and pretty easy, but the M***F*** NMEA protocol and SignalK BS proprietary s*** that is what will take forever to solve. I'll record a video or make a guide if I get this BS nut cracked.

Br, Peter
I can relate to the frustration, but calling other peopls's software s*** is not the best way to get help.

Despite that here goes....

Your post title is misleading: UDP and MQTT don't have practically anything to do with each other. Please think about others who are reading what you write, maybe much later - you are adding confusion.

Your first example seems to be sending UDP to itself as it uses localIP.

Here's a real life ESP8266 example to send SK over UDP that you can adapt: https://gist.github.com/tkurki/d8d45dfb3...1e8e95a45b

Netcat is a great way to test that your messages make to the server - points for sharing that!

SK Server does not accept UDP input by default, you need to add a Data Connection:
- Data type: Signal K
- Signal K Source. UDP
(2020-11-10, 09:03 AM)tkurki Wrote: [ -> ]I can relate to the frustration, but calling other peopls's software s*** is not the best way to get help.

Despite that here goes....

Your post title is misleading: UDP and MQTT don't have practically anything to do with each other. Please think about others who are reading what you write, maybe much later - you are adding confusion.

Your first example seems to be sending UDP to itself as it uses localIP.

Here's a real life ESP8266 example to send SK over UDP that you can adapt: https://gist.github.com/tkurki/d8d45dfb3...1e8e95a45b

Netcat is a great way to test that your messages make to the server - points for sharing that!

SK Server does not accept UDP input by default, you need to add a Data Connection:
- Data type: Signal K
- Signal K Source. UDP

I agree with your comment but this is still very frustrating and I’ve been reading countless of other forums and no clear solutions are available for a beginner like me. It’s all “here is my code” stuff and it doesn’t help much if you are a hobby programmer.

As for the title I was uncertain about going the Udo or mqtt path and hence why they were both included. At the time I was trying micropython and mqtt which honestly no-one should touch if you are a beginner.

So, since my UDP is working is there something I can do on the server/Openplotter side to get this into SignalK? Can node red help with this? And how do I do it?

When you say add a data connection, do you mean in KPLEX? I have tried that it didn’t work..

Kind regards,
Peter

ps: once I get this solved I’ll make a clear step by step guide for anyone to use in the future
(2020-11-10, 09:27 AM)Peter— Wrote: [ -> ]So, since my UDP is working is there something I can do on the server/Openplotter side to get this into SignalK? Can node red help with this? And how do I do it?

When you say add a data connection, do you mean in KPLEX? I have tried that it didn’t work..

It's simple to add a connection - just go to server- data connections and add one, set to data type signalk and UDP. Then send a signalk updates json over udp to that port. 



[Image: wl01v20.png]
Please reread my answer: "SK Server does not accept UDP input by default, you need to add a Data Connection".

SK Server means Signal K Server, not Kplex, Node-RED, MQTT or some other component. I thought it would be pretty obvious from the context.

While your "UDP is working" you need to send to the correct address and in correct format:
- send Signal K data in JSON (see the code I linked)
- send to your server's address and port (this may be already working per your netcat) OR send a broadcast message (see the code I linked)
Thanks guys that helps

I understood your comment tkurki I just didn’t know how to do it, but it’s obviously dead easy - thanks PaddyB.

So the final part of the problem now seems to be the Java JSON format which I understand nothing about. But I guess it’s a format where I have to state e.g that it’s a temp value and it’s measure in degC, or a wind value in this case, measured in knts.

I can see that in node red it’s possible to add a json node and this is something I would like to investigate if someone could just let me know how the standard format should look like. I’ll study it a bit maybe it will become obvious

So I studied a bit more and now understand that you can send anything as json, so if I just send a message like temp, c, number will SignalK then automatically understand it’s a temperature, it’s in degree c and it’s that number? Or does SignalK require a specific json setup?

Thanks guys
Peter

Ps: tkurki, I know you have provided me the answer in your code I just don’t understand it so please do not be frustrated with me...

Ok I found this:
http://signalk.org/specification/1.0.0/d...ranch.html

One more step closer I think.
Pages: 1 2 3