diff --git a/include/secrets.h SAMPLE b/include/secrets.h SAMPLE deleted file mode 100644 index 7b7339f..0000000 --- a/include/secrets.h SAMPLE +++ /dev/null @@ -1,4 +0,0 @@ -const char* wifi_ssid = "WIFI NETWORK HERE"; -const char* wifi_password = "WIFI PASSWORD HERE"; -const char* mqttServer = "192.168.1.1"; -const int mqttPort = 1883; \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 844d91b..08a38ff 100644 --- a/platformio.ini +++ b/platformio.ini @@ -8,12 +8,17 @@ ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html -[env:esp01_1m] +[env:esp01] platform = espressif8266 -board = esp01_1m +board = esp01 framework = arduino monitor_speed = 115200 -; upload_port = /dev/cu.usbserial-22410 +; monitor_port = /dev/cu.usbserial-22430 +; upload_port = /dev/cu.usbserial-22430 ;/dev/cu.usbserial-142320 ; lib_deps = PubSubClient - DHT sensor library \ No newline at end of file + DHT sensor library + WifiManager + ESP8266WebServer + DNSServer + ArduinoJson@5.9.0 \ No newline at end of file diff --git a/readme.md b/readme.md index 9d8ba8e..5ed4f72 100644 --- a/readme.md +++ b/readme.md @@ -3,4 +3,15 @@ Connects a DHT11 or DHT22 to an ESP-8266, then sends temperature and humidity ov I use an ESP-01 to keep things cheap. The goal is to have one of these things per room and one outside, so low cost is a high priority. -Keep the ESP separated from the DHT — or else the heat from the wifi module affects the temperature and humidity readings. \ No newline at end of file +Keep the ESP separated from the DHT — or else the heat from the wifi module affects the temperature and humidity readings. + +### Setup +Flash your device and it will create a wifi network called SimpleWeather. Connect to this and wait for the captive portal, or visit 192.168.4.1 to set up. Fields are: +1. Wifi network to join +2. Wifi password +3. MQTT server address +4. MQTT server port +5. Temperature topic +6. Humidity topic + +If your ESP device needs clearing out (old wifi credentials, etc) then set `resetWifiSettings` to true. Flash and let the device restart, then set it back to false and reflash again. Re-run setup. \ No newline at end of file diff --git a/src/SimpleWeather.cpp b/src/SimpleWeather.cpp index 748aa2f..c8831a0 100755 --- a/src/SimpleWeather.cpp +++ b/src/SimpleWeather.cpp @@ -1,78 +1,174 @@ -#include -#include +#include //this needs to be first, or it all crashes and burns... +#include //https://github.com/esp8266/Arduino +#include +#include +#include //https://github.com/tzapu/WiFiManager +#include //https://github.com/bblanchon/ArduinoJson #include -#include "DHT.h" -#include "math.h" -#include "secrets.h" // modify 'include/secrets.h SAMPLE' with your details and save as 'include/secrets.h' +#include #define DHTPIN 2 #define DHTTYPE DHT11 -const char* hostName = "Humidobot-2"; -const char* humidityTopic = "sensors/dht2/humidity"; -const char* temperatureTopic = "sensors/dht2/temperature"; - -unsigned long lastMeasureAttempt = 0; +const bool resetWifiSettings = false; // set true to clear out old settings and start fresh! +bool shouldSaveConfig = false; +const bool debug = false; DHT dht(DHTPIN, DHTTYPE); -WiFiClient espClient; -PubSubClient client(espClient); +WiFiClient wifiClient; +PubSubClient mqttClient(wifiClient); + +char hostName[40] = "SimpleWeather"; +char mqtt_server[40]; +char mqtt_port[6]; +char humidityTopic[40]; +char temperatureTopic[40]; const long measurementInterval = 5000; +unsigned long lastMeasureAttempt = 0; void yield(unsigned long yieldDuration) { //overload yield function to allow for any ms delay unsigned long yieldBegan = millis(); while ( (millis() - yieldBegan) < yieldDuration ) yield(); } -void setup_wifi() { - Serial.print("Connecting to " + String(wifi_ssid)); - WiFi.begin(wifi_ssid, wifi_password); - while (WiFi.status() != WL_CONNECTED) { - yield(500); - Serial.print("."); - } - Serial.print("WiFi connected. IP: "); - Serial.println(WiFi.localIP()); +void saveConfigCallback () { + if(debug) Serial.println("Should save config"); + shouldSaveConfig = true; } void reportResults(float temp, float humid) { if (!isnan(temp) || !isnan(humid)) { - Serial.println("-----------------------"); - Serial.println("Humidity (%): " + String(humid)); - Serial.println("Temperature (°C): " + String(temp)); - Serial.println("-----------------------"); - client.publish(humidityTopic, String(humid).c_str(), true); - client.publish(temperatureTopic, String(temp).c_str(), true); + if(debug) { + Serial.println("-----------------------"); + Serial.println("Humidity (%): " + String(humid)); + Serial.println("Temperature (°C): " + String(temp)); + Serial.println("-----------------------"); + } + mqttClient.publish(humidityTopic, String(humid).c_str(), true); + mqttClient.publish(temperatureTopic, String(temp).c_str(), true); } } -void reconnect() { - while (!client.connected()) { - Serial.print("Attempting MQTT connection..."); - if (client.connect(hostName)) { - Serial.println("connected"); +void reconnectMqtt() { + while (!mqttClient.connected()) { + if(debug) Serial.print("Attempting MQTT connection..."); + if (mqttClient.connect(hostName)) { + if(debug) Serial.println("connected"); } else { - Serial.print(" failed. MQTT connection error: "); - Serial.println(client.state()); - Serial.println(" try again in 5 seconds"); + if(debug) { + Serial.print(" failed. MQTT connection error: "); + Serial.println(mqttClient.state()); + Serial.println(" try again in 5 seconds"); + } yield(5000); } } } void setup() { - Serial.begin(115200); - Serial.println(); - setup_wifi(); - client.setServer(mqttServer, mqttPort); + if(resetWifiSettings) LittleFS.format(); + if(debug) Serial.println("mounting FS..."); + + if (LittleFS.begin()) { + if(debug) Serial.println("mounted file system"); + if (LittleFS.exists("/config.json")) { + //file exists, reading and loading + if(debug) Serial.println("reading config file"); + File configFile = LittleFS.open("/config.json", "r"); + if (configFile) { + if(debug) Serial.println("opened config file"); + size_t size = configFile.size(); + // Allocate a buffer to store contents of the file. + std::unique_ptr buf(new char[size]); + configFile.readBytes(buf.get(), size); + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.parseObject(buf.get()); + if(debug) json.printTo(Serial); + if (json.success()) { + if(debug) Serial.println("\nparsed json"); + strcpy(mqtt_server, json["mqtt_server"]); + strcpy(mqtt_port, json["mqtt_port"]); + strcpy(hostName, json["hostName"]); + strcpy(humidityTopic, json["humidityTopic"]); + strcpy(temperatureTopic, json["temperatureTopic"]); + } else { + if(debug) Serial.println("failed to load json config"); + } + configFile.close(); + } + } + } else { + if(debug) Serial.println("failed to mount FS"); + } + //end read + + WiFiManagerParameter custom_mqtt_port("port", "mqtt port", mqtt_port, 6); + WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40); + WiFiManagerParameter custom_mqtt_hostname("hostname", "host name", hostName, 40); + WiFiManagerParameter custom_mqtt_humidityTopic("humidityTopic", "humidity topic", humidityTopic, 40); + WiFiManagerParameter custom_mqtt_temperatureTopic("temperatureTopic", "temperature topic", temperatureTopic, 40); + + WiFiManager wifiManager; + + //set config save notify callback + wifiManager.setSaveConfigCallback(saveConfigCallback); + + //add all your parameters here + wifiManager.addParameter(&custom_mqtt_server); + wifiManager.addParameter(&custom_mqtt_port); + wifiManager.addParameter(&custom_mqtt_hostname); + wifiManager.addParameter(&custom_mqtt_humidityTopic); + wifiManager.addParameter(&custom_mqtt_temperatureTopic); + + if (resetWifiSettings) wifiManager.resetSettings(); + if (!wifiManager.autoConnect("SimpleWeather", "password")) { + if(debug) Serial.println("failed to connect and hit timeout"); + delay(3000); + ESP.reset(); + delay(5000); + } + + //if you get here you have connected to the WiFi + if(debug) Serial.println("connected!"); + + //read updated parameters + strcpy(mqtt_port, custom_mqtt_port.getValue()); + strcpy(mqtt_server, custom_mqtt_server.getValue()); + strcpy(hostName, custom_mqtt_hostname.getValue()); + strcpy(humidityTopic, custom_mqtt_humidityTopic.getValue()); + strcpy(temperatureTopic, custom_mqtt_temperatureTopic.getValue()); + + //save the custom parameters to FS + if (shouldSaveConfig) { + if(debug) Serial.println("saving config"); + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + json["mqtt_server"] = mqtt_server; + json["mqtt_port"] = mqtt_port; + json["hostName"] = hostName; + json["humidityTopic"] = humidityTopic; + json["temperatureTopic"] = temperatureTopic; + + File configFile = LittleFS.open("/config.json", "w"); + if (!configFile) Serial.println("failed to open config file for writing"); + + if(debug) json.printTo(Serial); + json.printTo(configFile); + configFile.close(); + //end save + } + + if(debug) Serial.println("local ip"); + if(debug) Serial.println(WiFi.localIP()); + uint16_t mqtt_port_int = (uint16_t)strtol(mqtt_port, NULL, 10); + mqttClient.setServer(mqtt_server, mqtt_port_int); dht.begin(); } void loop() { - if (WiFi.status() != WL_CONNECTED) setup_wifi(); - if (!client.connected()) reconnect(); - client.loop(); + if (!mqttClient.connected()) reconnectMqtt(); + mqttClient.loop(); if ((millis() - lastMeasureAttempt) > measurementInterval) { reportResults(dht.readTemperature(), dht.readHumidity()); lastMeasureAttempt = millis();