2019-02-08, 10:31 PM
(2019-02-08, 02:57 AM)abarrow Wrote: It's Node Red. I'll send you the script when I get home.
Here's the script. It is super simple - just connect to a TCP port (which is configured in OpenPlotter to send out NMEA strings), and output to MQTT.
Code:
[
{
"id": "d7c474e4.e397e8",
"type": "tab",
"label": "Flow 1",
"disabled": false,
"info": ""
},
{
"id": "2bb5840f.59abac",
"type": "debug",
"z": "d7c474e4.e397e8",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"x": 719,
"y": 167,
"wires": []
},
{
"id": "a00c6215.e7772",
"type": "mqtt out",
"z": "d7c474e4.e397e8",
"name": "",
"topic": "inTopic",
"qos": "",
"retain": "",
"broker": "30d4d987.926566",
"x": 990,
"y": 348,
"wires": []
},
{
"id": "1e891e14.3239c2",
"type": "tcp in",
"z": "d7c474e4.e397e8",
"name": "",
"server": "client",
"host": "127.0.0.1",
"port": "44444",
"datamode": "stream",
"datatype": "utf8",
"newline": "\\n",
"topic": "",
"base64": false,
"x": 265,
"y": 326,
"wires": [
[
"a00c6215.e7772",
"2bb5840f.59abac"
]
]
},
{
"id": "30d4d987.926566",
"type": "mqtt-broker",
"z": "",
"name": "",
"broker": "<YOUR MQTT BROKER ADDRESS>",
"port": "1883",
"clientid": "",
"usetls": false,
"compatmode": true,
"keepalive": "60",
"cleansession": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "howdy partner",
"closeTopic": "",
"closeQos": "0",
"closePayload": "",
"willTopic": "",
"willQos": "0",
"willPayload": ""
}
]
Code:
/*
Basic MQTT Connection for NMEA
*/
#include <WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#include <TinyGPS++.h>
#include <LiquidCrystal_I2C.h>
// Update these with values suitable for your network.
const char* ssid = "<YOUR SSID>";
const char* password = "<YOUR WIFI PASSWORD>";
const char* mqtt_server = "10.10.10.1";
const char* mqttUser = "pi";
const char* mqttPassword = "<YOUR MQTT PASSWORD>";
// The TinyGPS++ object
TinyGPSPlus gps;
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
// set the LCD number of columns and rows
int lcdColumns = 20;
int lcdRows = 4;
String DBT = "";
String northSouth = "N ";
String eastWest = "E ";
double latRaw;
double lonRaw;
String latiTude = "";
String longiTude = "";
// set LCD address, number of columns and rows
// if you don't know your display address, run an I2C scanner sketch
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);
//Create the knot character
byte customChar[8] = {
0b10000,
0b10100,
0b11000,
0b10100,
0b00010,
0b00111,
0b00010,
0b00011
};
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
lcd.setCursor(0,0);
lcd.print("SSID: ");
Serial.println(ssid);
lcd.setCursor(7,0);
lcd.print(ssid);
WiFi.begin(ssid, password);
int dot_cur = 0;
lcd.setCursor(0,1);
int reset_index = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
lcd.print(".");
//If WiFi doesn't connect in 30 seconds, do a software reset
reset_index ++;
if (reset_index > 60) {
Serial.println("WIFI Failed - restarting");
lcd.setCursor(0,2);
lcd.print("No WIFI: restarting");
ESP.restart();
}
}
randomSeed(micros());
Serial.println("");
lcd.clear();
Serial.println("WiFi connected");
lcd.setCursor(0,0);
lcd.print("WiFi connected");
Serial.println("IP address: ");
lcd.setCursor(0,2);
lcd.print("IP: ");
Serial.println(WiFi.localIP());
lcd.setCursor(5,2);
lcd.print(WiFi.localIP());
}
void setup_lcd(){
// initialize LCD
lcd.init();
// turn on LCD backlight
lcd.backlight();
// set cursor to first column, first row
lcd.setCursor(0, 0);
}
void callback(char* topic, byte* payload, unsigned int length) {
for (int i=0;i<length;i++) {
if (gps.encode(*payload++))
displayInfo();
}
Serial.println();
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str(),mqttUser,mqttPassword)) {
Serial.println("connected");
client.subscribe("inTopic");
//arrow characters in the upper right when MQTT is connected
lcd.setCursor(19,0);
lcd.print(char(127));
lcd.setCursor(19,1);
lcd.print(char(126));
delay(500);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
lcd.setCursor(0,1);
lcd.print("MQTT Failed");
lcd.setCursor(0,2);
lcd.print("rc=");
lcd.print(client.state());
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
setup_lcd();
// create a new custom character for knot
lcd.createChar(0, customChar);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
//Delay 5 secs so we can see what happened
delay (5000);
lcd.clear();
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
}
void displayInfo()
{
Serial.print(F("Location: "));
if (gps.location.isValid())
{
latRaw = gps.location.lat();
Serial.print(latRaw);
if (latRaw < 0){
northSouth = "S ";
}
else
{
northSouth = "N ";
}
latRaw = abs(latRaw);
int latDeg = latRaw;
Serial.println(latDeg);
double latMins = (latRaw - latDeg) * 60;
Serial.println(latMins);
latiTude = northSouth;
if (latDeg < 100){
latiTude += " ";
}
else if (latDeg < 10) {
latiTude += " ";
}
latiTude += latDeg;
latiTude += char(223);
if (latMins <10)
latiTude += " ";
latiTude += String(latMins,3);
latiTude += "\' ";
lcd.setCursor(0,0);
lcd.print("LAT: ");
lcd.print(latiTude);
Serial.print(F(","));
Serial.print(gps.location.lng(), 6);
lonRaw = gps.location.lng();
if (lonRaw < 0){
eastWest = "W ";
}
else
{
eastWest = "E ";
}
lonRaw = abs(lonRaw);
int lonDeg = lonRaw;
double lonMins = (lonRaw - lonDeg) * 60;
longiTude = eastWest;
if (lonDeg < 100){
longiTude += " ";
}
else if (lonDeg < 10) {
longiTude += " ";
}
longiTude += lonDeg;
longiTude += char(223);
if (lonMins < 10)
longiTude += " ";
longiTude += String(lonMins,3);
longiTude += "\' ";
lcd.setCursor(0,1);
lcd.print("LON: ");
lcd.print(longiTude);
}
else
{
Serial.print(F("INVALID"));
lcd.setCursor(0,0);
lcd.print("========NAN========");
lcd.setCursor(0,1);
lcd.print("========NAN========");
}
if (gps.speed.isValid()) {
lcd.setCursor(10,2);
lcd.print("SOG: ");
lcd.print(gps.speed.knots(),1);
//lcd.print("K");
lcd.write((uint8_t)0);
if (gps.speed.knots() < 10){
lcd.print(" ");
}
}
else
{
Serial.print(F("INVALID"));
lcd.setCursor(10,2);
lcd.print("===NAN===");
}
if (gps.course.isValid()){
Serial.println("");
Serial.print(F("COG="));
lcd.setCursor(0,2);
lcd.print("COG: ");
Serial.println(gps.course.deg());
lcd.print(gps.course.deg(), 0);
lcd.print(char(223));
if (gps.course.deg()<10){
lcd.print(" ");
}
else if (gps.course.deg()<100){
lcd.print(" ");
}
}
else
{
Serial.print(F("INVALID"));
lcd.setCursor(0,2);
lcd.print("==NAN==");
}
Serial.print(F(" Date/Time: "));
if (gps.date.isValid())
{
lcd.setCursor(10,3);
Serial.print(gps.date.month());
lcd.print(gps.date.month());
Serial.print(F("/"));
lcd.print(F("/"));
Serial.print(gps.date.day());
lcd.print(gps.date.day());
Serial.print(F("/"));
lcd.print(F("/"));
Serial.print(gps.date.year());
lcd.print(gps.date.year());
}
else
{
Serial.print(F("INVALID"));
lcd.setCursor(10,3);
lcd.print("===NAN===");
}
Serial.print(F(" "));
if (gps.time.isValid())
{
lcd.setCursor(0,3);
if (gps.time.hour() < 10) {
Serial.print(F("0"));
lcd.print(F("0"));
}
lcd.print(gps.time.hour());
Serial.print(gps.time.hour());
Serial.print(F(":"));
lcd.print(":");
if (gps.time.minute() < 10){
Serial.print(F("0"));
lcd.print(F("0"));
}
Serial.print(gps.time.minute());
lcd.print(gps.time.minute());
Serial.print(F(":"));
lcd.print(":");
if (gps.time.second() < 10) {
Serial.print(F("0"));
lcd.print(F("0"));
}
Serial.print(gps.time.second());
lcd.print(gps.time.second());
Serial.print(F("."));
if (gps.time.centisecond() < 10){
Serial.print(F("0"));
}
Serial.print(gps.time.centisecond());
lcd.print("Z");
}
else
{
Serial.print(F("INVALID"));
lcd.setCursor(0,3);
lcd.print("===NAN===");
}
Serial.println();
}