mirror of https://github.com/jeelabs/esp-link.git
parent
f220122ca8
commit
8a8649aab6
@ -1,207 +0,0 @@ |
|||||||
#include "EspLink.h" |
|
||||||
|
|
||||||
#define READ_BUF_DFLT_SIZE 64 |
|
||||||
|
|
||||||
// Standard SLIP escape chars from RFC
|
|
||||||
#define SLIP_END 0300 // indicates end of packet
|
|
||||||
#define SLIP_ESC 0333 // indicates byte stuffing
|
|
||||||
#define SLIP_ESC_END 0334 // ESC ESC_END means END data byte
|
|
||||||
#define SLIP_ESC_ESC 0335 // ESC ESC_ESC means ESC data byte
|
|
||||||
|
|
||||||
EspLink::EspLink(Stream &streamIn, CmdRequestCB callback):stream(streamIn),requestCb(callback) |
|
||||||
{ |
|
||||||
readBuf = NULL; |
|
||||||
readLastChar = 0; |
|
||||||
} |
|
||||||
|
|
||||||
EspLink::~EspLink() |
|
||||||
{ |
|
||||||
if( readBuf != NULL ) |
|
||||||
free( readBuf ); |
|
||||||
readBuf = NULL; |
|
||||||
} |
|
||||||
|
|
||||||
void EspLink::writeChar(uint8_t data) |
|
||||||
{ |
|
||||||
switch(data) |
|
||||||
{ |
|
||||||
case SLIP_END: |
|
||||||
stream.write(SLIP_ESC); |
|
||||||
stream.write(SLIP_ESC_END); |
|
||||||
break; |
|
||||||
case SLIP_ESC: |
|
||||||
stream.write(SLIP_ESC); |
|
||||||
stream.write(SLIP_ESC_ESC); |
|
||||||
break; |
|
||||||
default: |
|
||||||
stream.write(data); |
|
||||||
} |
|
||||||
|
|
||||||
crc16_add(data, &crc16_out); |
|
||||||
} |
|
||||||
|
|
||||||
/* CITT CRC16 polynomial ^16 + ^12 + ^5 + 1 */ |
|
||||||
/*---------------------------------------------------------------------------*/ |
|
||||||
void EspLink::crc16_add(uint8_t b, uint16_t *crc) |
|
||||||
{ |
|
||||||
*crc ^= b; |
|
||||||
*crc = (*crc >> 8) | (*crc << 8); |
|
||||||
*crc ^= (*crc & 0xff00) << 4; |
|
||||||
*crc ^= (*crc >> 8) >> 4; |
|
||||||
*crc ^= (*crc & 0xff00) >> 5; |
|
||||||
} |
|
||||||
|
|
||||||
void EspLink::writeBuf(uint8_t * buf, uint16_t len) |
|
||||||
{ |
|
||||||
while(len-- > 0) |
|
||||||
writeChar(*buf++); |
|
||||||
} |
|
||||||
|
|
||||||
void EspLink::sendPacketStart(uint16_t cmd, uint32_t value, uint16_t argc) |
|
||||||
{ |
|
||||||
crc16_out = 0; |
|
||||||
stream.write( SLIP_END ); |
|
||||||
writeBuf((uint8_t*)&cmd, 2); |
|
||||||
writeBuf((uint8_t*)&argc, 2); |
|
||||||
writeBuf((uint8_t*)&value, 4); |
|
||||||
} |
|
||||||
|
|
||||||
void EspLink::sendPacketArg(uint16_t len, uint8_t * data) |
|
||||||
{ |
|
||||||
writeBuf((uint8_t*)&len, 2); |
|
||||||
writeBuf(data, len); |
|
||||||
|
|
||||||
uint16_t pad = ((len+3)&~3) - len; // get to multiple of 4
|
|
||||||
if (pad > 0) { |
|
||||||
uint32_t temp = 0; |
|
||||||
writeBuf((uint8_t*)&temp, pad); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void EspLink::sendPacketEnd() { |
|
||||||
uint16_t crc = crc16_out; |
|
||||||
writeBuf((uint8_t*)&crc, 2); |
|
||||||
stream.write(SLIP_END); |
|
||||||
} |
|
||||||
|
|
||||||
void EspLink::parseSlipPacket() |
|
||||||
{ |
|
||||||
CmdRequest req; |
|
||||||
req.cmd = (CmdPacket *)readBuf; |
|
||||||
req.arg_num = 0; |
|
||||||
req.arg_ptr = readBuf + sizeof(CmdPacket); |
|
||||||
|
|
||||||
requestCb(&req); |
|
||||||
|
|
||||||
free(readBuf); |
|
||||||
readBuf = NULL; |
|
||||||
} |
|
||||||
|
|
||||||
void EspLink::checkPacket() |
|
||||||
{ |
|
||||||
if( readBufPtr <= 3 ) |
|
||||||
return; |
|
||||||
uint16_t crc = 0; |
|
||||||
for(uint16_t i=0; i < readBufPtr - 2; i++) |
|
||||||
crc16_add(readBuf[i], &crc); |
|
||||||
|
|
||||||
uint16_t crcpacket = *(uint16_t*)(readBuf + readBufPtr - 2); |
|
||||||
|
|
||||||
if( crc == crcpacket ) |
|
||||||
{ |
|
||||||
readBufPtr -= 2; |
|
||||||
parseSlipPacket(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void EspLink::readLoop() |
|
||||||
{ |
|
||||||
if( stream.available() > 0 ) |
|
||||||
{ |
|
||||||
int byt = stream.read(); |
|
||||||
|
|
||||||
switch(readState) |
|
||||||
{ |
|
||||||
case WAIT_FOR_SLIP_START: |
|
||||||
if( byt == SLIP_END ) |
|
||||||
{ |
|
||||||
if(readBuf != NULL) |
|
||||||
free(readBuf); |
|
||||||
readBufPtr = 0; |
|
||||||
readBufMax = READ_BUF_DFLT_SIZE; |
|
||||||
readBuf = (uint8_t *)malloc(readBufMax); |
|
||||||
readState = READ_SLIP_PACKAGE; |
|
||||||
} |
|
||||||
break; |
|
||||||
case READ_SLIP_PACKAGE: |
|
||||||
if( byt == SLIP_END ) |
|
||||||
{ |
|
||||||
readState = WAIT_FOR_SLIP_START; |
|
||||||
checkPacket(); |
|
||||||
break; |
|
||||||
} |
|
||||||
if( byt == SLIP_ESC ) |
|
||||||
break; |
|
||||||
if( readLastChar == SLIP_ESC && byt == SLIP_ESC_END ) |
|
||||||
byt = SLIP_END; |
|
||||||
else if( readLastChar == SLIP_ESC && byt == SLIP_ESC_ESC ) |
|
||||||
byt = SLIP_ESC; |
|
||||||
|
|
||||||
if( readBufPtr >= readBufMax ) |
|
||||||
{ |
|
||||||
readBufMax = readBufMax + READ_BUF_DFLT_SIZE; |
|
||||||
readBuf = (uint8_t *)realloc(readBuf, readBufMax); |
|
||||||
if( readBuf == NULL ) |
|
||||||
{ |
|
||||||
readState = WAIT_FOR_SLIP_START; // TODO
|
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
readBuf[readBufPtr++] = byt; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
readLastChar = byt; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Return the number of arguments given a command struct
|
|
||||||
uint32_t EspLink::cmdGetArgc(CmdRequest *req) { |
|
||||||
return req->cmd->argc; |
|
||||||
} |
|
||||||
|
|
||||||
// Copy the next argument from a command structure into the data pointer, returns 0 on success
|
|
||||||
// -1 on error
|
|
||||||
int32_t EspLink::cmdPopArg(CmdRequest *req, void *data, uint16_t len) { |
|
||||||
uint16_t length; |
|
||||||
|
|
||||||
if (req->arg_num >= req->cmd->argc) |
|
||||||
return -1; |
|
||||||
|
|
||||||
length = *(uint16_t*)req->arg_ptr; |
|
||||||
if (length != len) return -1; // safety check
|
|
||||||
|
|
||||||
memcpy(data, req->arg_ptr + 2, length); |
|
||||||
req->arg_ptr += (length+5)&~3; // round up to multiple of 4
|
|
||||||
|
|
||||||
req->arg_num ++; |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
// Skip the next argument
|
|
||||||
void EspLink::cmdSkipArg(CmdRequest *req) { |
|
||||||
uint16_t length; |
|
||||||
|
|
||||||
if (req->arg_num >= req->cmd->argc) return; |
|
||||||
|
|
||||||
length = *(uint16_t*)req->arg_ptr; |
|
||||||
|
|
||||||
req->arg_ptr += (length+5)&~3; |
|
||||||
req->arg_num ++; |
|
||||||
} |
|
||||||
|
|
||||||
// Return the length of the next argument
|
|
||||||
uint16_t EspLink::cmdArgLen(CmdRequest *req) { |
|
||||||
return *(uint16_t*)req->arg_ptr; |
|
||||||
} |
|
||||||
|
|
@ -1,91 +0,0 @@ |
|||||||
#ifndef ESP_LINK_H |
|
||||||
#define ESP_LINK_H |
|
||||||
|
|
||||||
#include <inttypes.h> |
|
||||||
#include <Stream.h> |
|
||||||
|
|
||||||
typedef struct __attribute__((__packed__)) { |
|
||||||
uint16_t len; // length of data
|
|
||||||
uint8_t data[0]; // really data[len]
|
|
||||||
} CmdArg; |
|
||||||
|
|
||||||
typedef struct __attribute__((__packed__)) { |
|
||||||
uint16_t cmd; // command to perform, from CmdName enum
|
|
||||||
uint16_t argc; // number of arguments to command
|
|
||||||
uint32_t value; // callback pointer for response or first argument
|
|
||||||
CmdArg args[0]; // really args[argc]
|
|
||||||
} CmdPacket; |
|
||||||
|
|
||||||
typedef struct { |
|
||||||
CmdPacket *cmd; // command packet header
|
|
||||||
uint32_t arg_num; // number of args parsed
|
|
||||||
uint8_t *arg_ptr; // pointer to ??
|
|
||||||
} CmdRequest; |
|
||||||
|
|
||||||
typedef void (* CmdRequestCB)(CmdRequest *); |
|
||||||
|
|
||||||
typedef enum { |
|
||||||
CMD_NULL = 0, |
|
||||||
CMD_SYNC, // synchronize and clear
|
|
||||||
CMD_RESP_V, // response with a value
|
|
||||||
CMD_RESP_CB, // response with a callback
|
|
||||||
CMD_WIFI_STATUS, // get the current wifi status
|
|
||||||
CMD_CB_ADD, |
|
||||||
CMD_CB_EVENTS, |
|
||||||
CMD_GET_TIME, // get current time in seconds since the unix epoch
|
|
||||||
|
|
||||||
CMD_MQTT_SETUP = 10, // set-up callbacks
|
|
||||||
CMD_MQTT_PUBLISH, // publish a message
|
|
||||||
CMD_MQTT_SUBSCRIBE, // subscribe to a topic
|
|
||||||
CMD_MQTT_LWT, // set the last-will-topic and messge
|
|
||||||
|
|
||||||
CMD_REST_SETUP = 20, |
|
||||||
CMD_REST_REQUEST, |
|
||||||
CMD_REST_SETHEADER, |
|
||||||
|
|
||||||
CMD_WEB_DATA = 30, |
|
||||||
CMD_WEB_REQ_CB, |
|
||||||
} CmdName; |
|
||||||
|
|
||||||
typedef enum |
|
||||||
{ |
|
||||||
WAIT_FOR_SLIP_START, |
|
||||||
READ_SLIP_PACKAGE, |
|
||||||
} ReadState; |
|
||||||
|
|
||||||
class EspLink |
|
||||||
{ |
|
||||||
private: |
|
||||||
uint16_t crc16_out; |
|
||||||
Stream &stream; |
|
||||||
ReadState readState; |
|
||||||
uint8_t * readBuf; |
|
||||||
uint16_t readBufPtr; |
|
||||||
uint16_t readBufMax; |
|
||||||
int readLastChar; |
|
||||||
CmdRequestCB requestCb; |
|
||||||
|
|
||||||
void crc16_add(uint8_t b, uint16_t *crc); |
|
||||||
void writeChar(uint8_t chr); |
|
||||||
void writeBuf(uint8_t * buf, uint16_t len); |
|
||||||
void checkPacket(); |
|
||||||
void parseSlipPacket(); |
|
||||||
|
|
||||||
public: |
|
||||||
EspLink(Stream &stream, CmdRequestCB callback); |
|
||||||
~EspLink(); |
|
||||||
|
|
||||||
void sendPacketStart(uint16_t cmd, uint32_t value, uint16_t argc); |
|
||||||
void sendPacketArg(uint16_t len, uint8_t * data); |
|
||||||
void sendPacketEnd(); |
|
||||||
|
|
||||||
void readLoop(); |
|
||||||
|
|
||||||
uint32_t cmdGetArgc(CmdRequest *req); |
|
||||||
int32_t cmdPopArg(CmdRequest *req, void *data, uint16_t len); |
|
||||||
void cmdSkipArg(CmdRequest *req); |
|
||||||
uint16_t cmdArgLen(CmdRequest *req); |
|
||||||
}; |
|
||||||
|
|
||||||
#endif /* ESP_LINK_H */ |
|
||||||
|
|
@ -1,214 +0,0 @@ |
|||||||
#include "WebServer.h" |
|
||||||
#include "Arduino.h" |
|
||||||
|
|
||||||
#define RESUBSCRIBE_LIMIT 1000 |
|
||||||
|
|
||||||
WebServer * WebServer::instance = NULL; |
|
||||||
|
|
||||||
void webServerCallback(CmdRequest *req) |
|
||||||
{ |
|
||||||
WebServer::getInstance()->handleRequest(req); |
|
||||||
} |
|
||||||
|
|
||||||
WebServer::WebServer(Stream &streamIn, const WebMethod * PROGMEM methodsIn):espLink(streamIn, webServerCallback),methods(methodsIn),stream(streamIn),esplink_cb(NULL) |
|
||||||
{ |
|
||||||
instance = this; |
|
||||||
} |
|
||||||
|
|
||||||
void WebServer::init() |
|
||||||
{ |
|
||||||
registerCallback(); |
|
||||||
} |
|
||||||
|
|
||||||
void WebServer::loop() |
|
||||||
{ |
|
||||||
// resubscribe periodically
|
|
||||||
uint32_t elapsed = millis() - last_connect_ts; |
|
||||||
if( elapsed > RESUBSCRIBE_LIMIT ) |
|
||||||
registerCallback(); |
|
||||||
espLink.readLoop(); |
|
||||||
} |
|
||||||
|
|
||||||
void WebServer::registerCallback() |
|
||||||
{ |
|
||||||
espLink.sendPacketStart(CMD_CB_ADD, 100, 1); |
|
||||||
espLink.sendPacketArg(5, (uint8_t *)"webCb"); |
|
||||||
espLink.sendPacketEnd(); |
|
||||||
last_connect_ts = millis(); |
|
||||||
} |
|
||||||
|
|
||||||
void WebServer::invokeMethod(RequestReason reason, WebMethod * method, CmdRequest *req) |
|
||||||
{ |
|
||||||
switch(reason) |
|
||||||
{ |
|
||||||
case WS_BUTTON: |
|
||||||
{ |
|
||||||
uint16_t len = espLink.cmdArgLen(req); |
|
||||||
char bf[len+1]; |
|
||||||
bf[len] = 0; |
|
||||||
espLink.cmdPopArg(req, bf, len); |
|
||||||
|
|
||||||
method->callback(BUTTON_PRESS, bf, len); |
|
||||||
} |
|
||||||
break; |
|
||||||
case WS_SUBMIT: |
|
||||||
{ |
|
||||||
int arg_len = espLink.cmdGetArgc( req ); |
|
||||||
int cnt = 4; |
|
||||||
|
|
||||||
while( cnt < arg_len ) |
|
||||||
{ |
|
||||||
uint16_t len = espLink.cmdArgLen(req); |
|
||||||
char bf[len+1]; |
|
||||||
bf[len] = 0; |
|
||||||
espLink.cmdPopArg(req, bf, len); |
|
||||||
|
|
||||||
value_ptr = bf + 2 + strlen(bf+1); |
|
||||||
method->callback(SET_FIELD, bf+1, strlen(bf+1)); |
|
||||||
|
|
||||||
cnt++; |
|
||||||
} |
|
||||||
} |
|
||||||
return; |
|
||||||
case WS_LOAD: |
|
||||||
case WS_REFRESH: |
|
||||||
break; |
|
||||||
default: |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
espLink.sendPacketStart(CMD_WEB_DATA, 100, 255); |
|
||||||
espLink.sendPacketArg(4, remote_ip); |
|
||||||
espLink.sendPacketArg(2, (uint8_t *)&remote_port); |
|
||||||
|
|
||||||
method->callback( reason == WS_LOAD ? LOAD : REFRESH, NULL, 0); |
|
||||||
|
|
||||||
espLink.sendPacketArg(0, NULL); |
|
||||||
espLink.sendPacketEnd(); |
|
||||||
} |
|
||||||
|
|
||||||
void WebServer::handleRequest(CmdRequest *req) |
|
||||||
{ |
|
||||||
if( req->cmd->cmd != CMD_WEB_REQ_CB ) |
|
||||||
{ |
|
||||||
if( esplink_cb != NULL ) |
|
||||||
esplink_cb(req); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
uint16_t shrt; |
|
||||||
espLink.cmdPopArg(req, &shrt, 2); |
|
||||||
RequestReason reason = (RequestReason)shrt; |
|
||||||
|
|
||||||
espLink.cmdPopArg(req, &remote_ip, 4); |
|
||||||
espLink.cmdPopArg(req, &remote_port, 2); |
|
||||||
|
|
||||||
{ |
|
||||||
uint16_t len = espLink.cmdArgLen(req); |
|
||||||
char bf[len+1]; |
|
||||||
bf[len] = 0; |
|
||||||
espLink.cmdPopArg(req, bf, len); |
|
||||||
|
|
||||||
const WebMethod * meth = methods; |
|
||||||
do |
|
||||||
{ |
|
||||||
WebMethod m; |
|
||||||
memcpy_P(&m, meth, sizeof(WebMethod)); |
|
||||||
if( m.url == NULL || m.callback == NULL ) |
|
||||||
break; |
|
||||||
|
|
||||||
if( strcmp_P(bf, m.url) == 0 ) |
|
||||||
{ |
|
||||||
invokeMethod(reason, &m, req); |
|
||||||
return; |
|
||||||
} |
|
||||||
meth++; |
|
||||||
}while(1); |
|
||||||
} |
|
||||||
|
|
||||||
if( reason == WS_SUBMIT ) |
|
||||||
return; |
|
||||||
|
|
||||||
// empty response
|
|
||||||
espLink.sendPacketStart(CMD_WEB_DATA, 100, 2); |
|
||||||
espLink.sendPacketArg(4, remote_ip); |
|
||||||
espLink.sendPacketArg(2, (uint8_t *)&remote_port); |
|
||||||
espLink.sendPacketEnd(); |
|
||||||
} |
|
||||||
|
|
||||||
void WebServer::setArgString(const char * name, const char * value) |
|
||||||
{ |
|
||||||
uint8_t nlen = strlen(name); |
|
||||||
uint8_t vlen = strlen(value); |
|
||||||
char buf[nlen + vlen + 3]; |
|
||||||
buf[0] = WEB_STRING; |
|
||||||
strcpy(buf+1, name); |
|
||||||
strcpy(buf+2+nlen, value); |
|
||||||
espLink.sendPacketArg(nlen+vlen+2, (uint8_t *)buf); |
|
||||||
} |
|
||||||
|
|
||||||
void WebServer::setArgStringP(const char * name, const char * value) |
|
||||||
{ |
|
||||||
uint8_t nlen = strlen(name); |
|
||||||
uint8_t vlen = strlen_P(value); |
|
||||||
char buf[nlen + vlen + 3]; |
|
||||||
buf[0] = WEB_STRING; |
|
||||||
strcpy(buf+1, name); |
|
||||||
strcpy_P(buf+2+nlen, value); |
|
||||||
espLink.sendPacketArg(nlen+vlen+2, (uint8_t *)buf); |
|
||||||
} |
|
||||||
|
|
||||||
void WebServer::setArgBoolean(const char * name, uint8_t value) |
|
||||||
{ |
|
||||||
uint8_t nlen = strlen(name); |
|
||||||
char buf[nlen + 4]; |
|
||||||
buf[0] = WEB_BOOLEAN; |
|
||||||
strcpy(buf+1, name); |
|
||||||
buf[2 + nlen] = value; |
|
||||||
espLink.sendPacketArg(nlen+3, (uint8_t *)buf); |
|
||||||
} |
|
||||||
|
|
||||||
void WebServer::setArgJson(const char * name, const char * value) |
|
||||||
{ |
|
||||||
uint8_t nlen = strlen(name); |
|
||||||
uint8_t vlen = strlen(value); |
|
||||||
char buf[nlen + vlen + 3]; |
|
||||||
buf[0] = WEB_JSON; |
|
||||||
strcpy(buf+1, name); |
|
||||||
strcpy(buf+2+nlen, value); |
|
||||||
espLink.sendPacketArg(nlen+vlen+2, (uint8_t *)buf); |
|
||||||
} |
|
||||||
|
|
||||||
void WebServer::setArgInt(const char * name, int32_t value) |
|
||||||
{ |
|
||||||
uint8_t nlen = strlen(name); |
|
||||||
char buf[nlen + 7]; |
|
||||||
buf[0] = WEB_INTEGER; |
|
||||||
strcpy(buf+1, name); |
|
||||||
memcpy(buf+2+nlen, &value, 4); |
|
||||||
espLink.sendPacketArg(nlen+6, (uint8_t *)buf); |
|
||||||
} |
|
||||||
|
|
||||||
int32_t WebServer::getArgInt() |
|
||||||
{ |
|
||||||
return (int32_t)atol(value_ptr); |
|
||||||
} |
|
||||||
|
|
||||||
char * WebServer::getArgString() |
|
||||||
{ |
|
||||||
return value_ptr; |
|
||||||
} |
|
||||||
|
|
||||||
uint8_t WebServer::getArgBoolean() |
|
||||||
{ |
|
||||||
if( strcmp_P(value_ptr, PSTR("on")) == 0 ) |
|
||||||
return 1; |
|
||||||
if( strcmp_P(value_ptr, PSTR("true")) == 0 ) |
|
||||||
return 1; |
|
||||||
if( strcmp_P(value_ptr, PSTR("yes")) == 0 ) |
|
||||||
return 1; |
|
||||||
if( strcmp_P(value_ptr, PSTR("1")) == 0 ) |
|
||||||
return 1; |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
@ -1,91 +0,0 @@ |
|||||||
#ifndef WEB_SERVER_H |
|
||||||
#define WEB_SERVER_H |
|
||||||
|
|
||||||
#include "EspLink.h" |
|
||||||
|
|
||||||
typedef enum |
|
||||||
{ |
|
||||||
BUTTON_PRESS, |
|
||||||
SET_FIELD, |
|
||||||
REFRESH, |
|
||||||
LOAD, |
|
||||||
} WebServerCommand; |
|
||||||
|
|
||||||
typedef void (*WebServerCallback)(WebServerCommand command, char * data, int dataLen); |
|
||||||
|
|
||||||
typedef struct |
|
||||||
{ |
|
||||||
const char * PROGMEM url; |
|
||||||
WebServerCallback callback; |
|
||||||
} WebMethod; |
|
||||||
|
|
||||||
|
|
||||||
typedef enum { |
|
||||||
WS_LOAD=0, |
|
||||||
WS_REFRESH, |
|
||||||
WS_BUTTON, |
|
||||||
WS_SUBMIT, |
|
||||||
} RequestReason; |
|
||||||
|
|
||||||
typedef enum |
|
||||||
{ |
|
||||||
WEB_STRING=0, |
|
||||||
WEB_NULL, |
|
||||||
WEB_INTEGER, |
|
||||||
WEB_BOOLEAN, |
|
||||||
WEB_FLOAT, |
|
||||||
WEB_JSON |
|
||||||
} WebValueType; |
|
||||||
|
|
||||||
class WebServer |
|
||||||
{ |
|
||||||
friend void webServerCallback(CmdRequest *req); |
|
||||||
|
|
||||||
private: |
|
||||||
const WebMethod * PROGMEM methods; |
|
||||||
Stream &stream; |
|
||||||
static WebServer * instance; |
|
||||||
|
|
||||||
void invokeMethod(RequestReason reason, WebMethod * method, CmdRequest *req); |
|
||||||
void handleRequest(CmdRequest *req); |
|
||||||
|
|
||||||
uint8_t remote_ip[4]; |
|
||||||
uint16_t remote_port; |
|
||||||
|
|
||||||
char * value_ptr; |
|
||||||
|
|
||||||
uint32_t last_connect_ts; |
|
||||||
|
|
||||||
CmdRequestCB esplink_cb; |
|
||||||
|
|
||||||
protected: |
|
||||||
EspLink espLink; |
|
||||||
|
|
||||||
public: |
|
||||||
WebServer(Stream &stream, const WebMethod * PROGMEM methods); |
|
||||||
|
|
||||||
void init(); |
|
||||||
void loop(); |
|
||||||
|
|
||||||
void registerCallback(); |
|
||||||
|
|
||||||
void setEspLinkCallback(CmdRequestCB cb) { esplink_cb = cb; } |
|
||||||
|
|
||||||
static WebServer * getInstance() { return instance; } |
|
||||||
uint8_t * getRemoteIp() { return remote_ip; } |
|
||||||
uint16_t getRemotePort() { return remote_port; } |
|
||||||
|
|
||||||
void setArgInt(const char * name, int32_t value); |
|
||||||
void setArgJson(const char * name, const char * value); |
|
||||||
void setArgString(const char * name, const char * value); |
|
||||||
void setArgStringP(const char * name, const char * value); |
|
||||||
void setArgBoolean(const char * name, uint8_t value); |
|
||||||
|
|
||||||
int32_t getArgInt(); |
|
||||||
char * getArgString(); |
|
||||||
uint8_t getArgBoolean(); |
|
||||||
|
|
||||||
EspLink * getEspLink() { return &espLink; } |
|
||||||
}; |
|
||||||
|
|
||||||
#endif /* WEB_SERVER_H */ |
|
@ -1,35 +0,0 @@ |
|||||||
#include "EspLink.h" |
|
||||||
#include "WebServer.h" |
|
||||||
#include "Pages.h" |
|
||||||
|
|
||||||
const char ledURL[] PROGMEM = "/LED.html.json"; |
|
||||||
const char userURL[] PROGMEM = "/User.html.json"; |
|
||||||
const char voltageURL[] PROGMEM = "/Voltage.html.json"; |
|
||||||
|
|
||||||
const WebMethod PROGMEM methods[] = { |
|
||||||
{ ledURL, ledHtmlCallback }, |
|
||||||
{ userURL, userHtmlCallback }, |
|
||||||
{ voltageURL, voltageHtmlCallback }, |
|
||||||
{ NULL, NULL }, |
|
||||||
}; |
|
||||||
|
|
||||||
WebServer webServer(Serial, methods); |
|
||||||
|
|
||||||
void setup() |
|
||||||
{ |
|
||||||
Serial.begin(57600); |
|
||||||
webServer.init(); |
|
||||||
|
|
||||||
ledInit(); |
|
||||||
userInit(); |
|
||||||
voltageInit(); |
|
||||||
} |
|
||||||
|
|
||||||
void loop() |
|
||||||
{ |
|
||||||
webServer.loop(); |
|
||||||
|
|
||||||
ledLoop(); |
|
||||||
voltageLoop(); |
|
||||||
} |
|
||||||
|
|
@ -1,188 +0,0 @@ |
|||||||
#include "WebServer.h" |
|
||||||
|
|
||||||
#define LED_PIN 13 |
|
||||||
|
|
||||||
int8_t blinking = 0; |
|
||||||
int8_t frequency = 10; |
|
||||||
uint8_t pattern = 2; |
|
||||||
uint16_t elapse = 100; |
|
||||||
uint16_t elapse_delta = 200; |
|
||||||
uint32_t next_ts = 0; |
|
||||||
|
|
||||||
#define MAX_LOGS 5 |
|
||||||
uint32_t log_ts[MAX_LOGS]; |
|
||||||
uint8_t log_msg[MAX_LOGS]; |
|
||||||
uint8_t log_ptr = 0; |
|
||||||
|
|
||||||
void ledInit() |
|
||||||
{ |
|
||||||
pinMode(LED_PIN, OUTPUT); |
|
||||||
digitalWrite(LED_PIN, false); |
|
||||||
} |
|
||||||
|
|
||||||
void ledLoop() |
|
||||||
{
|
|
||||||
if( blinking ) |
|
||||||
{ |
|
||||||
if( next_ts <= millis() ) |
|
||||||
{ |
|
||||||
digitalWrite(LED_PIN, !digitalRead(LED_PIN)); |
|
||||||
next_ts += elapse; |
|
||||||
elapse = elapse_delta - elapse; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void ledAddLog(uint8_t msg) |
|
||||||
{ |
|
||||||
if( log_ptr >= MAX_LOGS ) |
|
||||||
log_ptr = MAX_LOGS - 1; |
|
||||||
|
|
||||||
for(int8_t i=log_ptr-1; i >= 0; i--) |
|
||||||
{ |
|
||||||
log_ts[i+1] = log_ts[i]; |
|
||||||
log_msg[i+1] = log_msg[i]; |
|
||||||
} |
|
||||||
log_msg[0] = msg; |
|
||||||
log_ts[0] = millis(); |
|
||||||
log_ptr++; |
|
||||||
} |
|
||||||
|
|
||||||
void ledHistoryToLog(char * buf) |
|
||||||
{ |
|
||||||
buf[0] = 0; |
|
||||||
strcat(buf, "["); |
|
||||||
for(uint8_t i=0; i < log_ptr; i++) |
|
||||||
{ |
|
||||||
if( i != 0 ) |
|
||||||
strcat(buf, ","); |
|
||||||
|
|
||||||
char bf[20]; |
|
||||||
sprintf(bf, "\"%lds: ", log_ts[i] / 1000); |
|
||||||
strcat(buf, bf); |
|
||||||
|
|
||||||
uint8_t msg = log_msg[i]; |
|
||||||
if( msg == 0xE1 ) |
|
||||||
{ |
|
||||||
strcat_P(buf, PSTR("set pattern to 25%-75%")); |
|
||||||
} |
|
||||||
else if( msg == 0xE2 ) |
|
||||||
{ |
|
||||||
strcat_P(buf, PSTR("set pattern to 50%-50%")); |
|
||||||
} |
|
||||||
else if( msg == 0xE3 ) |
|
||||||
{ |
|
||||||
strcat_P(buf, PSTR("set pattern to 75%-25%")); |
|
||||||
} |
|
||||||
else if( msg == 0xF0 ) |
|
||||||
{ |
|
||||||
strcat_P(buf, PSTR("set led on")); |
|
||||||
} |
|
||||||
else if( msg == 0xF1 ) |
|
||||||
{ |
|
||||||
strcat_P(buf, PSTR("set led blinking")); |
|
||||||
} |
|
||||||
else if( msg == 0xF2 ) |
|
||||||
{ |
|
||||||
strcat_P(buf, PSTR("set led off")); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
strcat_P(buf, PSTR("set frequency to ")); |
|
||||||
sprintf(bf, "%d Hz", msg); |
|
||||||
strcat(buf, bf); |
|
||||||
} |
|
||||||
strcat(buf, "\""); |
|
||||||
} |
|
||||||
strcat(buf, "]"); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void ledHtmlCallback(WebServerCommand command, char * data, int dataLen) |
|
||||||
{ |
|
||||||
switch(command) |
|
||||||
{ |
|
||||||
case BUTTON_PRESS: |
|
||||||
if( strcmp_P(data, PSTR("btn_on") ) == 0 ) |
|
||||||
{ |
|
||||||
if( blinking || digitalRead(LED_PIN) == false ) |
|
||||||
ledAddLog(0xF0); |
|
||||||
blinking = 0; |
|
||||||
digitalWrite(LED_PIN, true); |
|
||||||
} else if( strcmp_P(data, PSTR("btn_off") ) == 0 ) |
|
||||||
{ |
|
||||||
if( blinking || digitalRead(LED_PIN) == true ) |
|
||||||
ledAddLog(0xF2); |
|
||||||
blinking = 0; |
|
||||||
digitalWrite(LED_PIN, false); |
|
||||||
} else if( strcmp_P(data, PSTR("btn_blink") ) == 0 ) |
|
||||||
{ |
|
||||||
if( !blinking ) |
|
||||||
ledAddLog(0xF1); |
|
||||||
blinking = 1; |
|
||||||
next_ts = millis() + elapse; |
|
||||||
} |
|
||||||
break; |
|
||||||
case SET_FIELD: |
|
||||||
if( strcmp_P(data, PSTR("frequency") ) == 0 ) |
|
||||||
{ |
|
||||||
int8_t oldf = frequency; |
|
||||||
frequency = webServer.getArgInt(); |
|
||||||
digitalWrite(LED_PIN, false); |
|
||||||
elapse_delta = 2000 / frequency; |
|
||||||
elapse = pattern * elapse_delta / 4; |
|
||||||
if( oldf != frequency ) |
|
||||||
ledAddLog(frequency); |
|
||||||
} |
|
||||||
else if( strcmp_P(data, PSTR("pattern") ) == 0 ) |
|
||||||
{ |
|
||||||
int8_t oldp = pattern; |
|
||||||
char * arg = webServer.getArgString(); |
|
||||||
|
|
||||||
if( strcmp_P(arg, PSTR("25_75")) == 0 ) |
|
||||||
pattern = 1; |
|
||||||
else if( strcmp_P(arg, PSTR("50_50")) == 0 ) |
|
||||||
pattern = 2; |
|
||||||
else if( strcmp_P(arg, PSTR("75_25")) == 0 ) |
|
||||||
pattern = 3; |
|
||||||
|
|
||||||
digitalWrite(LED_PIN, false); |
|
||||||
elapse = pattern * elapse_delta / 4; |
|
||||||
|
|
||||||
if( oldp != pattern ) |
|
||||||
ledAddLog(0xE0 + pattern); |
|
||||||
} |
|
||||||
break; |
|
||||||
case LOAD: |
|
||||||
webServer.setArgInt("frequency", frequency); |
|
||||||
|
|
||||||
switch(pattern) |
|
||||||
{ |
|
||||||
case 1: |
|
||||||
webServer.setArgStringP("pattern", PSTR("25_75")); |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
webServer.setArgStringP("pattern", PSTR("50_50")); |
|
||||||
break; |
|
||||||
case 3: |
|
||||||
webServer.setArgStringP("pattern", PSTR("75_25")); |
|
||||||
break; |
|
||||||
} |
|
||||||
case REFRESH: |
|
||||||
{ |
|
||||||
if( blinking ) |
|
||||||
webServer.setArgStringP("text", PSTR("LED is blinking")); |
|
||||||
else |
|
||||||
webServer.setArgStringP("text", digitalRead(LED_PIN) ? PSTR("LED is turned on") : PSTR("LED is turned off")); |
|
||||||
|
|
||||||
char buf[255]; |
|
||||||
ledHistoryToLog(buf); |
|
||||||
webServer.setArgJson("led_history", buf); |
|
||||||
} |
|
||||||
break; |
|
||||||
default: |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
@ -1,8 +0,0 @@ |
|||||||
all: user_img |
|
||||||
|
|
||||||
clean: |
|
||||||
rm -rf web-page.espfs.img
|
|
||||||
|
|
||||||
user_img: |
|
||||||
../../../../../createEspFs.pl web-page web-page.espfs.img
|
|
||||||
|
|
@ -1,17 +0,0 @@ |
|||||||
#ifndef PAGES_H |
|
||||||
#define PAGES_H |
|
||||||
|
|
||||||
void ledHtmlCallback(WebServerCommand command, char * data, int dataLen); |
|
||||||
void ledLoop(); |
|
||||||
void ledInit(); |
|
||||||
|
|
||||||
void userHtmlCallback(WebServerCommand command, char * data, int dataLen); |
|
||||||
void userInit(); |
|
||||||
|
|
||||||
void voltageHtmlCallback(WebServerCommand command, char * data, int dataLen); |
|
||||||
void voltageLoop(); |
|
||||||
void voltageInit(); |
|
||||||
|
|
||||||
#endif /* PAGES_H */ |
|
||||||
|
|
||||||
|
|
@ -1,84 +0,0 @@ |
|||||||
#include <EEPROM.h> |
|
||||||
#include "WebServer.h" |
|
||||||
|
|
||||||
#define MAGIC 0xABEF |
|
||||||
|
|
||||||
#define MAX_STR_LEN 32 |
|
||||||
|
|
||||||
#define POS_MAGIC 0 |
|
||||||
#define POS_FIRST_NAME (POS_MAGIC + 2) |
|
||||||
#define POS_LAST_NAME (POS_FIRST_NAME + MAX_STR_LEN) |
|
||||||
#define POS_AGE (POS_LAST_NAME + MAX_STR_LEN) |
|
||||||
#define POS_GENDER (POS_AGE+1) |
|
||||||
#define POS_NOTIFICATIONS (POS_GENDER+1) |
|
||||||
|
|
||||||
void userInit() |
|
||||||
{ |
|
||||||
uint16_t magic; |
|
||||||
EEPROM.get(POS_MAGIC, magic); |
|
||||||
|
|
||||||
if( magic != MAGIC ) |
|
||||||
{ |
|
||||||
magic = MAGIC; |
|
||||||
EEPROM.put(POS_MAGIC, magic); |
|
||||||
EEPROM.update(POS_FIRST_NAME, 0); |
|
||||||
EEPROM.update(POS_LAST_NAME, 0); |
|
||||||
EEPROM.update(POS_AGE, 0); |
|
||||||
EEPROM.update(POS_GENDER, 'f'); |
|
||||||
EEPROM.update(POS_NOTIFICATIONS, 0); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void userWriteStr(char * str, int ndx) |
|
||||||
{ |
|
||||||
for(uint8_t i=0; i < MAX_STR_LEN-1; i++) |
|
||||||
{ |
|
||||||
EEPROM.update(ndx + i, str[i]); |
|
||||||
if( str[i] == 0 ) |
|
||||||
break; |
|
||||||
} |
|
||||||
EEPROM.update(ndx + MAX_STR_LEN - 1, 0); |
|
||||||
} |
|
||||||
|
|
||||||
void userReadStr(char * str, int ndx) |
|
||||||
{ |
|
||||||
for(uint8_t i=0; i < MAX_STR_LEN; i++) |
|
||||||
{ |
|
||||||
str[i] = EEPROM[ndx + i]; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void userHtmlCallback(WebServerCommand command, char * data, int dataLen) |
|
||||||
{ |
|
||||||
switch(command) |
|
||||||
{ |
|
||||||
case SET_FIELD: |
|
||||||
if( strcmp_P(data, PSTR("first_name")) == 0 ) |
|
||||||
userWriteStr(webServer.getArgString(), POS_FIRST_NAME); |
|
||||||
if( strcmp_P(data, PSTR("last_name")) == 0 ) |
|
||||||
userWriteStr(webServer.getArgString(), POS_LAST_NAME); |
|
||||||
if( strcmp_P(data, PSTR("age")) == 0 ) |
|
||||||
EEPROM.update(POS_AGE, (uint8_t)webServer.getArgInt()); |
|
||||||
if( strcmp_P(data, PSTR("gender")) == 0 ) |
|
||||||
EEPROM.update(POS_GENDER, (strcmp_P(webServer.getArgString(), PSTR("male")) == 0 ? 'm' : 'f')); |
|
||||||
if( strcmp_P(data, PSTR("notifications")) == 0 ) |
|
||||||
EEPROM.update(POS_NOTIFICATIONS, (uint8_t)webServer.getArgBoolean()); |
|
||||||
break; |
|
||||||
case LOAD: |
|
||||||
{ |
|
||||||
char buf[MAX_STR_LEN]; |
|
||||||
userReadStr( buf, POS_FIRST_NAME ); |
|
||||||
webServer.setArgString("first_name", buf); |
|
||||||
userReadStr( buf, POS_LAST_NAME ); |
|
||||||
webServer.setArgString("last_name", buf); |
|
||||||
webServer.setArgInt("age", (uint8_t)EEPROM[POS_AGE]); |
|
||||||
webServer.setArgStringP("gender", (EEPROM[POS_GENDER] == 'm') ? PSTR("male") : PSTR("female")); |
|
||||||
webServer.setArgBoolean("notifications", EEPROM[POS_NOTIFICATIONS] != 0); |
|
||||||
} |
|
||||||
break; |
|
||||||
case REFRESH: |
|
||||||
// do nothing
|
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
@ -1,125 +0,0 @@ |
|||||||
#include "WebServer.h" |
|
||||||
|
|
||||||
#include <avr/io.h> |
|
||||||
|
|
||||||
#define SAMPLE_COUNT 100 |
|
||||||
#define PERIOD_COUNT (135 * SAMPLE_COUNT) |
|
||||||
|
|
||||||
uint16_t smin = 0xFFFF; |
|
||||||
uint16_t smax = 0; |
|
||||||
uint32_t savg = 0; |
|
||||||
|
|
||||||
uint16_t count; |
|
||||||
uint32_t voltage = 0; |
|
||||||
uint16_t measured_voltage = 0; |
|
||||||
|
|
||||||
#define MAX_HISTORY 3 |
|
||||||
|
|
||||||
uint8_t history_cnt = 0; |
|
||||||
uint32_t h_ts[MAX_HISTORY]; |
|
||||||
uint16_t h_min[MAX_HISTORY]; |
|
||||||
uint16_t h_max[MAX_HISTORY]; |
|
||||||
uint16_t h_avg[MAX_HISTORY]; |
|
||||||
|
|
||||||
uint16_t calibrate = 0x128; // calibrate this manually
|
|
||||||
|
|
||||||
void voltageInit() |
|
||||||
{ |
|
||||||
analogReference(DEFAULT); |
|
||||||
|
|
||||||
count = 0; |
|
||||||
} |
|
||||||
|
|
||||||
void voltageLoop() |
|
||||||
{ |
|
||||||
uint16_t adc = analogRead(A0);
|
|
||||||
|
|
||||||
if( adc < smin ) |
|
||||||
smin = adc; |
|
||||||
if( adc > smax ) |
|
||||||
smax = adc; |
|
||||||
savg += adc; |
|
||||||
|
|
||||||
voltage += adc; |
|
||||||
count++; |
|
||||||
|
|
||||||
if( (count % SAMPLE_COUNT) == 0 ) |
|
||||||
{ |
|
||||||
voltage /= SAMPLE_COUNT; |
|
||||||
measured_voltage = voltage * calibrate / 256; |
|
||||||
voltage = 0; |
|
||||||
} |
|
||||||
if( count == PERIOD_COUNT ) |
|
||||||
{ |
|
||||||
for(int8_t i=MAX_HISTORY-2; i >=0; i-- ) |
|
||||||
{ |
|
||||||
h_ts[i+1] = h_ts[i]; |
|
||||||
h_min[i+1] = h_min[i]; |
|
||||||
h_max[i+1] = h_max[i]; |
|
||||||
h_avg[i+1] = h_avg[i]; |
|
||||||
} |
|
||||||
|
|
||||||
h_ts[0] = millis(); |
|
||||||
h_min[0] = (uint32_t)smin * calibrate / 256; |
|
||||||
h_max[0] = (uint32_t)smax * calibrate / 256; |
|
||||||
h_avg[0] = (savg / PERIOD_COUNT) * calibrate / 256; |
|
||||||
|
|
||||||
smin = 0xFFFF; |
|
||||||
smax = 0; |
|
||||||
savg = 0; |
|
||||||
|
|
||||||
if( history_cnt < MAX_HISTORY ) |
|
||||||
history_cnt++; |
|
||||||
count = 0; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void voltageHtmlCallback(WebServerCommand command, char * data, int dataLen) |
|
||||||
{ |
|
||||||
switch(command) |
|
||||||
{ |
|
||||||
case BUTTON_PRESS: |
|
||||||
// no buttons
|
|
||||||
break;
|
|
||||||
case SET_FIELD: |
|
||||||
/* TODO */ |
|
||||||
break; |
|
||||||
case LOAD: |
|
||||||
case REFRESH: |
|
||||||
{ |
|
||||||
char buf[20]; |
|
||||||
uint8_t int_part = measured_voltage / 256; |
|
||||||
uint8_t float_part = ((measured_voltage & 255) * 100) / 256; |
|
||||||
sprintf(buf, "%d.%02d V", int_part, float_part); |
|
||||||
webServer.setArgString("voltage", buf); |
|
||||||
|
|
||||||
char tab[256]; |
|
||||||
tab[0] = 0; |
|
||||||
strcat_P(tab, PSTR("[[\"Time\",\"Min\",\"AVG\",\"Max\"]")); |
|
||||||
|
|
||||||
for(uint8_t i=0; i < history_cnt; i++ ) |
|
||||||
{ |
|
||||||
uint8_t min_i = h_min[i] / 256; |
|
||||||
uint8_t min_f = ((h_min[i] & 255) * 100) / 256; |
|
||||||
uint8_t max_i = h_max[i] / 256; |
|
||||||
uint8_t max_f = ((h_max[i] & 255) * 100) / 256; |
|
||||||
uint8_t avg_i = h_avg[i] / 256; |
|
||||||
uint8_t avg_f = ((h_avg[i] & 255) * 100) / 256; |
|
||||||
|
|
||||||
sprintf(buf, ",[\"%d s\",", h_ts[i] / 1000); |
|
||||||
strcat(tab, buf); |
|
||||||
sprintf(buf, "\"%d.%02d V\",", min_i, min_f); |
|
||||||
strcat(tab, buf); |
|
||||||
sprintf(buf, "\"%d.%02d V\",", avg_i, avg_f); |
|
||||||
strcat(tab, buf); |
|
||||||
sprintf(buf, "\"%d.%02d V\"]", max_i, max_f); |
|
||||||
strcat(tab, buf); |
|
||||||
} |
|
||||||
|
|
||||||
strcat_P(tab, PSTR("]")); |
|
||||||
webServer.setArgJson("table", tab); |
|
||||||
} |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
Binary file not shown.
@ -1,36 +0,0 @@ |
|||||||
<!-- EspLink will add header here --> |
|
||||||
|
|
||||||
<div class="header"> |
|
||||||
<h1>LED configuration</h1> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="content"> |
|
||||||
<div class="pure-g"><div class="pure-u-1 pure-u-md-1-2"> |
|
||||||
<div class="card"> |
|
||||||
<h1>Control</h1> |
|
||||||
<button id="btn_on" type="button">Turn on</button> |
|
||||||
<button id="btn_blink" type="button">Start blinking</button> |
|
||||||
<button id="btn_off" type="button">Turn off</button> |
|
||||||
<p id="text"/> |
|
||||||
</div> |
|
||||||
<div class="card"> |
|
||||||
<h1>Frequency and pattern</h1> |
|
||||||
<form> |
|
||||||
<b>Pattern:</b><br/> |
|
||||||
<input type="radio" name="pattern" value="25_75">25% on 75% off</input><br/> |
|
||||||
<input type="radio" name="pattern" value="50_50">50% on 50% off</input><br/> |
|
||||||
<input type="radio" name="pattern" value="75_25">75% on 25% off</input><br/> |
|
||||||
|
|
||||||
<b>Frequency:</b><br/> |
|
||||||
<input type="range" name="frequency" min="1" max="25"><br/> |
|
||||||
<input type="submit"> |
|
||||||
</form> |
|
||||||
</div></div> |
|
||||||
<div class="pure-u-1 pure-u-md-1-2"> |
|
||||||
<div class="card" style="min-height: 400px"> |
|
||||||
<h1>Logs</h1> |
|
||||||
<ul id="led_history"/> |
|
||||||
</div> |
|
||||||
</div></div> |
|
||||||
</div> |
|
||||||
</body></html> |
|
@ -1,24 +0,0 @@ |
|||||||
<!-- EspLink will add header here --> |
|
||||||
|
|
||||||
<div class="header"> |
|
||||||
<h1>User setup</h1> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="content"> |
|
||||||
<form> |
|
||||||
First name:<br/><input name="first_name" type="text"/> |
|
||||||
Last name:<br/><input name="last_name" type="text"/> |
|
||||||
Age: |
|
||||||
<input name="age" type="number"/> |
|
||||||
Gender: |
|
||||||
<select name="gender"> |
|
||||||
<option value="female">Female</option> |
|
||||||
<option value="male">Male</option> |
|
||||||
</select> |
|
||||||
<br> |
|
||||||
Notifications<input name="notifications" type="checkbox"/> |
|
||||||
<br> |
|
||||||
<input type="submit"> |
|
||||||
</form> |
|
||||||
</div> |
|
||||||
</body></html> |
|
@ -1,15 +0,0 @@ |
|||||||
<!-- EspLink will add header here --> |
|
||||||
|
|
||||||
<meta name="refresh-rate" content="500" /> |
|
||||||
|
|
||||||
<div class="header"> |
|
||||||
<h1>Voltage measurement</h1> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="content"> |
|
||||||
<p id="voltage" align="center" style="font-size: 800%"/> |
|
||||||
|
|
||||||
<table class="pure-table pure-table-bordered" align="center" id="table"/> |
|
||||||
</div> |
|
||||||
|
|
||||||
</body></html> |
|
@ -1,49 +0,0 @@ |
|||||||
#include "EspLink.h" |
|
||||||
#include "WebServer.h" |
|
||||||
|
|
||||||
#define LED_PIN 13 |
|
||||||
|
|
||||||
void simpleLedHtmlCallback(WebServerCommand command, char * data, int dataLen); |
|
||||||
const char simpleLedURL[] PROGMEM = "/SimpleLED.html.json"; |
|
||||||
|
|
||||||
const WebMethod PROGMEM methods[] = { |
|
||||||
{ simpleLedURL, simpleLedHtmlCallback }, |
|
||||||
{ NULL, NULL }, |
|
||||||
}; |
|
||||||
|
|
||||||
WebServer webServer(Serial, methods); |
|
||||||
|
|
||||||
void simpleLedHtmlCallback(WebServerCommand command, char * data, int dataLen) |
|
||||||
{ |
|
||||||
switch(command) |
|
||||||
{ |
|
||||||
case BUTTON_PRESS: |
|
||||||
if( strcmp_P(data, PSTR("btn_on") ) == 0 ) |
|
||||||
digitalWrite(LED_PIN, true); |
|
||||||
else if( strcmp_P(data, PSTR("btn_off") ) == 0 ) |
|
||||||
digitalWrite(LED_PIN, false); |
|
||||||
break; |
|
||||||
case SET_FIELD: |
|
||||||
// no fields to set
|
|
||||||
break; |
|
||||||
case LOAD: |
|
||||||
case REFRESH: |
|
||||||
if( digitalRead(LED_PIN) ) |
|
||||||
webServer.setArgString("text", "LED is on"); |
|
||||||
else |
|
||||||
webServer.setArgString("text", "LED is off"); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void setup() |
|
||||||
{ |
|
||||||
Serial.begin(57600); |
|
||||||
webServer.init(); |
|
||||||
} |
|
||||||
|
|
||||||
void loop() |
|
||||||
{ |
|
||||||
webServer.loop(); |
|
||||||
} |
|
||||||
|
|
@ -1,7 +0,0 @@ |
|||||||
<!-- EspLink will add header here --> |
|
||||||
|
|
||||||
<h1 class="header">Simple LED control</h1> |
|
||||||
<h2><div id="text"/></h2> |
|
||||||
<button id="btn_on" type="button">Turn on</button> |
|
||||||
<button id="btn_off" type="button">Turn off</button> |
|
||||||
</body></html> |
|
@ -1 +0,0 @@ |
|||||||
For information on installing libraries, see: http://www.arduino.cc/en/Guide/Libraries |
|
Loading…
Reference in new issue