Création
This commit is contained in:
parent
b4717923d7
commit
fbf038dd8b
|
@ -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 <Arduino.h>
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266WebServer.h>
|
||||||
|
#include <ESP8266mDNS.h>
|
||||||
|
#include <WiFiUDP.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <Ticker.h>
|
||||||
|
//#include <WebSocketsServer.h>
|
||||||
|
//#include <Hash.h>
|
||||||
|
#include <NeoPixelBus.h>
|
||||||
|
#include <LibTeleinfo.h>
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
|
@ -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 <Arduino.h>
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266WebServer.h>
|
||||||
|
#include <ESP8266mDNS.h>
|
||||||
|
#include <WiFiUDP.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <Ticker.h>
|
||||||
|
//#include <WebSocketsServer.h>
|
||||||
|
//#include <Hash.h>
|
||||||
|
#include <NeoPixelBus.h>
|
||||||
|
#include <LibTeleinfo.h>
|
||||||
|
|
||||||
|
// 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 (cntr<size) {
|
||||||
|
z = 0;
|
||||||
|
crc = 0;
|
||||||
|
for(int i=client.available();i>0;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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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("<html><head>"
|
||||||
|
"<meta name='viewport' content='width=device-width, initial-scale=1'>"
|
||||||
|
"<meta charset='UTF-8'>"
|
||||||
|
"<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css'>"
|
||||||
|
"<link rel='stylesheet' href='//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.8.1/bootstrap-table.min.css'>"
|
||||||
|
// Our custom style
|
||||||
|
"<style type='text/css'>"
|
||||||
|
".nav-tabs {margin-top:4px;}"
|
||||||
|
".fixed-table-body {height:auto;}"
|
||||||
|
".progress {position:relative;}"
|
||||||
|
".progress span {position:absolute;display:block;width:100%;color:black;}"
|
||||||
|
"</style>"
|
||||||
|
"<script src='http://code.jquery.com/jquery-2.1.3.min.js'></script>"
|
||||||
|
"<script src='http://cdn.rawgit.com/Foliotek/AjaxQ/master/ajaxq.js'></script>"
|
||||||
|
"<title>Wifinfo</title>"
|
||||||
|
"</head><body>");
|
||||||
|
|
||||||
|
response += F("<div class='container'>"
|
||||||
|
// Onglets
|
||||||
|
"<ul class='nav nav-tabs' id='myTab'>"
|
||||||
|
"<li class='active'>"
|
||||||
|
"<a href='#tab_tinfo' data-toggle='tab'>"
|
||||||
|
"Téléinformation <span class='badge' id='scharge'></span>"
|
||||||
|
"</a>"
|
||||||
|
"</li>"
|
||||||
|
"<li><a href='#tab_sys' data-toggle='tab'>Système</a></li>"
|
||||||
|
"<li><a href='#tab_cfg' data-toggle='tab'>Configuration</a></li>"
|
||||||
|
"</ul>");
|
||||||
|
|
||||||
|
// Contenu des onglets
|
||||||
|
response += F("<div class='tab-content'>");
|
||||||
|
|
||||||
|
// tab teleinfo
|
||||||
|
response += F( "<div class='tab-pane fade in active' id='tab_tinfo'>"
|
||||||
|
"<h4>Données de Téléinformation</h4>"
|
||||||
|
"<div><span style='float:left;width:18ex;text-align:center;'>Charge courante : </span>"
|
||||||
|
"<div class='progress'>"
|
||||||
|
"<div class='progress-bar progress-bar-success' style='width:0' id='pbar'>"
|
||||||
|
"<span class=show id='pcharge'>Attente des données</span>"
|
||||||
|
"</div></div></div>"
|
||||||
|
"<div id='toolbar'>"
|
||||||
|
"</div>"
|
||||||
|
"<table data-toggle='table' "
|
||||||
|
"data-toolbar='#toolbar'"
|
||||||
|
"data-url='/tinfojsontbl' "
|
||||||
|
"class='table table-striped' "
|
||||||
|
"data-show-refresh='true' "
|
||||||
|
"data-show-toggle='true' "
|
||||||
|
"data-show-columns='true' "
|
||||||
|
"data-search='true' "
|
||||||
|
"data-row-style='rowStyle' "
|
||||||
|
"id='tblinfo' "
|
||||||
|
"data-select-item-name='toolbar1'>"
|
||||||
|
"<thead>"
|
||||||
|
"<tr>"
|
||||||
|
"<th data-field='na' data-align='left' data-sortable='true' data-formatter='labelFormatter'>Etiquette</th>"
|
||||||
|
"<th data-field='va' data-align='left' data-sortable='true' data-formatter='valueFormatter'>Valeur</th>"
|
||||||
|
"<th data-field='ck' data-align='center'>Checksum</th>"
|
||||||
|
"<th data-field='fl' data-align='center' data-visible='false'>Flags</th>"
|
||||||
|
"</tr>"
|
||||||
|
"</thead>"
|
||||||
|
"</table>"
|
||||||
|
"</div>"); // tab pane
|
||||||
|
// tab Systeme
|
||||||
|
response += F( "<div class='tab-pane fade' id='tab_sys'>"
|
||||||
|
"<h4>Données du système</h4>"
|
||||||
|
"<table data-toggle='table' "
|
||||||
|
"data-url='/sysjsontbl' "
|
||||||
|
"class='table table-striped' "
|
||||||
|
"data-show-refresh='true' "
|
||||||
|
"data-show-toggle='true' "
|
||||||
|
"data-search='true' "
|
||||||
|
"id='tblsys' "
|
||||||
|
"data-select-item-name='toolbar2'>"
|
||||||
|
"<thead>"
|
||||||
|
"<tr>"
|
||||||
|
"<th data-field='na' data-align='left'>Donnée</th>"
|
||||||
|
"<th data-field='va' data-align='left'>Valeur</th>"
|
||||||
|
"</tr>"
|
||||||
|
"</thead>"
|
||||||
|
"</table>"
|
||||||
|
"</div>"); // tab pane
|
||||||
|
|
||||||
|
// tab Configuration
|
||||||
|
response += F( "<div class='tab-pane fade' id='tab_cfg'>"
|
||||||
|
"<h4>Configuration du module WifInfo</h4>"
|
||||||
|
"<p>Cette partie reste à faire, des volontaires motivés ?</p>"
|
||||||
|
"</div>"); // tab pane
|
||||||
|
|
||||||
|
response += F("</div>"); // tab content
|
||||||
|
|
||||||
|
/*
|
||||||
|
response += F("<script>$( document ).ready(function() {"));
|
||||||
|
response += F("$.getq('queue','/"));
|
||||||
|
response += F("Uptime"));
|
||||||
|
response += F("', function(data) { $('#"));
|
||||||
|
response += F("Uptime"));
|
||||||
|
response += F("').html(data."));
|
||||||
|
response += F("Uptime"));
|
||||||
|
response += F("); });"));
|
||||||
|
response += F("});</script>"));
|
||||||
|
*/
|
||||||
|
|
||||||
|
response += F("</div>\r\n"); // Container
|
||||||
|
response += F("<script src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js'></script>\r\n");
|
||||||
|
response += F("<script src='//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.8.1/bootstrap-table.min.js'></script>\r\n");
|
||||||
|
response += F("<script src='//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.8.1/locale/bootstrap-table-fr-FR.min.js'></script>\r\n");
|
||||||
|
|
||||||
|
response += F("<script>" "\r\n"
|
||||||
|
"var counters={};"
|
||||||
|
"var isousc, iinst;"
|
||||||
|
"function rowStyle(row, index){" "\r\n"
|
||||||
|
"var classes=['active','success','info','warning','danger'];" "\r\n"
|
||||||
|
"var flags=parseInt(row.fl,10);" "\r\n"
|
||||||
|
"if (flags&0x80){return{classes:classes[4]};}""\r\n"
|
||||||
|
"if (flags&0x02){return{classes:classes[3]};}""\r\n"
|
||||||
|
"if (flags&0x08){return{classes:classes[1]};}""\r\n"
|
||||||
|
"return {};""\r\n"
|
||||||
|
"}""\r\n"
|
||||||
|
"function labelFormatter(value, row){" "\r\n"
|
||||||
|
"var flags=parseInt(row.fl,10);" "\r\n"
|
||||||
|
"if (typeof counters[value]==='undefined') counters[value]=1;" "\r\n"
|
||||||
|
"if (flags&0x88) counters[value]++;" "\r\n"
|
||||||
|
"return value + ' <span class=\"badge\">'+counters[value]+'</span>';" "\r\n"
|
||||||
|
"}" "\r\n"
|
||||||
|
"function valueFormatter(value, row){" "\r\n"
|
||||||
|
"if (row.na==\"ISOUSC\")" "\r\n"
|
||||||
|
"isousc=parseInt(value);" "\r\n"
|
||||||
|
"else if (row.na==\"IINST\"){" "\r\n"
|
||||||
|
"var pb, pe, cl;" "\r\n"
|
||||||
|
"iinst=parseInt(value);" "\r\n"
|
||||||
|
"pe=parseInt(iinst*100/isousc);" "\r\n"
|
||||||
|
"if (isNaN(pe)) pe=0;" "\r\n"
|
||||||
|
"cl='success';" "\r\n"
|
||||||
|
"if (pe>70) cl ='info';" "\r\n"
|
||||||
|
"if (pe>80) cl ='warning';" "\r\n"
|
||||||
|
"if (pe>90) cl ='danger';" "\r\n"
|
||||||
|
"cl = 'progress-bar-' + cl;" "\r\n"
|
||||||
|
"if (pe>0) $('#scharge').text(pe+'%');" "\r\n"
|
||||||
|
"if (typeof isousc!='undefined')" "\r\n"
|
||||||
|
" $('#pcharge').text(iinst+'A / '+isousc+'A');" "\r\n"
|
||||||
|
"$('#pbar').attr('class','progress-bar '+cl);" "\r\n"
|
||||||
|
"$('#pbar').css('width', pe+'%');"" \r\n"
|
||||||
|
"}" "\r\n"
|
||||||
|
"return value;" "\r\n"
|
||||||
|
"}" "\r\n"
|
||||||
|
"</script>" "\r\n");
|
||||||
|
|
||||||
|
response += F("<script>" "\r\n"
|
||||||
|
"var myTimer;" "\r\n"
|
||||||
|
"function myRefresh(){" "\r\n"
|
||||||
|
"var id=$('.nav-tabs .active > a').attr('href');" "\r\n"
|
||||||
|
"if (id=='#tab_tinfo') id='#tblinfo';" "\r\n"
|
||||||
|
"if (id=='#tab_sys') id='#tblsys';" "\r\n"
|
||||||
|
#ifdef DEBUG
|
||||||
|
"console.log('Refreshing : '+id);" "\r\n"
|
||||||
|
#endif
|
||||||
|
"clearInterval(myTimer);" "\r\n"
|
||||||
|
"$('#tblinfo').bootstrapTable('refresh',{silent: true});" "\r\n"
|
||||||
|
"if (id=='#tblsys')" "\r\n"
|
||||||
|
"$(id).bootstrapTable('refresh',{silent: true});" "\r\n"
|
||||||
|
"}""\r\n"
|
||||||
|
|
||||||
|
"$(function () {" "\r\n"
|
||||||
|
"$('#tblinfo').on('load-success.bs.table', function (e, data) {" "\r\n"
|
||||||
|
#ifdef DEBUG
|
||||||
|
"console.log('Event: load-success.bs.table');" "\r\n"
|
||||||
|
#endif
|
||||||
|
"myTimer=setInterval(function(){myRefresh()},1000);" "\r\n"
|
||||||
|
"})" "\r\n"
|
||||||
|
".on('load-error.bs.table', function (e, status) {" "\r\n"
|
||||||
|
#ifdef DEBUG
|
||||||
|
"console.log('Event: load-error.bs.table');" "\r\n"
|
||||||
|
#endif
|
||||||
|
"myTimer=setInterval(function(){myRefresh()},5000);" "\r\n"
|
||||||
|
"})" "\r\n"
|
||||||
|
"});" "\r\n"
|
||||||
|
"</script>");
|
||||||
|
|
||||||
|
response += F("</body></html>\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();
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue