From fbf038dd8b7145b286ef44941670ba99e98fa0bd Mon Sep 17 00:00:00 2001 From: Charles Date: Wed, 29 Jul 2015 21:18:08 +0200 Subject: [PATCH] =?UTF-8?q?Cr=C3=A9ation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/ESP8266_WifInfo/ESP8266_WifInfo.h | 107 ++++ examples/ESP8266_WifInfo/ESP8266_WifInfo.ino | 532 ++++++++++++++++++ examples/ESP8266_WifInfo/config.cpp | 173 ++++++ examples/ESP8266_WifInfo/config.h | 69 +++ examples/ESP8266_WifInfo/route.cpp | 558 +++++++++++++++++++ examples/ESP8266_WifInfo/route.h | 47 ++ 6 files changed, 1486 insertions(+) create mode 100644 examples/ESP8266_WifInfo/ESP8266_WifInfo.h create mode 100644 examples/ESP8266_WifInfo/ESP8266_WifInfo.ino create mode 100644 examples/ESP8266_WifInfo/config.cpp create mode 100644 examples/ESP8266_WifInfo/config.h create mode 100644 examples/ESP8266_WifInfo/route.cpp create mode 100644 examples/ESP8266_WifInfo/route.h diff --git a/examples/ESP8266_WifInfo/ESP8266_WifInfo.h b/examples/ESP8266_WifInfo/ESP8266_WifInfo.h new file mode 100644 index 0000000..ee7aec7 --- /dev/null +++ b/examples/ESP8266_WifInfo/ESP8266_WifInfo.h @@ -0,0 +1,107 @@ +// ********************************************************************************** +// ESP8266 WifInfo WEB Server global Include file +// ********************************************************************************** +// Creative Commons Attrib Share-Alike License +// You are free to use/extend this library but please abide with the CC-BY-SA license: +// Attribution-NonCommercial-ShareAlike 4.0 International License +// http://creativecommons.org/licenses/by-nc-sa/4.0/ +// +// For any explanation about teleinfo ou use , see my blog +// http://hallard.me/category/tinfo +// +// This program works with the Wifinfo board +// see schematic here https://github.com/hallard/teleinfo/tree/master/Wifinfo +// +// Written by Charles-Henri Hallard (http://hallard.me) +// +// History : V1.00 2015-06-14 - First release +// +// All text above must be included in any redistribution. +// +// ********************************************************************************** +#ifndef WIFINFO_H +#define WIFINFO_H + +// Include Arduino header +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include +#include + +#include "route.h" +#include "config.h" + + +#define DEBUG + +// I prefix debug macro to be sure to use specific for THIS library +// debugging, this should not interfere with main sketch or other +// libraries +#ifdef DEBUG +#define Debug(x) Serial1.print(x) +#define Debugln(x) Serial1.println(x) +#define Debugf(...) Serial1.printf(__VA_ARGS__) +#define Debugflush Serial1.flush +#else +#define Debug(x) {} +#define Debugln(x) {} +#define Debugf(...) {} +#define Debugflush {} +#endif + +#define BLINK_LED_MS 50 // 50 ms blink +#define RGB_LED_PIN 14 +#define BLU_LED_PIN 1 +#define RED_LED_PIN 12 +// value for RGB color +#define COLOR_RED rgb_brightness, 0, 0 +#define COLOR_YELLOW rgb_brightness, rgb_brightness, 0 +#define COLOR_GREEN 0, rgb_brightness, 0 +#define COLOR_CYAN 0, rgb_brightness, rgb_brightness +#define COLOR_BLUE 0, 0, rgb_brightness +#define COLOR_MAGENTA rgb_brightness, 0, rgb_brightness + +// GPIO 1 TX on board blue led +#define LedBluON() {digitalWrite(BLU_LED_PIN, 0);} +#define LedBluOFF() {digitalWrite(BLU_LED_PIN, 1);} +// GPIO 12 red led +#define LedRedON() {digitalWrite(RED_LED_PIN, 1);} +#define LedRedOFF() {digitalWrite(RED_LED_PIN, 0);} + + // Light off the RGB LED +#define LedRGBOFF() { rgb_led.SetPixelColor(0,0,0,0); rgb_led.Show(); } +#define LedRGBON(x) { rgb_led.SetPixelColor(0,x); rgb_led.Show(); } + +// sysinfo informations +typedef struct +{ + String sys_uptime; + String sys_free_ram; + String sys_flash_size; + String sys_flash_speed; + String sys_firmware_size; + String sys_firmware_free; + String sys_vcc; + String sys_eep_config; +} _sysinfo; + +// Exported variables/object instancied in main sketch +// =================================================== +extern ESP8266WebServer server; +extern WiFiUDP OTA; +extern TInfo tinfo; +extern NeoPixelBus rgb_led ; +extern uint8_t rgb_brightness; +extern unsigned long seconds; +extern _sysinfo sysinfo; + + +#endif + diff --git a/examples/ESP8266_WifInfo/ESP8266_WifInfo.ino b/examples/ESP8266_WifInfo/ESP8266_WifInfo.ino new file mode 100644 index 0000000..3e0b90b --- /dev/null +++ b/examples/ESP8266_WifInfo/ESP8266_WifInfo.ino @@ -0,0 +1,532 @@ +// ********************************************************************************** +// ESP8266 Teleinfo WEB Server +// ********************************************************************************** +// Creative Commons Attrib Share-Alike License +// You are free to use/extend this library but please abide with the CC-BY-SA license: +// Attribution-NonCommercial-ShareAlike 4.0 International License +// http://creativecommons.org/licenses/by-nc-sa/4.0/ +// +// For any explanation about teleinfo ou use , see my blog +// http://hallard.me/category/tinfo +// +// This program works with the Wifinfo board +// see schematic here https://github.com/hallard/teleinfo/tree/master/Wifinfo +// +// Written by Charles-Henri Hallard (http://hallard.me) +// +// History : V1.00 2015-06-14 - First release +// +// All text above must be included in any redistribution. +// +// ********************************************************************************** +// Include Arduino header +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include +#include + +// Global project file +#include "ESP8266_WifInfo.h" + + +// To be able to read VCC from ESP SDK +ADC_MODE(ADC_VCC); + +//WiFiManager wifi(0); +ESP8266WebServer server ( 80 ); +// Udp listener and telnet server +WiFiUDP OTA; +// Teleinfo +TInfo tinfo; +// RGB Loed +NeoPixelBus rgb_led = NeoPixelBus(1, RGB_LED_PIN, NEO_RGB | NEO_KHZ800); + +// define whole brigtness level for RGBLED +uint8_t rgb_brightness = 127; +// LED Blink timers +Ticker rgb_ticker; +Ticker blu_ticker; +Ticker red_ticker; +Ticker Every_1_Sec; + +volatile boolean task_1_sec = false; +unsigned long seconds = 0; + +// sysinfo data +_sysinfo sysinfo; + +/* ====================================================================== +Function: UpdateSysinfo +Purpose : update sysinfo variables +Input : true if first call + true if needed to print on serial debug +Output : - +Comments: - +====================================================================== */ +void UpdateSysinfo(boolean first_call, boolean show_debug) +{ + char buff[64]; + int sec = seconds; + int min = sec / 60; + int hr = min / 60; + + sprintf( buff, "%02d:%02d:%02d", hr, min % 60, sec % 60); + sysinfo.sys_uptime = buff; + + sprintf( buff, "%d KB", ESP.getFreeHeap()/1024 ); + sysinfo.sys_free_ram = buff; + + sprintf( buff, "%d mV", ESP.getVcc()); + sysinfo.sys_vcc = buff; + + // Values not subject to change during running sketch + if (first_call) { + sprintf( buff, "%d KB", ESP.getFlashChipSize()/1024 ); + sysinfo.sys_flash_size = buff; + sprintf( buff, "%d KB", ESP.getSketchSize()/1024 ); + sysinfo.sys_firmware_size = buff; + sprintf( buff, "%d KB", ESP.getFreeSketchSpace()/1024 ); + sysinfo.sys_firmware_free = buff; + sprintf( buff, "%d MHZ", ESP.getFlashChipSpeed()/1000 ); + sysinfo.sys_flash_speed = buff; + } + + if (show_debug) + { + Debug(F("Firmware : ")); Debugln(__DATE__ " " __TIME__); + Debug(F("Flash Size : ")); Debugln(sysinfo.sys_flash_size); + Debug(F("CPU Speed : ")); Debugln(sysinfo.sys_flash_speed); + Debug(F("Sketch size : ")); Debugln(sysinfo.sys_firmware_size); + Debug(F("Free size : ")); Debugln(sysinfo.sys_firmware_free); + Debug(F("Free RAM : ")); Debugln(sysinfo.sys_free_ram); + Debug(F("OTA port : ")); Debugln(config.ota_port); + Debug(F("VCC : ")); Debugln(sysinfo.sys_vcc); + Debug(F("Saved Config : ")); Debugln(sysinfo.sys_eep_config); + } +} + +/* ====================================================================== +Function: Task_1_Sec +Purpose : update our second ticker +Input : - +Output : - +Comments: - +====================================================================== */ +void Task_1_Sec() +{ + task_1_sec = true; + seconds++; +} + +/* ====================================================================== +Function: LedOff +Purpose : callback called after led blink delay +Input : led (defined in term of PIN) +Output : - +Comments: - +====================================================================== */ +void LedOff(int led) +{ + if (led==BLU_LED_PIN) + LedBluOFF(); + if (led==RED_LED_PIN) + LedRedOFF(); + if (led==RGB_LED_PIN) + LedRGBOFF(); +} + +/* ====================================================================== +Function: ADPSCallback +Purpose : called by library when we detected a ADPS on any phased +Input : phase number + 0 for ADPS (monophase) + 1 for ADIR1 triphase + 2 for ADIR2 triphase + 3 for ADIR3 triphase +Output : - +Comments: should have been initialised in the main sketch with a + tinfo.attachADPSCallback(ADPSCallback()) +====================================================================== */ +void ADPSCallback(uint8_t phase) +{ + // Monophasé + if (phase == 0 ) { + Debugln(F("ADPS")); + } else { + Debug(F("ADPS Phase ")); + Debugln('0' + phase); + } +} + +/* ====================================================================== +Function: DataCallback +Purpose : callback when we detected new or modified data received +Input : linked list pointer on the concerned data + value current state being TINFO_VALUE_ADDED/TINFO_VALUE_UPDATED +Output : - +Comments: - +====================================================================== */ +void DataCallback(ValueList * me, uint8_t flags) +{ + + // This is for simulating ADPS during my tests + // =========================================== + /* + static uint8_t test = 0; + // Each new/updated values + if (++test >= 20) { + test=0; + uint8_t anotherflag = TINFO_FLAGS_NONE; + ValueList * anotherme = tinfo.addCustomValue("ADPS", "46", &anotherflag); + + // Do our job (mainly debug) + DataCallback(anotherme, anotherflag); + } + Debugf("%02d:",test); + */ + // =========================================== + + + // Do whatever you want there + Debug(me->name); + Debug('='); + Debug(me->value); + + if ( flags & TINFO_FLAGS_NOTHING ) Debug(F(" Nothing")); + if ( flags & TINFO_FLAGS_ADDED ) Debug(F(" Added")); + if ( flags & TINFO_FLAGS_UPDATED ) Debug(F(" Updated")); + if ( flags & TINFO_FLAGS_EXIST ) Debug(F(" Exist")); + if ( flags & TINFO_FLAGS_ALERT ) Debug(F(" Alert")); + + Debugln(); +} + +/* ====================================================================== +Function: NewFrame +Purpose : callback when we received a complete teleinfo frame +Input : linked list pointer on the concerned data +Output : - +Comments: - +====================================================================== */ +void NewFrame(ValueList * me) +{ + char buff[32]; + + // Light the RGB LED + LedRGBON(COLOR_GREEN); + + sprintf( buff, "New Frame (%ld Bytes free)", ESP.getFreeHeap() ); + Debugln(buff); + + // led off after delay + rgb_ticker.once_ms( (uint32_t) BLINK_LED_MS, LedOff, (int) RGB_LED_PIN); +} + +/* ====================================================================== +Function: NewFrame +Purpose : callback when we received a complete teleinfo frame +Input : linked list pointer on the concerned data +Output : - +Comments: it's called only if one data in the frame is different than + the previous frame +====================================================================== */ +void UpdatedFrame(ValueList * me) +{ + char buff[32]; + + // Light the RGB LED (purple) + LedRGBON(COLOR_MAGENTA); + + sprintf( buff, "Updated Frame (%ld Bytes free)", ESP.getFreeHeap() ); + Debugln(buff); + + // led off after delay + rgb_ticker.once_ms(BLINK_LED_MS, LedOff, RGB_LED_PIN); +} + +/* ====================================================================== +Function: CheckOTAUpdate +Purpose : Check if we need to update the firmware over the Air +Input : - +Output : - +Comments: If upgraded, no return, perform update and reboot ESP +====================================================================== */ +void CheckOTAUpdate(void) +{ + //OTA detection + if (OTA.parsePacket()) { + IPAddress remote = OTA.remoteIP(); + int cmd = OTA.parseInt(); + int port = OTA.parseInt(); + int size = OTA.parseInt(); + + Debug(F("Update Start: ip:")); + Debug(remote); + Debugf(", port:%d, size:%d\n", port, size); + uint32_t startTime = millis(); + + WiFiUDP::stopAll(); + + for (uint8_t i=0; i<=10;i++) { + LedRGBOFF(); + delay(75); + LedRGBON(COLOR_MAGENTA); + delay(25); + } + + int ww = 0; + WiFiClient client; + + if (!client.connect(remote, port)){ + Debugf("Connect Failed: %u\n", millis() - startTime); + return; + } + + client.setTimeout(10000); + int cntr = 0; + int z = 0; + uint16_t crc; + + // do until we do not get transfered full size + while (cntr0;i--) { + int b = client.read(); + + // timeout + if (b == -1) + break; + + crc += (byte)b; + z++; + cntr++; + } + + // Printback code differ from original espota.py + if (z) + client.printf(PSTR("%d %d\n"), z, crc); + } + Debugf("Done %d/%d\r\n", cntr, size); + + // All transfered ? + if(cntr>=size) { + client.print("OK"); + Debugf("Update Success in %u ms\r\nRebooting...\r\n", millis() - startTime); + ESP.restart(); + } else { + Update.printError(client); + Update.printError(Serial1); + } + } + + // Be sure to re enable it + OTA.begin(config.ota_port); +} + +/* ====================================================================== +Function: WifiHandleConn +Purpose : Handle Wifi connection / reconnection and OTA updates +Input : - +Output : state of the wifi status +Comments: - +====================================================================== */ +int WifiHandleConn() +{ + int ret = WiFi.status(); + + // Wait for connection if disconnected + if ( ret != WL_CONNECTED ) { + // Yellow we're not connected anymore + LedRGBON(COLOR_YELLOW); + + Debug(F("Connecting to: ")); + Debug( config.ssid ); + Debug(F("...")); + + WiFi.begin(config.ssid, config.pass); + + ret = WiFi.waitForConnectResult(); + if ( ret != WL_CONNECTED) { + Debugln(F("Connection failed!")); + } else { + Debugln(F("Connected")); + Debug(F("IP address : ")); Debugln(WiFi.localIP()); + Debug(F("MAC address : ")); Debugln(WiFi.macAddress()); + + MDNS.begin(config.host); + MDNS.addService("arduino", "tcp", config.ota_port); + OTA.begin(config.ota_port); + + // just in case your sketch sucks, keep update OTA Available + // Trust me, when coding and testing it happens, this could save + // the need to connect FTDI to reflash + // Usefull just after 1st connexion when called from setup() before + // launching potentially bugging main() + for (uint8_t i=0; i<= 20; i++) { + LedRGBON(COLOR_GREEN); + delay(25); + LedRGBOFF(); + delay(75); + CheckOTAUpdate(); + } + } + } + + // Handle OTA if we're connected + if ( ret == WL_CONNECTED ) + CheckOTAUpdate(); + + return ret; +} + +/* ====================================================================== +Function: setup +Purpose : Setup I/O and other one time startup stuff +Input : - +Output : - +Comments: - +====================================================================== */ +void setup() +{ + // Set WiFi to station mode and disconnect from an AP if it was previously connected + //WiFi.mode(WIFI_STA); + //WiFi.disconnect(); + //delay(100); + + // Init the serial 1 + // Teleinfo is connected to RXD2 (GPIO13) to + // avoid conflict when flashing, this is why + // we swap RXD1/RXD1 to RXD2/TXD2 + // Note that TXD2 is not used teleinfo is receive only + Serial.begin(1200, SERIAL_7E1); + Serial.swap(); + + // Our Debug Serial TXD0 + // note this serial can only transmit, just + // enough for debugging purpose + Serial1.begin(115200); + + Debugln(F("============")); + Debugln(F("Wifinfo V1.0")); + Debugln(); + Debugflush(); + + // Clear our global flags + config.config = 0; + + // Our configuration is stored into EEPROM + EEPROM.begin(sizeof(_Config)); + + // Read Configuration from EEP + if (readConfig()) { + sysinfo.sys_eep_config = PSTR("good CRC, config OK"); + } else { + // Error, enable default configuration + strcpy_P(config.ssid, PSTR(DEFAULT_WIFI_SSID)); + strcpy_P(config.pass, PSTR(DEFAULT_WIFI_PASS)); + strcpy_P(config.host, PSTR(DEFAULT_HOSTNAME)); + config.ota_port = DEFAULT_OTA_PORT ; + + // Indicate the error in global flags + config.config |= CFG_BAD_CRC; + sysinfo.sys_eep_config = PSTR("Bad CRC, reset to default"); + + // save back + saveConfig(); + } + + Debugln(sysinfo.sys_eep_config); + + // Init teleinfo + tinfo.init(); + + // Attach the callback we need + // set all as an example + tinfo.attachADPS(ADPSCallback); + tinfo.attachData(DataCallback); + tinfo.attachNewFrame(NewFrame); + tinfo.attachUpdatedFrame(UpdatedFrame); + + // Init the RGB Led + rgb_led.Begin(); + + // We'll drive the on board LED (TXD1) and our on GPIO1 + // old TXD1, not used anymore, has been swapped + pinMode(BLU_LED_PIN, OUTPUT); + pinMode(RED_LED_PIN, OUTPUT); + LedRedOFF(); + LedBluOFF(); + + // connect + WifiHandleConn(); + + // Update sysinfor variable and print them + UpdateSysinfo(true, true); + + server.on("/", handleRoot); + server.on("/json", sendJSON); + server.on("/tinfojsontbl", tinfoJSONTable); + server.on("/sysjsontbl", sysJSONTable); + server.onNotFound(handleNotFound); + server.begin(); + + Debugln(F("HTTP server started")); + + //webSocket.begin(); + //webSocket.onEvent(webSocketEvent); + + // Light off the RGB LED + LedRGBOFF(); + + // control watchdog + ESP.wdtEnable(WDTO_4S); + //ESP.wdtDisable() + ESP.wdtFeed(); + + // Update sysinfo every second + Every_1_Sec.attach(1, Task_1_Sec); +} + +/* ====================================================================== +Function: loop +Purpose : infinite loop main code +Input : - +Output : - +Comments: - +====================================================================== */ +void loop() +{ + static char c; + + // Handle connection/disconnection/OTA update + if ( WifiHandleConn() == WL_CONNECTED ) { + + // Do all related network stuff + server.handleClient(); + + //webSocket.loop(); + } + + // 1 second task job ? + if (task_1_sec) { + UpdateSysinfo(false, false); + task_1_sec = false; + } + + // Handle teleinfo serial + if ( Serial.available() ) { + // Read Serial and process to tinfo + c = Serial.read(); + //Serial1.print(c); + tinfo.process(c); + } +} + diff --git a/examples/ESP8266_WifInfo/config.cpp b/examples/ESP8266_WifInfo/config.cpp new file mode 100644 index 0000000..aec3c09 --- /dev/null +++ b/examples/ESP8266_WifInfo/config.cpp @@ -0,0 +1,173 @@ +// ********************************************************************************** +// ESP8266 Teleinfo WEB Server configuration Include file +// ********************************************************************************** +// Creative Commons Attrib Share-Alike License +// You are free to use/extend this library but please abide with the CC-BY-SA license: +// Attribution-NonCommercial-ShareAlike 4.0 International License +// http://creativecommons.org/licenses/by-nc-sa/4.0/ +// +// For any explanation about teleinfo ou use , see my blog +// http://hallard.me/category/tinfo +// +// This program works with the Wifinfo board +// see schematic here https://github.com/hallard/teleinfo/tree/master/Wifinfo +// +// Written by Charles-Henri Hallard (http://hallard.me) +// +// History : V1.00 2015-06-14 - First release +// +// All text above must be included in any redistribution. +// +// ********************************************************************************** +#include "./config.h" + +// Configuration structure for whole program +_Config config; + + +uint16_t crc16Update(uint16_t crc, uint8_t a) +{ + int i; + crc ^= a; + for (i = 0; i < 8; ++i) { + if (crc & 1) + crc = (crc >> 1) ^ 0xA001; + else + crc = (crc >> 1); + } + return crc; +} + +/* ====================================================================== +Function: eeprom_dump +Purpose : dump eeprom value to serial +Input : - +Output : - +Comments: - +====================================================================== */ +void eepromDump(uint8_t bytesPerRow) +{ + uint16_t i,b; + char buf[10]; + uint16_t j=0 ; + + // default to 16 bytes per row + if (bytesPerRow==0) + bytesPerRow=16; + + Debugln(); + + // loop thru EEP address + for (i = 0; i <= sizeof(_Config); i++) { + // First byte of the row ? + if (j==0) { + // Display Address + Debug(buf); + Debugf("%04X : ", i); + } + + // write byte in hex form + Debugf("%02X ", EEPROM.read(i)); + + // Last byte of the row ? + // start a new line + if (++j >= bytesPerRow) { + j=0; + Debugln(); + } + } +} + +/* ====================================================================== +Function: readConfig +Purpose : fill config structure with data located into eeprom +Input : - +Output : true if config found and crc ok, false otherwise +Comments: - +====================================================================== */ +bool readConfig (void) +{ + uint16_t crc = ~0; + uint8_t * pconfig = (uint8_t *) &config ; + uint8_t data ; + + // For whole size of config structure + for (uint8_t i = 0; i < sizeof(_Config); ++i) { + // read data + data = EEPROM.read(i); + + // save into struct + *pconfig++ = data ; + + // calc CRC + crc = crc16Update(crc, data); + } + + // CRC Error ? + if (crc != 0) { + // Clear config + memset(&config, 0, sizeof( _Config )); + return false; + } + + return true ; +} + +/* ====================================================================== +Function: saveConfig +Purpose : save config structure values into eeprom +Input : - +Output : true if saved and readback ok +Comments: once saved, config is read again to check the CRC +====================================================================== */ +bool saveConfig (void) +{ + uint8_t * pconfig ; + bool ret_code; + + // Init pointer + pconfig = (uint8_t *) &config ; + + // Init CRC + config.crc = ~0; + + // For whole size of config structure, pre-calculate CRC + for (uint8_t i = 0; i < sizeof (_Config) - 2; ++i) + config.crc = crc16Update(config.crc, *pconfig++); + + // Re init pointer + pconfig = (uint8_t *) &config ; + + // For whole size of config structure, write to EEP + for (byte i = 0; i < sizeof(_Config); ++i) + EEPROM.write(i, *pconfig++); + + // Physically save + EEPROM.commit(); + + // Read Again to see if saved ok + ret_code = readConfig(); + + Debug(F("Write config")); + + if (ret_code) + Debugln(F("OK!")); + else + Debugln(F("Error!")); + + // return result + return (ret_code); +} + +/* ====================================================================== +Function: showConfig +Purpose : display configuration +Input : - +Output : - +Comments: - +====================================================================== */ +void showConfig() +{ + +} + diff --git a/examples/ESP8266_WifInfo/config.h b/examples/ESP8266_WifInfo/config.h new file mode 100644 index 0000000..36cfb67 --- /dev/null +++ b/examples/ESP8266_WifInfo/config.h @@ -0,0 +1,69 @@ +// ********************************************************************************** +// ESP8266 Teleinfo WEB Server configuration Include file +// ********************************************************************************** +// Creative Commons Attrib Share-Alike License +// You are free to use/extend this library but please abide with the CC-BY-SA license: +// Attribution-NonCommercial-ShareAlike 4.0 International License +// http://creativecommons.org/licenses/by-nc-sa/4.0/ +// +// For any explanation about teleinfo ou use , see my blog +// http://hallard.me/category/tinfo +// +// This program works with the Wifinfo board +// see schematic here https://github.com/hallard/teleinfo/tree/master/Wifinfo +// +// Written by Charles-Henri Hallard (http://hallard.me) +// +// History : V1.00 2015-06-14 - First release +// +// All text above must be included in any redistribution. +// +// ********************************************************************************** +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +// Include main project include file +#include "ESP8266_WifInfo.h" + +#define CFG_MAX_SSID_SIZE 32 +#define CFG_MAX_PASS_SIZE 32 +#define CFG_MAX_HOSTNAME 16 + +// Mettez ici vos identifiant de connexion à +// votre réseau WIFI +#define DEFAULT_WIFI_SSID "************" +#define DEFAULT_WIFI_PASS "************" +#define DEFAULT_HOSTNAME "WifInfo-esp01" +#define DEFAULT_OTA_PORT 8266 + +// Bit definition for different configuration modes +#define CFG_LCD 0x0001 // Enable display +#define CFG_DEBUG 0x0002 // Enable serial debug +#define CFG_BAD_CRC 0x8000 // Bad CRC when reading configuration + +// Config saved into eeprom +// 128 bytes total including CRC +typedef struct +{ + char ssid[CFG_MAX_SSID_SIZE]; /* SSID */ + char pass[CFG_MAX_PASS_SIZE]; /* Password */ + char host[CFG_MAX_HOSTNAME]; /* Password */ + uint32_t config; /* Bit field register */ + uint16_t ota_port; /* OTA port */ + uint8_t filler[40]; /* in case adding data in config avoiding loosing current conf by bad crc*/ + uint16_t crc; +} _Config; + + +// Exported variables/object instancied in main sketch +// =================================================== +extern _Config config; + +// Declared exported function from route.cpp +// =================================================== +bool readConfig (void); +bool saveConfig (void); + + +#endif + diff --git a/examples/ESP8266_WifInfo/route.cpp b/examples/ESP8266_WifInfo/route.cpp new file mode 100644 index 0000000..0471373 --- /dev/null +++ b/examples/ESP8266_WifInfo/route.cpp @@ -0,0 +1,558 @@ +// ********************************************************************************** +// ESP8266 Teleinfo WEB Server, route web function +// ********************************************************************************** +// Creative Commons Attrib Share-Alike License +// You are free to use/extend this library but please abide with the CC-BY-SA license: +// Attribution-NonCommercial-ShareAlike 4.0 International License +// http://creativecommons.org/licenses/by-nc-sa/4.0/ +// +// For any explanation about teleinfo ou use , see my blog +// http://hallard.me/category/tinfo +// +// This program works with the Wifinfo board +// see schematic here https://github.com/hallard/teleinfo/tree/master/Wifinfo +// +// Written by Charles-Henri Hallard (http://hallard.me) +// +// History : V1.00 2015-06-14 - First release +// +// All text above must be included in any redistribution. +// +// ********************************************************************************** + +// Include Arduino header +#include "route.h" + +/* ====================================================================== +Function: handleRoot +Purpose : handle main page /, display information +Input : - +Output : - +Comments: - +====================================================================== */ +void handleRoot(void) +{ + String response=""; + + // Just to debug where we are + Debug(F("Serving / page...")); + + LedBluON(); + + // start HTML Code + response += F("" + "" + "" + "" + "" + // Our custom style + "" + "" + "" + "Wifinfo" + ""); + + response += F("
" + // Onglets + ""); + + // Contenu des onglets + response += F("
"); + + // tab teleinfo + response += F( "
" + "

