Code: Select all
#include <FS.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <ESP8266httpUpdate.h>
#include <WiFiManager.h>
#include <ArduinoJson.h>
#include <EEPROM.h>
#include <Ticker.h>
// solid green - factory reset
// blink green - connecting wifi
// blink blue - configuration required (SoftAP)
// blink magenta - connecting to cloud server
// solid cyan - connected to cloud server
// blinking cyan - transmitting/receiving data
// solid yellow - firmware update
#define LED_GREEN 0
#define LED_BLUE 4
#define LED_RED 5
#define RESET_ALL 16
#define ENABLE_DEBUG 12
#define version "1.0.2"
#define PortalServer "forum.reefangel.com"
#define MQTTServer "forum.reefangel.com"
#define MQTTPORT 1883 // MQTT server port
WiFiManager wifiManager;
WiFiServer server(2000);
WiFiClient webclient;
WiFiClient portalclient;
WiFiClient espClient;
PubSubClient CloudClient(espClient);
Ticker ticker;
long lastMsg = 0;
char msg[50];
int value = 0;
boolean LED_status = false;
boolean first_connection = true;
boolean sending_data = false;
boolean data_ready = false;
boolean PortalConnection = false;
boolean shouldSaveConfig = false;
boolean updating = false;
boolean debug_log = false;
unsigned long cloudmillis = millis();
unsigned long client_timeout = millis();
unsigned long serial_timeout = millis();
String currentLine = ""; // make a String to hold incoming data from the client
char mqtt_username[32];
char mqtt_password[32];
// Function prototypes
void SendData();
void callback(char* topic, byte* payload, unsigned int length);
void reconnect();
void saveConfigCallback ();
void configModeCallback (WiFiManager *myWiFiManager);
void WifiCheckCallback ();
void APtick();
void Wifitick();
void Cloudtick();
void Datatick();
void print_debug(String value);
void println_debug(String value);
void LED_Color(int Red, int Green, int Blue);
void setup() {
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
pinMode(LED_RED, OUTPUT);
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_BLUE, HIGH);
digitalWrite(LED_RED, HIGH);
wifi_station_set_hostname( "ReefAngelCloudWifi" );
Serial.begin(57600);
Serial.setRxBufferSize(2048);
pinMode(RESET_ALL, INPUT);
digitalWrite(RESET_ALL, HIGH);
pinMode(ENABLE_DEBUG, INPUT);
digitalWrite(ENABLE_DEBUG, HIGH);
EEPROM.begin(512);
if (digitalRead(ENABLE_DEBUG) == LOW)
{
wifiManager.setDebugOutput(true);
debug_log = true;
}
else
{
wifiManager.setDebugOutput(false);
debug_log = false;
}
// wifiManager.setDebugOutput(true);
// debug_log=true;
println_debug("");
print_debug("Current version: ");
println_debug(version);
if (digitalRead(RESET_ALL) == LOW)
{
// updating=true;
println_debug("Resetting");
EEPROM.write(256, 0);
EEPROM.commit();
ESP.reset();
while (1);
}
wifiManager.setVersion(version);
if (EEPROM.read(128) != 1)
{
wifiManager.resetSettings();
SPIFFS.format();
EEPROM.write(128, 1);
EEPROM.commit();
}
if (SPIFFS.begin()) {
Serial.println("mounted file system");
if (SPIFFS.exists("/config.json")) {
//file exists, reading and loading
Serial.println("reading config file");
File configFile = SPIFFS.open("/config.json", "r");
if (configFile) {
Serial.println("opened config file");
size_t size = configFile.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());
json.printTo(Serial);
if (json.success()) {
Serial.println("\nparsed json");
strcpy(mqtt_username, json["mqtt_username"]);
strcpy(mqtt_password, json["mqtt_password"]);
} else {
Serial.println("failed to load json config");
}
}
}
} else {
Serial.println("failed to mount FS");
}
WiFiManagerParameter custom_mqtt_username("Cloud Username", "Cloud Username", mqtt_username, 40);
WiFiManagerParameter custom_mqtt_password("Cloud Password", "Cloud Password", mqtt_password, 40);
wifiManager.addParameter(&custom_mqtt_username);
wifiManager.addParameter(&custom_mqtt_password);
wifiManager.setSaveConfigCallback(saveConfigCallback);
wifiManager.setAPCallback(configModeCallback);
wifiManager.setCheckWifiCallback(WifiCheckCallback);
LED_Color(0, 0, 0);
ticker.attach(0.5, Wifitick);
wifiManager.autoConnect("ReefAngelCloudWifi");
ticker.detach();
LED_Color(900, 0, 1023);
CloudClient.setServer(MQTTServer, MQTTPORT);
CloudClient.setCallback(callback);
strcpy(mqtt_username, custom_mqtt_username.getValue());
strcpy(mqtt_password, custom_mqtt_password.getValue());
Serial.print("username: ");
Serial.println(mqtt_username);
Serial.print("password: ");
Serial.println(mqtt_password);
if (shouldSaveConfig) {
Serial.println("saving config");
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
json["mqtt_username"] = mqtt_username;
json["mqtt_password"] = mqtt_password;
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("failed to open config file for writing");
}
json.printTo(Serial);
Serial.println("");
json.printTo(configFile);
configFile.close();
//end save
}
print_debug("IP address: ");
if (debug_log) Serial.println(WiFi.localIP());
}
void loop() {
if ((digitalRead(RESET_ALL) == LOW) && !updating)
{
if (WiFi.status() == WL_CONNECTED)
{
updating = true;
ticker.detach();
LED_Color(1023, 900, 0);
println_debug("Updating...");
ESPhttpUpdate.update("forum.reefangel.com", 80, "/firmware/CloudWifiESP8266Attachment.ino.bin");
}
else
{
println_debug("Resetting");
EEPROM.write(256, 0);
EEPROM.commit();
ESP.reset();
while (1);
}
}
if (!CloudClient.connected() && (((millis() - cloudmillis) > 30000) || first_connection)) {
first_connection = false;
LED_Color(0, 0, 0);
ticker.detach();
ticker.attach(0.5, Cloudtick);
reconnect();
}
CloudClient.loop();
webclient = server.available();
if (webclient) { // if you get a client,
LED_Color(0, 0, 0);
ticker.detach();
ticker.attach(0.05, Datatick);
println_debug("new incoming client"); // print a message out the serial port
client_timeout = millis();
while (webclient.connected()) { // loop while the client's connected
if (millis() - client_timeout > 2000)
{
println_debug("incoming client timeout"); // print a message out the serial port
webclient.stop();
LED_Color(0, 1023, 1023);
ticker.detach();
}
if (!sending_data)
{
while (webclient.available()) { // if there's bytes to read from the client,
char c = webclient.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
}
}
while (Serial.available())
{
sending_data = true;
char c = Serial.read();
currentLine += c;
serial_timeout = millis();
if (c == 13) SendData();
// if (currentLine.length() == 255) {
// SendData();
// }
}
if (millis() - serial_timeout > 400)
{
if (currentLine.length() > 0) {
SendData();
//webclient.println();
sending_data = false;
delay(1000);
}
}
}
// close the connection:
webclient.stop();
LED_Color(0, 1023, 1023);
ticker.detach();
println_debug("incoming client disconnected");
}
else
{
sending_data = false;
while (Serial.available())
{
char c = Serial.read();
currentLine += c;
if (c == 10) data_ready = true;
serial_timeout = millis();
if (millis() - serial_timeout > 200 || data_ready)
{
if (currentLine.length() > 0)
{
data_ready = false;
serial_timeout = millis();
if (currentLine.startsWith("GET")) {
PortalConnection = true;
println_debug("Connecting to Portal Server");
LED_Color(0, 0, 0);
ticker.detach();
ticker.attach(0.05, Datatick);
if (portalclient.connect(PortalServer, 3000)) {
println_debug("Connected");
// Log the request being sent
println_debug("Sending Request:");
// Make a HTTP request:
portalclient.println(currentLine);
portalclient.println(F(" HTTP/1.1\r\n"));
portalclient.println(F("Host: reefangel.com\r\n"));
portalclient.println(F("Connection: close\r\n"));
portalclient.println();
} else {
println_debug("Failed to connect");
LED_Color(0, 1023, 1023);
ticker.detach();
}
}
if (currentLine.startsWith("CLOUD:"))
{
//Serial.print(currentLine);
if (currentLine.length() < 32)
{
if (CloudClient.connected())
{
println_debug("Publishing ");
currentLine.replace("CLOUD:", "");
println_debug(currentLine);
char pub_buffer[sizeof(mqtt_username) + 5];
sprintf(pub_buffer, "%s/out", mqtt_username);
//println_debug(pub_buffer);
char pub_msg[currentLine.length() + 1];
currentLine.toCharArray(pub_msg, currentLine.length() + 1);
CloudClient.publish(pub_buffer, pub_msg);
}
}
else
{
//Serial.print(F("Error on incoming data: "));
//Serial.println(currentLine.length());
}
}
//Serial.print(currentLine);
currentLine = "";
}
}
}
while (portalclient.available()) {
char c = portalclient.read();
// Serial.write(c);
}
if (PortalConnection && !portalclient.connected()) {
PortalConnection = false;
// Serial.println();
println_debug("Disconnecting from Portal Server");
portalclient.stop();
LED_Color(0, 1023, 1023);
ticker.detach();
}
if (portalclient.connected()) {
println_debug("Response from the server:");
// Wait for data from the server
while (portalclient.connected() || portalclient.available()) {
if (portalclient.available()) {
String line = portalclient.readStringUntil('\r');
println_debug(line);
}
}
println_debug("Server connection closed");
}
}
}
void SendData()
{
serial_timeout = millis();
// Serial.print(currentLine);
webclient.print(currentLine);
Serial.println(currentLine);
currentLine = "";
}
//void setup_wifi() {
//
// delay(10);
// // We start by connecting to a WiFi network
// Serial.println();
// Serial.print(F("Connecting to "));
// Serial.println(WIFI_SSID);
//
// WiFi.begin(WIFI_SSID, WIFI_PASS);
//
// while (WiFi.status() != WL_CONNECTED) {
// delay(500);
// Serial.print(".");
// }
// digitalWrite(LED_GREEN,HIGH);
//
// Serial.println("");
// Serial.println(F("WiFi connected"));
// Serial.print(F("IP address: "));
// Serial.println(WiFi.localIP());
//}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("cloud:");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.print(" ");
}
void reconnect() {
// Loop until we're reconnected
if (!CloudClient.connected()) {
cloudmillis = millis();
// Serial.print(F("Username: "));
// Serial.println(CLOUD_USERNAME);
println_debug("Connecting to cloud server...");
// Attempt to connect
char sub_buffer[sizeof(mqtt_username) + 6];
sprintf(sub_buffer, "RA-%s", mqtt_username);
//Serial.println(sub_buffer);
if (CloudClient.connect(sub_buffer, mqtt_username, mqtt_password)) {
println_debug("Connected");
// Once connected, publish an announcement...
sprintf(sub_buffer, "%s/in/#", mqtt_username);
print_debug("Subscribing to ");
println_debug(sub_buffer);
CloudClient.subscribe(sub_buffer);
ticker.detach();
LED_Color(0, 1023, 1023);
//Serial.swap();
} else {
print_debug("Failed, rc=");
if (debug_log) Serial.print(CloudClient.state());
println_debug(" try again in 30 seconds");
}
}
}
void saveConfigCallback () {
println_debug("Should save config");
shouldSaveConfig = true;
}
void configModeCallback (WiFiManager *myWiFiManager) {
LED_Color(0, 0, 0);
ticker.detach();
println_debug("Entered config mode");
WiFi.softAPIP();
ticker.attach(0.5, APtick);
}
void WifiCheckCallback () {
WiFi.softAPdisconnect(true);
LED_Color(0, 0, 0);
ticker.detach();
println_debug("Checking Wifi Credentials");
ticker.attach(0.5, Wifitick);
}
void APtick()
{
//toggle state
int state = digitalRead(LED_BLUE); // get the current state of GPIO1 pin
digitalWrite(LED_BLUE, !state); // set pin to the opposite state
}
void Wifitick()
{
//toggle state
int state = digitalRead(LED_GREEN); // get the current state of GPIO1 pin
digitalWrite(LED_GREEN, !state); // set pin to the opposite state
}
void Cloudtick()
{
//toggle state
int state = digitalRead(LED_BLUE); // get the current state of GPIO1 pin
digitalWrite(LED_RED, !state); // set pin to the opposite state
digitalWrite(LED_BLUE, !state); // set pin to the opposite state
}
void Datatick()
{
//toggle state
int state = digitalRead(LED_BLUE); // get the current state of GPIO1 pin
digitalWrite(LED_GREEN, !state); // set pin to the opposite state
digitalWrite(LED_BLUE, !state); // set pin to the opposite state
}
void print_debug(String value)
{
if (debug_log)
Serial.print(value);
}
void println_debug(String value)
{
if (debug_log)
Serial.println(value);
}
void LED_Color(int Red, int Green, int Blue)
{
analogWrite(LED_RED, 1023 - Red);
analogWrite(LED_GREEN, 1023 - Green);
analogWrite(LED_BLUE, 1023 - Blue);
}