First draft of wifimanager
This commit is contained in:
parent
8df391e66f
commit
b3ec7ab03c
|
|
@ -14,6 +14,5 @@ board = ttgo-lora32-v1
|
||||||
framework = arduino
|
framework = arduino
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
lib_deps =
|
lib_deps =
|
||||||
thingpulse/ESP8266 and ESP32 OLED driver for SSD1306 displays@^4.5.0
|
https://github.com/tzapu/WiFiManager.git
|
||||||
sandeepmistry/LoRa@^0.8.0
|
bblanchon/ArduinoJson@^7.0.4
|
||||||
knolleary/PubSubClient@^2.8
|
|
||||||
|
|
|
||||||
|
|
@ -1,200 +1,297 @@
|
||||||
// OLED
|
// File System Library
|
||||||
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
|
#include <FS.h>
|
||||||
#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
|
// SPI Flash Syetem Library
|
||||||
|
#include <SPIFFS.h>
|
||||||
|
|
||||||
// LORA
|
|
||||||
#include <SPI.h>
|
|
||||||
#include <LoRa.h>
|
|
||||||
|
|
||||||
// MQTT
|
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <PubSubClient.h>
|
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
WiFiServer server(80);
|
||||||
|
// Define WiFiManager Object
|
||||||
|
WiFiManager wm;
|
||||||
|
|
||||||
SSD1306 display(0x3c, 4, 15);
|
// Flag for saving data
|
||||||
|
bool shouldSaveConfig = false;
|
||||||
//OLED pins to ESP32 GPIOs via this connection:
|
|
||||||
//OLED_SDA GPIO4
|
|
||||||
//OLED_SCL GPIO15
|
|
||||||
//OLED_RST GPIO16
|
|
||||||
|
|
||||||
|
|
||||||
|
// JSON configuration file
|
||||||
|
#define JSON_CONFIG_FILE "/test_config.json"
|
||||||
|
// Variables to hold data from custom textboxes
|
||||||
|
char testString[50] = "test value";
|
||||||
|
int testNumber = 1234;
|
||||||
|
|
||||||
// WIFI_LoRa_32 ports
|
// Variable to store the HTTP request
|
||||||
|
String header;
|
||||||
|
|
||||||
// GPIO5 SX1278 SCK
|
// Assign output variables to GPIO pins
|
||||||
// GPIO19 SX1278 MISO
|
const int output5 = 25;
|
||||||
// GPIO27 SX1278 MOSI
|
|
||||||
// GPIO18 SX1278 CS
|
|
||||||
// GPIO14 SX1278 RESET
|
|
||||||
// GPIO26 SX1278 IRQ(Interrupt Request)
|
|
||||||
|
|
||||||
#define SS 18
|
#define TRIGGER_PIN 0
|
||||||
#define RST 14
|
|
||||||
#define DI0 26
|
|
||||||
// #define BAND 429E6
|
|
||||||
|
|
||||||
// LoRa Settings
|
void saveConfigFile()
|
||||||
#define BAND 434500000.00
|
// Save Config in JSON format
|
||||||
#define spreadingFactor 9
|
{
|
||||||
// #define SignalBandwidth 62.5E3
|
Serial.println(F("Saving configuration..."));
|
||||||
#define SignalBandwidth 31.25E3
|
|
||||||
|
// Create a JSON document
|
||||||
#define codingRateDenominator 8
|
StaticJsonDocument<512> json;
|
||||||
|
json["testString"] = testString;
|
||||||
|
json["testNumber"] = testNumber;
|
||||||
|
|
||||||
// WiFi Network Credentials
|
// Open config file
|
||||||
const char *ssid = "SoS IOT";
|
File configFile = SPIFFS.open(JSON_CONFIG_FILE, "w");
|
||||||
const char *password = "godisr8n";
|
if (!configFile)
|
||||||
|
{
|
||||||
// MQTTCredentials
|
// Error, file did not open
|
||||||
const char *MQTT_USER = "simon";
|
Serial.println("failed to open config file for writing");
|
||||||
const char *MQTT_PASS = "bajsa123";
|
|
||||||
|
|
||||||
IPAddress broker(10,0,0,3); // IP address of your MQTT broker eg. 192.168.1.50
|
|
||||||
const char *ID = "esp_1"; // Name of our device, must be unique
|
|
||||||
const char *TOPIC = "test/sensor"; // Topic to subcribe to
|
|
||||||
WiFiClient wclient;
|
|
||||||
|
|
||||||
PubSubClient client(wclient); // Setup MQTT client
|
|
||||||
|
|
||||||
String data = "";
|
|
||||||
|
|
||||||
// Connect to WiFi network
|
|
||||||
void setup_wifi() {
|
|
||||||
Serial.print("\nConnecting to ");
|
|
||||||
Serial.println(ssid);
|
|
||||||
|
|
||||||
WiFi.begin(ssid, password); // Connect to network
|
|
||||||
|
|
||||||
while (WiFi.status() != WL_CONNECTED) { // Wait for connection
|
|
||||||
delay(500);
|
|
||||||
Serial.print(".");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println();
|
// Serialize JSON data to write to file
|
||||||
Serial.println("WiFi connected");
|
serializeJsonPretty(json, Serial);
|
||||||
Serial.print("IP address: ");
|
if (serializeJson(json, configFile) == 0)
|
||||||
Serial.println(WiFi.localIP());
|
{
|
||||||
|
// Error writing file
|
||||||
|
Serial.println(F("Failed to write to file"));
|
||||||
|
}
|
||||||
|
// Close file
|
||||||
|
configFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reconnect to client
|
bool loadConfigFile()
|
||||||
void reconnect() {
|
// Load existing configuration file
|
||||||
// Loop until we're reconnected
|
{
|
||||||
while (!client.connected()) {
|
// Uncomment if we need to format filesystem
|
||||||
Serial.print("Attempting MQTT connection...");
|
// SPIFFS.format();
|
||||||
// Attempt to connect
|
|
||||||
if (client.connect(ID,MQTT_USER,MQTT_PASS)) {
|
// Read configuration from FS json
|
||||||
Serial.println("connected");
|
Serial.println("Mounting File System...");
|
||||||
Serial.print("Publishing to: ");
|
|
||||||
Serial.println(TOPIC);
|
// May need to make it begin(true) first time you are using SPIFFS
|
||||||
Serial.println('\n');
|
if (SPIFFS.begin(false) || SPIFFS.begin(true))
|
||||||
|
{
|
||||||
|
Serial.println("mounted file system");
|
||||||
|
if (SPIFFS.exists(JSON_CONFIG_FILE))
|
||||||
|
{
|
||||||
|
// The file exists, reading and loading
|
||||||
|
Serial.println("reading config file");
|
||||||
|
File configFile = SPIFFS.open(JSON_CONFIG_FILE, "r");
|
||||||
|
if (configFile)
|
||||||
|
{
|
||||||
|
Serial.println("Opened configuration file");
|
||||||
|
StaticJsonDocument<512> json;
|
||||||
|
DeserializationError error = deserializeJson(json, configFile);
|
||||||
|
serializeJsonPretty(json, Serial);
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
Serial.println("Parsing JSON");
|
||||||
|
|
||||||
|
strcpy(testString, json["testString"]);
|
||||||
|
testNumber = json["testNumber"].as<int>();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Error loading JSON data
|
||||||
|
Serial.println("Failed to load json config");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Error mounting file system
|
||||||
|
Serial.println("Failed to mount FS");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
void saveConfigCallback()
|
||||||
Serial.println(" try again in 5 seconds");
|
// Callback notifying us of the need to save configuration
|
||||||
// Wait 5 seconds before retrying
|
{
|
||||||
|
Serial.println("Should save config");
|
||||||
|
shouldSaveConfig = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void configModeCallback(WiFiManager *myWiFiManager)
|
||||||
|
// Called when config mode launched
|
||||||
|
{
|
||||||
|
Serial.println("Entered Configuration Mode");
|
||||||
|
|
||||||
|
Serial.print("Config SSID: ");
|
||||||
|
Serial.println(myWiFiManager->getConfigPortalSSID());
|
||||||
|
|
||||||
|
Serial.print("Config IP Address: ");
|
||||||
|
Serial.println(WiFi.softAPIP());
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
// Change to true when testing to force configuration every time we run
|
||||||
|
bool forceConfig = false;
|
||||||
|
|
||||||
|
bool spiffsSetup = loadConfigFile();
|
||||||
|
if (!spiffsSetup)
|
||||||
|
{
|
||||||
|
Serial.println(F("Forcing config mode as there is no saved config"));
|
||||||
|
forceConfig = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pinMode(TRIGGER_PIN, INPUT);
|
||||||
|
|
||||||
|
WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
|
||||||
|
|
||||||
|
// Setup Serial monitor
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(10);
|
||||||
|
|
||||||
|
|
||||||
|
// Reset settings (only for development)
|
||||||
|
//wm.resetSettings();
|
||||||
|
|
||||||
|
// Set config save notify callback
|
||||||
|
wm.setSaveConfigCallback(saveConfigCallback);
|
||||||
|
|
||||||
|
// Set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
|
||||||
|
wm.setAPCallback(configModeCallback);
|
||||||
|
|
||||||
|
// Custom elements
|
||||||
|
|
||||||
|
// Text box (String) - 50 characters maximum
|
||||||
|
WiFiManagerParameter custom_text_box("key_text", "Enter your string here", testString, 50);
|
||||||
|
|
||||||
|
// Need to convert numerical input to string to display the default value.
|
||||||
|
char convertedValue[6];
|
||||||
|
sprintf(convertedValue, "%d", testNumber);
|
||||||
|
|
||||||
|
// Text box (Number) - 7 characters maximum
|
||||||
|
WiFiManagerParameter custom_text_box_num("key_num", "Enter your number here", convertedValue, 7);
|
||||||
|
|
||||||
|
// Add all defined parameters
|
||||||
|
wm.addParameter(&custom_text_box);
|
||||||
|
wm.addParameter(&custom_text_box_num);
|
||||||
|
|
||||||
|
if (forceConfig)
|
||||||
|
// Run if we need a configuration
|
||||||
|
{
|
||||||
|
if (!wm.startConfigPortal("NEWTEST_AP", "password"))
|
||||||
|
{
|
||||||
|
Serial.println("failed to connect and hit timeout");
|
||||||
|
delay(3000);
|
||||||
|
//reset and try again, or maybe put it to deep sleep
|
||||||
|
ESP.restart();
|
||||||
delay(5000);
|
delay(5000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ADC? Battery voltage
|
|
||||||
// const uint8_t vbatPin = 34;
|
|
||||||
// float VBAT; // battery voltage from ESP32 ADC read
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
pinMode(16,OUTPUT);
|
|
||||||
digitalWrite(16, LOW); // set GPIO16 low to reset OLED
|
|
||||||
delay(50);
|
|
||||||
digitalWrite(16, HIGH);
|
|
||||||
|
|
||||||
display.init();
|
|
||||||
display.flipScreenVertically();
|
|
||||||
display.setFont(ArialMT_Plain_10);
|
|
||||||
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
|
||||||
|
|
||||||
Serial.begin(115200);
|
|
||||||
while (!Serial); //if just the the basic function, must connect to a computer
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
Serial.println("LoRa Receiver");
|
|
||||||
display.drawString(5,5,"LoRa Receiver");
|
|
||||||
display.display();
|
|
||||||
SPI.begin(5,19,27,18);
|
|
||||||
LoRa.setPins(SS,RST,DI0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
pinMode(vbatPin, INPUT);
|
|
||||||
VBAT = (120.0/20.0) * (float)(analogRead(vbatPin)) / 1024.0; // LiPo battery voltage in volts
|
|
||||||
Serial.println("Vbat = "); Serial.print(VBAT); Serial.println(" Volts");
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!LoRa.begin(BAND)) {
|
|
||||||
display.drawString(5,25,"Starting LoRa failed!");
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
Serial.println("LoRa Initial OK!");
|
|
||||||
|
|
||||||
Serial.print("LoRa Frequency: ");
|
|
||||||
Serial.println(BAND);
|
|
||||||
|
|
||||||
Serial.print("LoRa Spreading Factor: ");
|
|
||||||
Serial.println(spreadingFactor);
|
|
||||||
LoRa.setSpreadingFactor(spreadingFactor);
|
|
||||||
|
|
||||||
Serial.print("LoRa Signal Bandwidth: ");
|
|
||||||
Serial.println(SignalBandwidth);
|
|
||||||
LoRa.setSignalBandwidth(SignalBandwidth);
|
|
||||||
|
|
||||||
LoRa.setCodingRate4(codingRateDenominator);
|
|
||||||
|
|
||||||
display.drawString(5,25,"LoRa Initializing OK!");
|
|
||||||
display.display();
|
|
||||||
|
|
||||||
setup_wifi(); // Connect to network
|
|
||||||
client.setServer(broker, 1883);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
if (!client.connected()) // Reconnect if connection is lost
|
|
||||||
{
|
{
|
||||||
reconnect();
|
if (!wm.autoConnect("NEWTEST_AP"))
|
||||||
}
|
{
|
||||||
client.loop();
|
Serial.println("failed to connect and hit timeout");
|
||||||
// try to parse packet
|
delay(3000);
|
||||||
int packetSize = LoRa.parsePacket();
|
// if we still have not connected restart and try all over again
|
||||||
if (packetSize) {
|
ESP.restart();
|
||||||
// received a packets
|
delay(5000);
|
||||||
Serial.print("Received packet. ");
|
|
||||||
|
|
||||||
display.clear();
|
|
||||||
display.setFont(ArialMT_Plain_16);
|
|
||||||
display.drawString(3, 0, "Received packet ");
|
|
||||||
display.display();
|
|
||||||
|
|
||||||
// read packet
|
|
||||||
while (LoRa.available()) {
|
|
||||||
data = LoRa.readString();
|
|
||||||
Serial.print(data);
|
|
||||||
display.drawString(20,22, data);
|
|
||||||
display.display();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// print RSSI of packet
|
|
||||||
Serial.print(" with RSSI ");
|
|
||||||
Serial.println(LoRa.packetRssi());
|
|
||||||
Serial.print(" with SNR ");
|
|
||||||
Serial.println(LoRa.packetSnr());
|
|
||||||
// display.drawString(0, 45, "RSSI: ");
|
|
||||||
// display.drawString(50, 45, (String)LoRa.packetRssi());
|
|
||||||
|
|
||||||
display.drawString(0, 45, (String)LoRa.packetRssi() + "dB (" + (String)LoRa.packetSnr() +"dB)");
|
|
||||||
|
|
||||||
display.display();
|
|
||||||
client.publish(TOPIC, data.c_str() );
|
|
||||||
Serial.println((String)TOPIC + " => " + data + ";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we get here, we are connected to the WiFi
|
||||||
|
|
||||||
|
Serial.println("");
|
||||||
|
Serial.println("WiFi connected");
|
||||||
|
Serial.print("IP address: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
|
||||||
|
// Lets deal with the user config values
|
||||||
|
|
||||||
|
// Copy the string value
|
||||||
|
strncpy(testString, custom_text_box.getValue(), sizeof(testString));
|
||||||
|
Serial.print("testString: ");
|
||||||
|
Serial.println(testString);
|
||||||
|
|
||||||
|
//Convert the number value
|
||||||
|
testNumber = atoi(custom_text_box_num.getValue());
|
||||||
|
Serial.print("testNumber: ");
|
||||||
|
Serial.println(testNumber);
|
||||||
|
|
||||||
|
|
||||||
|
// Save the custom parameters to FS
|
||||||
|
if (shouldSaveConfig)
|
||||||
|
{
|
||||||
|
saveConfigFile();
|
||||||
|
}
|
||||||
|
server.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
WiFiClient client = server.available(); // Listen for incoming clients
|
||||||
|
|
||||||
|
if (client)
|
||||||
|
{ // If a new client connects,
|
||||||
|
Serial.println("New Client."); // print a message out in the serial port
|
||||||
|
String currentLine = ""; // make a String to hold incoming data from the client
|
||||||
|
while (client.connected())
|
||||||
|
{ // loop while the client's connected
|
||||||
|
if (client.available())
|
||||||
|
{ // if there's bytes to read from the client,
|
||||||
|
char c = client.read(); // read a byte, then
|
||||||
|
Serial.write(c); // print it out the serial monitor
|
||||||
|
header += c;
|
||||||
|
if (c == '\n')
|
||||||
|
{ // if the byte is a newline character
|
||||||
|
// if the current line is blank, you got two newline characters in a row.
|
||||||
|
// that's the end of the client HTTP request, so send a response:
|
||||||
|
if (currentLine.length() == 0)
|
||||||
|
{
|
||||||
|
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
|
||||||
|
// and a content-type so the client knows what's coming, then a blank line:
|
||||||
|
client.println("HTTP/1.1 200 OK");
|
||||||
|
client.println("Content-type:text/html");
|
||||||
|
client.println("Connection: close");
|
||||||
|
client.println();
|
||||||
|
|
||||||
|
|
||||||
|
// Display the HTML web page
|
||||||
|
client.println("<!DOCTYPE html><html>");
|
||||||
|
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
|
||||||
|
client.println("<link rel=\"icon\" href=\"data:,\">");
|
||||||
|
// CSS to style the on/off buttons
|
||||||
|
// Feel free to change the background-color and font-size attributes to fit your preferences
|
||||||
|
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
|
||||||
|
client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
|
||||||
|
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
|
||||||
|
client.println(".button2 {background-color: #77878A;}</style></head>");
|
||||||
|
|
||||||
|
// Web Page Heading
|
||||||
|
client.println("<body><h1>ESP8266 Web Server</h1>");
|
||||||
|
|
||||||
|
// Display current state, and ON/OFF buttons for GPIO 5
|
||||||
|
// If the output5State is off, it displays the ON button
|
||||||
|
client.println("</body></html>");
|
||||||
|
|
||||||
|
// The HTTP response ends with another blank line
|
||||||
|
client.println();
|
||||||
|
// Break out of the while loop
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // if you got a newline, then clear currentLine
|
||||||
|
currentLine = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c != '\r')
|
||||||
|
{ // if you got anything else but a carriage return character,
|
||||||
|
currentLine += c; // add it to the end of the currentLine
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Clear the header variable
|
||||||
|
header = "";
|
||||||
|
// Close the connection
|
||||||
|
client.stop();
|
||||||
|
Serial.println("Client disconnected.");
|
||||||
|
Serial.println("");
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue