|
| 1 | +/* |
| 2 | + Use ESP32 WiFi to get AssistNow Online (MGA) data from PointPerfect (broker) as a Client using MQTT |
| 3 | + By: Paul Clark / SparkFun |
| 4 | + Date: March 9th, 2022 |
| 5 | + Based on original code by: u-blox AG / Michael Ammann |
| 6 | + License: MIT. See license file for more information but you can |
| 7 | + basically do whatever you want with this code. |
| 8 | +
|
| 9 | + This example shows how to obtain AssistNow Online (MGA) data from a PointPerfect Broker over WiFi |
| 10 | + and push it over I2C to a ZED-F9x. |
| 11 | + It's confusing, but the Arduino is acting as a 'client' to the PointPerfect service. |
| 12 | +
|
| 13 | + You will need to have a valid u-blox Thingstream account and have a PointPerfect Thing and payed plan. |
| 14 | + To sign up, go to: https://portal.thingstream.io/app/location-services/things |
| 15 | +
|
| 16 | + This is a proof of concept to show how to connect via MQTT to get AssistNow MGA data. |
| 17 | +
|
| 18 | + For more information about MQTT, SPARTN and PointPerfect Correction Services |
| 19 | + please see: https://www.u-blox.com/en/product/pointperfect |
| 20 | + |
| 21 | + Feel like supporting open source hardware? |
| 22 | + Buy a board from SparkFun! |
| 23 | + SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 |
| 24 | + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 |
| 25 | + SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 |
| 26 | +
|
| 27 | + Hardware Connections: |
| 28 | + Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus |
| 29 | + If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425) |
| 30 | + Open the serial monitor at 115200 baud to see the output |
| 31 | +*/ |
| 32 | +#include <WiFi.h> |
| 33 | +#include <WiFiClientSecure.h> |
| 34 | +#include <ArduinoMqttClient.h> // Click here to get the library: http://librarymanager/All#ArduinoMqttClient |
| 35 | +#include "secrets.h" |
| 36 | + |
| 37 | +#include <SparkFun_u-blox_GNSS_Arduino_Library.h> // Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS |
| 38 | +SFE_UBLOX_GNSS myGNSS; |
| 39 | + |
| 40 | +//Global variables |
| 41 | +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
| 42 | +long lastReceived_ms = 0; //5 RTCM messages take approximately ~300ms to arrive at 115200bps |
| 43 | +int maxTimeBeforeHangup_ms = 10000; //If we fail to get a complete RTCM frame after 10s, then disconnect from caster |
| 44 | +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
| 45 | + |
| 46 | +void setup() |
| 47 | +{ |
| 48 | + Serial.begin(115200); |
| 49 | + while (!Serial); |
| 50 | + Serial.println(F("PointPerfect AssistNow testing")); |
| 51 | + |
| 52 | + Wire.begin(); //Start I2C |
| 53 | + |
| 54 | + if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port |
| 55 | + { |
| 56 | + Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); |
| 57 | + while (1); |
| 58 | + } |
| 59 | + |
| 60 | + Serial.println(F("u-blox module connected")); |
| 61 | + myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise |
| 62 | + myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_SPARTN); |
| 63 | + |
| 64 | + myGNSS.setNavigationFrequency(1); //Set output in Hz. |
| 65 | + |
| 66 | + Serial.print(F("Connecting to local WiFi")); |
| 67 | + WiFi.begin(ssid, password); |
| 68 | + while (WiFi.status() != WL_CONNECTED) { |
| 69 | + delay(500); |
| 70 | + Serial.print(F(".")); |
| 71 | + } |
| 72 | + Serial.println(); |
| 73 | + |
| 74 | + Serial.print(F("WiFi connected with IP: ")); |
| 75 | + Serial.println(WiFi.localIP()); |
| 76 | + |
| 77 | + while (Serial.available()) Serial.read(); |
| 78 | +} |
| 79 | + |
| 80 | +void loop() |
| 81 | +{ |
| 82 | + if (Serial.available()) |
| 83 | + { |
| 84 | + beginClient(); |
| 85 | + while (Serial.available()) Serial.read(); //Empty buffer of any newline chars |
| 86 | + } |
| 87 | + |
| 88 | + Serial.println(F("Press any key to start MQTT Client.")); |
| 89 | + |
| 90 | + delay(1000); |
| 91 | +} |
| 92 | + |
| 93 | +WiFiClientSecure wifiClient = WiFiClientSecure(); |
| 94 | +MqttClient mqttClient(wifiClient); |
| 95 | + |
| 96 | +void mqttMessageHandler(int messageSize) { |
| 97 | + uint8_t mgaData[512 * 4]; //Most incoming data is around 500 bytes but may be larger |
| 98 | + int mgaCount = 0; |
| 99 | + Serial.print(F("Pushed data from ")); |
| 100 | + Serial.print(mqttClient.messageTopic()); |
| 101 | + Serial.println(F(" topic to ZED")); |
| 102 | + while (mqttClient.available()) |
| 103 | + { |
| 104 | + char ch = mqttClient.read(); |
| 105 | + //Serial.write(ch); //Pipe to serial port is fine but beware, it's a lot of binary data |
| 106 | + mgaData[mgaCount++] = ch; |
| 107 | + if (mgaCount == sizeof(mgaData)) |
| 108 | + break; |
| 109 | + } |
| 110 | + |
| 111 | + if (mgaCount > 0) |
| 112 | + { |
| 113 | + //Push MGA data to GNSS module over I2C |
| 114 | + myGNSS.pushRawData(mgaData, mgaCount, false); |
| 115 | + lastReceived_ms = millis(); |
| 116 | + } |
| 117 | +} |
| 118 | + |
| 119 | +//Connect to MQTT broker, receive MGA, and push to ZED module over I2C |
| 120 | +void beginClient() |
| 121 | +{ |
| 122 | + Serial.println(F("Subscribing to Broker. Press key to stop")); |
| 123 | + delay(10); //Wait for any serial to arrive |
| 124 | + while (Serial.available()) Serial.read(); //Flush |
| 125 | + |
| 126 | + while (Serial.available() == 0) |
| 127 | + { |
| 128 | + //Connect if we are not already |
| 129 | + if (wifiClient.connected() == false) |
| 130 | + { |
| 131 | + // Connect to AWS IoT |
| 132 | + wifiClient.setCACert(AWS_CERT_CA); |
| 133 | + wifiClient.setCertificate(AWS_CERT_CRT); |
| 134 | + wifiClient.setPrivateKey(AWS_CERT_PRIVATE); |
| 135 | + mqttClient.setId(MQTT_CLIENT_ID); |
| 136 | + mqttClient.setKeepAliveInterval(60*1000); |
| 137 | + mqttClient.setConnectionTimeout( 5*1000); |
| 138 | + if (!mqttClient.connect(AWS_IOT_ENDPOINT, AWS_IOT_PORT)) { |
| 139 | + Serial.print(F("MQTT connection failed! Error code = ")); |
| 140 | + Serial.println(mqttClient.connectError()); |
| 141 | + return; |
| 142 | + } else { |
| 143 | + Serial.println(F("You're connected to the PointPerfect MQTT broker: ")); |
| 144 | + Serial.println(AWS_IOT_ENDPOINT); |
| 145 | + // Subscribe to MQTT and register a callback |
| 146 | + Serial.println(F("Subscribe to Topics")); |
| 147 | + mqttClient.onMessage(mqttMessageHandler); |
| 148 | + mqttClient.subscribe(MQTT_TOPIC_ASSISTNOW); |
| 149 | + lastReceived_ms = millis(); |
| 150 | + } //End attempt to connect |
| 151 | + } //End connected == false |
| 152 | + else { |
| 153 | + mqttClient.poll(); |
| 154 | + } |
| 155 | + //Close socket if we don't have new data for 10s |
| 156 | + if (millis() - lastReceived_ms > maxTimeBeforeHangup_ms) |
| 157 | + { |
| 158 | + Serial.println(F("Timeout. Disconnecting...")); |
| 159 | + if (mqttClient.connected() == true) |
| 160 | + mqttClient.stop(); |
| 161 | + return; |
| 162 | + } |
| 163 | + |
| 164 | + delay(10); |
| 165 | + } |
| 166 | + |
| 167 | + Serial.println(F("User pressed a key")); |
| 168 | + Serial.println(F("Disconnecting...")); |
| 169 | + wifiClient.stop(); |
| 170 | +} |
0 commit comments