Données de Téléinformation

" + "
Charge courante : " + "
" + "
" + "Attente des données" + "
" + "
" + "
" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "
EtiquetteValeurChecksumFlags
" + "
"); // tab pane + // tab Systeme + response += F( "
" + "

Données du système

" + "" + "" + "" + "" + "" + "" + "" + "
DonnéeValeur
" + "
"); // tab pane + + // tab Configuration + response += F( "
" + "

Configuration du module WifInfo

" + "

Cette partie reste à faire, des volontaires motivés ?

" + "
"); // tab pane + + response += F("
"); // tab content + +/* + response += F("")); +*/ + + response += F("
\r\n"); // Container + response += F("\r\n"); + response += F("\r\n"); + response += F("\r\n"); + + response += F("" "\r\n"); + + response += F(""); + + response += F("\r\n"); + + // Just to debug buffer free size + Debug(F("sending ")); + Debug(response.length()); + Debug(F(" bytes...")); + + // Send response to client + server.send ( 200, "text/html", response ); + + Debug(F("OK!")); + + LedBluOFF(); +} + +/* ====================================================================== +Function: formatNumberJSON +Purpose : check if data value is full number and send correct JSON format +Input : String where to add response + char * value to check +Output : - +Comments: 00150 => 150 + ADCO => "ADCO" + 1 => 1 +====================================================================== */ +void formatNumberJSON( String &response, char * value) +{ + // we have at least something ? + if (value && strlen(value)) + { + boolean isNumber = true; + uint8_t c; + char * p = value; + + // just to be sure + if (strlen(p)<=16) { + // check if value is number + while (*p && isNumber) { + if ( *p < '0' || *p > '9' ) + isNumber = false; + p++; + } + + // this will add "" on not number values + if (!isNumber) { + response += '\"' ; + response += value ; + response += F("\":") ; + } else { + // this will remove leading zero on numbers + p = value; + while (*p=='0' && *(p+1) ) + p++; + response += p ; + } + } else { + Debugln(F("formatNumberJSON error!")); + } + } +} + + +/* ====================================================================== +Function: tinfoJSONTable +Purpose : dump all teleinfo values in JSON table format for browser +Input : linked list pointer on the concerned data + true to dump all values, false for only modified ones +Output : - +Comments: - +====================================================================== */ +void tinfoJSONTable(void) +{ + ValueList * me = tinfo.getList(); + String response = ""; + + // Just to debug where we are + Debug(F("Serving /tinfoJSONTable page...\r\n")); + + // Got at least one ? + if (me) { + uint8_t index=0; + + boolean first_item = true; + // Json start + response += F("[\r\n"); + + // Loop thru the node + while (me->next) { + + // we're there + ESP.wdtFeed(); + + // go to next node + me = me->next; + + // First item do not add , separator + if (first_item) + first_item = false; + else + response += F(",\r\n"); + + Debug(F("(")) ; + Debug(++index) ; + Debug(F(") ")) ; + + if (me->name) Debug(me->name) ; + else Debug(F("NULL")) ; + + Debug(F("=")) ; + + if (me->value) Debug(me->value) ; + else Debug(F("NULL")) ; + + Debug(F(" '")) ; + Debug(me->checksum) ; + Debug(F("' ")); + + // Flags management + if ( me->flags) { + Debug(F("Flags:0x")); + Debugf("%02X => ", me->flags); + if ( me->flags & TINFO_FLAGS_EXIST) + Debug(F("Exist ")) ; + if ( me->flags & TINFO_FLAGS_UPDATED) + Debug(F("Updated ")) ; + if ( me->flags & TINFO_FLAGS_ADDED) + Debug(F("New ")) ; + } + + Debugln() ; + + response += F("{\"na\":\""); + response += me->name ; + response += F("\", \"va\":\"") ; + response += me->value; + response += F("\", \"ck\":\"") ; + if (me->checksum == '"' || me->checksum == '\\' || me->checksum == '/') + response += '\\'; + response += (char) me->checksum; + response += F("\", \"fl\":"); + response += me->flags ; + response += '}' ; + + } + // Json end + response += F("\r\n]"); + + } else { + Debugln(F("sending 404...")); + server.send ( 404, "text/plain", "No data" ); + } + Debug(F("sending...")); + server.send ( 200, "text/json", response ); + Debugln(F("OK!")); +} + +/* ====================================================================== +Function: sysJSONTable +Purpose : dump all sysinfo values in JSON table format for browser +Input : linked list pointer on the concerned data + true to dump all values, false for only modified ones +Output : - +Comments: - +====================================================================== */ +void sysJSONTable() +{ + String response = ""; + + // Just to debug where we are + Debug(F("Serving /sysJSONTable page...")); + + // Json start + response += F("[\r\n"); + + response += "{\"na\":\"Uptime\",\"va\":\""; + response += sysinfo.sys_uptime; + response += "\"},\r\n"; + + response += "{\"na\":\"Compile le\",\"va\":\"" __DATE__ " " __TIME__ "\"},\r\n"; + response += "{\"na\":\"Free Ram\",\"va\":\""; + response += sysinfo.sys_free_ram; + response += "\"},\r\n"; + + response += "{\"na\":\"Flash Size\",\"va\":\""; + response += sysinfo.sys_flash_size ; + response += "\"},\r\n"; + + response += "{\"na\":\"Firmware Size\",\"va\":\""; + response += sysinfo.sys_firmware_size; + response += "\"},\r\n"; + + response += "{\"na\":\"Free Size\",\"va\":\""; + response += sysinfo.sys_firmware_free; + response += "\"},\r\n"; + + response += "{\"na\":\"Wifi SSID\",\"va\":\""; + response += config.ssid; + response += "\"},\r\n"; + + response += "{\"na\":\"OTA Network Port\",\"va\":"; + response += config.ota_port ; + response += "},\r\n"; + + response += "{\"na\":\"Wifi RSSI\",\"va\":\""; + response += WiFi.RSSI() ; + response += " dB\"}\r\n"; + + // Json end + response += F("]\r\n"); + + Debug(F("sending...")); + server.send ( 200, "text/json", response ); + Debugln(F("Ok!")); +} + +/* ====================================================================== +Function: sendJSON +Purpose : dump all values in JSON +Input : linked list pointer on the concerned data + true to dump all values, false for only modified ones +Output : - +Comments: - +====================================================================== */ +void sendJSON(void) +{ + ValueList * me = tinfo.getList(); + String response = ""; + + // Got at least one ? + if (me) { + // Json start + response += F("{\"_UPTIME\":"); + response += seconds; + + // Loop thru the node + while (me->next) { + + // we're there + ESP.wdtFeed(); + + // go to next node + me = me->next; + + response += F(",\"") ; + response += me->name ; + response += F("\":") ; + formatNumberJSON(response, me->value); + } + // Json end + response += F("}\r\n") ; + + } else { + server.send ( 404, "text/plain", "No data" ); + } + server.send ( 200, "text/json", response ); +} + +/* ====================================================================== +Function: handleNotFound +Purpose : default WEB routing when URI is not found +Input : linked list pointer on the concerned data + true to dump all values, false for only modified ones +Output : - +Comments: We search is we have a name that match to this URI, if one we + return it's pair name/value in json +====================================================================== */ +void handleNotFound(void) +{ + String response = ""; + + // We check for an known label + ValueList * me = tinfo.getList(); + const char * uri; + boolean found = false; + + // Led on + LedBluON(); + + // convert uri to char * for compare + uri = server.uri().c_str(); + + Debugf("handleNotFound(%s)\r\n", uri); + + // Got at least one and consistent URI ? + if (me && uri && *uri=='/' && *++uri ) { + + // Loop thru the linked list of values + while (me->next && !found) { + + // we're there + ESP.wdtFeed(); + + // go to next node + me = me->next; + + //Debugf("compare to '%s' ", me->name); + // Do we have this one ? + if (stricmp (me->name, uri) == 0 ) + { + // no need to continue + found = true; + + // Add to respone + response += F("{\"") ; + response += me->name ; + response += F("\":") ; + formatNumberJSON(response, me->value); + response += F("}\r\n"); + } + } + } + + // Got it, send json + if (found) { + server.send ( 200, "text/json", response ); + } else { + // send error message in plain text + String message = "File Not Found\n\n"; + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += ( server.method() == HTTP_GET ) ? "GET" : "POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + + for ( uint8_t i = 0; i < server.args(); i++ ) { + message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n"; + } + + server.send ( 404, "text/plain", message ); + } + + // Led off + LedBluOFF(); +} + diff --git a/examples/ESP8266_WifInfo/route.h b/examples/ESP8266_WifInfo/route.h new file mode 100644 index 0000000..015ca66 --- /dev/null +++ b/examples/ESP8266_WifInfo/route.h @@ -0,0 +1,47 @@ +// ********************************************************************************** +// ESP8266 Teleinfo WEB Server routing Include file +// ********************************************************************************** +// Creative Commons Attrib Share-Alike License +// You are free to use/extend this library but please abide with the CC-BY-SA license: +// Attribution-NonCommercial-ShareAlike 4.0 International License +// http://creativecommons.org/licenses/by-nc-sa/4.0/ +// +// For any explanation about teleinfo ou use , see my blog +// http://hallard.me/category/tinfo +// +// This program works with the Wifinfo board +// see schematic here https://github.com/hallard/teleinfo/tree/master/Wifinfo +// +// Written by Charles-Henri Hallard (http://hallard.me) +// +// History : V1.00 2015-06-14 - First release +// +// All text above must be included in any redistribution. +// +// ********************************************************************************** + +#ifndef ROUTE_H +#define ROUTE_H + +// Include main project include file +#include "ESP8266_WifInfo.h" + +// Web response max size +#define RESPONSE_BUFFER_SIZE 4096 + +// Exported variables/object instancied in main sketch +// =================================================== +extern char response[]; +extern uint16_t response_idx; + +// declared exported function from route.cpp +// =================================================== +void handleTest(void); +void handleRoot(void); +void handleNotFound(void); +void tinfoJSONTable(void); +void sysJSONTable(void); +void sendJSON(void); + + +#endif