// TODO: Pouzit FPSTR() !!! #include #include #include #include #include #include #include #include // Definice I/O pinu #define ONE_WIRE_PIN 2 // DS18B20 pin #define FORCE_CONFIG_BUTTON_PIN 3 // pin pro tlacitko na vynucenou rekonfiguraci (RXD) #define LED_PIN 1 // pin, na kterem je pripojena LED dioda (TXD) // Definice obsazeni EEPROM #define elementSize(type, element) sizeof(((type *)0)->element) typedef struct { wificonfigarea_t wc; // oblast, vyhrazena pro konfiguraci WiFi char apiKey[33]; // retezec, obsahujici APIKEY pro ThingSpeak char server[65]; // retezec, obsahujici adresu Thingspeak serveru char field[65]; // jmeno datapointu, do ktereho je ukladana teplota char periode[32]; // perioda ukladani dat [s] char mDNSname[32]; // jmeno pro mDNS resolver }eepromdata; MDNSResponder mdns; ESP8266WebServer wwwserver(80); // webovy server - pouzity je jak pro nastaveni ESP modulu pomoci WifiConfig, tak pro praci aplikace String content; // obsah, vraceny webovym serverem WifiConfig wifi; // konfigurace ESP modulu OneWire oneWire(ONE_WIRE_PIN); DallasTemperature DS18B20(&oneWire); String mDNSname; float Temp; // pracovni hodnota teploty String APIKey; // API klic k ThingSpeak String server; // URL serveru String field; // jmeno datapointu uint32_t periode; // perioda odesilani na server WiFiClient client; Interval txinterval; // perioda pro odesilani dat na server Interval blink; // blikani indikacni LED Interval measure; // interval pro mereni teploty static void handleSave(void) { APIKey = wwwserver.arg("a"); setEEPROMString(offsetof(eepromdata, apiKey), elementSize(eepromdata, apiKey), APIKey); server = wwwserver.arg("s"); setEEPROMString(offsetof(eepromdata, server), elementSize(eepromdata, server), server); field = wwwserver.arg("f"); setEEPROMString(offsetof(eepromdata, field), elementSize(eepromdata, field), field); periode = atoi(wwwserver.arg("p").c_str()); if (periode && (periode < 15)) periode = 15; // minimalni perioda je 15 sekund (ThingSpeak rule) setEEPROMString(offsetof(eepromdata, periode), elementSize(eepromdata, periode), String(periode)); mDNSname = wwwserver.arg("m"); setEEPROMString(offsetof(eepromdata, mDNSname), elementSize(eepromdata, mDNSname), mDNSname); content = F("{v}"); content.replace("{v}", "Setup"); content += F(""); content += F(""); content += F(""); content += F("Configuration saved - mDNS change requires an RESET"); content += F(""); wwwserver.send(200, F("text/html"), content); } static void handleSetup(void) { content = F("{v}"); content.replace("{v}", "Setup"); content += F(""); content += F(""); content += F("
"); content += F("mDNS id

"); content.replace("{v}", mDNSname); content += F("Server

"); content.replace("{v}", server); content += F("API Key

"); content.replace("{v}", APIKey); content += F("Field

"); content.replace("{v}", field); content += F("Period

"); content.replace("{v}", String(periode)); content += F("
"); content += F(""); wwwserver.send(200, F("text/html"), content); } static void handleRoot(void) { content = F("{v}"); content.replace("{v}", "YAFET"); content += F(""); content += F(""); content += F(""); content += F("Temperature: "); content += String(Temp); content += F("°C"); content += F(""); wwwserver.send(200, F("text/html"), content); } void setup() { EEPROM.begin(512); // zahajujeme praci s EEPROM pinMode(FORCE_CONFIG_BUTTON_PIN, INPUT_PULLUP); // RXD slouzi jako vstup tlacitka delay(10); wifi.begin(offsetof(eepromdata, wc), digitalRead(FORCE_CONFIG_BUTTON_PIN)); // startujeme pripojeni pinMode(LED_PIN, OUTPUT); // indikacni LED dioda wwwserver.on("/", handleRoot); // korenovy/implicitni obsah wwwserver.on("/setup", handleSetup); // nastaveni parametru wwwserver.on("/s", handleSave); // ulozeni parametru wwwserver.begin(); // startujeme webovy server Temp = 0.; APIKey = getEEPROMString(offsetof(eepromdata, apiKey), elementSize(eepromdata, apiKey)); server = getEEPROMString(offsetof(eepromdata, server), elementSize(eepromdata, server)); field = getEEPROMString(offsetof(eepromdata, field), elementSize(eepromdata, field)); periode = atoi(getEEPROMString(offsetof(eepromdata, periode), elementSize(eepromdata, periode)).c_str()); mDNSname = getEEPROMString(offsetof(eepromdata, mDNSname), elementSize(eepromdata, mDNSname)); if (mDNSname.length() > 0) mdns.begin(mDNSname.c_str(), WiFi.localIP()); } void loop() { // osetreni mereni teploty if (measure.expired()) { DS18B20.requestTemperatures(); Temp = DS18B20.getTempCByIndex(0); measure.set(5000); } // osetreni behu weboveho serveru wwwserver.handleClient(); // osetrujeme praci serveru // osetreni odesilani na ThingSpeak if ((0 != periode) && server.length() && APIKey.length() && field.length()) { if (txinterval.expired()) { if (client.connect(server.c_str(), 80)) { String postStr = APIKey; postStr +="&"; postStr += field; postStr += "="; postStr += String(Temp); postStr += "\r\n\r\n"; client.print(F("POST /update HTTP/1.1\n")); client.print("Host: " + server + "\n"); client.print(F("Connection: close\n")); client.print("X-THINGSPEAKAPIKEY: " + APIKey + "\n"); client.print(F("Content-Type: application/x-www-form-urlencoded\n")); client.print(F("Content-Length: ")); client.print(postStr.length()); client.print(F("\n\n")); client.print(postStr); } client.stop(); txinterval.set(1000 * periode); } } // blikani indikacni LED diodou if (blink.expired()) { digitalWrite(LED_PIN, !digitalRead(LED_PIN)); blink.set(1000); } }