Compare commits
7 Commits
2d73921bc7
...
78231e9228
Author | SHA1 | Date | |
---|---|---|---|
|
78231e9228 | ||
|
57a5f05e29 | ||
|
5116ea41eb | ||
|
2b32fd68ea | ||
|
af25f55089 | ||
|
d0349ea26e | ||
|
ea60399ea3 |
@ -13,13 +13,20 @@ var powerInfoInter = null;
|
|||||||
|
|
||||||
var execTimeStart = null;
|
var execTimeStart = null;
|
||||||
|
|
||||||
|
//XMLHttpRequest objects
|
||||||
|
let ajaxReqPowerInfo = new XMLHttpRequest();
|
||||||
|
let ajaxReqGetIoMode = new XMLHttpRequest();
|
||||||
|
|
||||||
|
let ajaxReqRtc = new XMLHttpRequest();
|
||||||
|
|
||||||
//This function set the app up
|
//This function set the app up
|
||||||
function init()
|
function init()
|
||||||
{
|
{
|
||||||
console.log("Body loaded - starting setup");
|
console.log("Body loaded - starting setup");
|
||||||
|
|
||||||
refreshRtc();
|
initAjaxRtc();
|
||||||
rtcClockInter = setInterval(refreshRtc,1000);
|
refreshRtc(ajaxReqRtc);
|
||||||
|
rtcClockInter = setInterval(() => {refreshRtc(ajaxReqRtc)},1000);
|
||||||
|
|
||||||
refreshSysInfo();
|
refreshSysInfo();
|
||||||
sysinfoInter = setInterval(refreshSysInfo,10000);
|
sysinfoInter = setInterval(refreshSysInfo,10000);
|
||||||
@ -28,13 +35,13 @@ function init()
|
|||||||
sigStrenthInter = setInterval(refreshSigStrength,1000);
|
sigStrenthInter = setInterval(refreshSigStrength,1000);
|
||||||
|
|
||||||
sdCardSize();
|
sdCardSize();
|
||||||
getIoMode();
|
getIoMode(ajaxReqGetIoMode);
|
||||||
getIoLevel();
|
getIoLevel();
|
||||||
|
|
||||||
ioModeLevelInter = setInterval(() => {getIoMode();getIoLevel();},1000);
|
ioModeLevelInter = setInterval(() => {getIoMode(ajaxReqGetIoMode);getIoLevel();},1000);
|
||||||
|
|
||||||
powerInfo();
|
powerInfo(ajaxReqPowerInfo);
|
||||||
powerInfoInter = setInterval(powerInfo,10000);
|
powerInfoInter = setInterval(() => {powerInfo(ajaxReqPowerInfo);},10000);
|
||||||
|
|
||||||
//We init the time boxes
|
//We init the time boxes
|
||||||
var curDate = new Date();
|
var curDate = new Date();
|
||||||
@ -47,6 +54,49 @@ function init()
|
|||||||
console.log("Ending setup");
|
console.log("Ending setup");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initAjaxRtc()
|
||||||
|
{
|
||||||
|
ajaxReqRtc.timeout = 5000;
|
||||||
|
ajaxReqRtc.onreadystatechange = function()
|
||||||
|
{
|
||||||
|
switch(this.readyState)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
console.log("Connection established");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
console.log("Request received");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
console.log("Processing request");
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
console.log("Response is ready");
|
||||||
|
if(this.status != 0){onConnected(); document.getElementById('execTime').innerHTML = new Date().getTime() - execTimeStart;}
|
||||||
|
if(this.status == 200)
|
||||||
|
{
|
||||||
|
console.log("Response : " + this.responseText);
|
||||||
|
var rtcObj = JSON.parse(this.responseText);
|
||||||
|
console.log(rtcObj);
|
||||||
|
document.getElementById('rtcValue').innerHTML = rtcObj.time + ' ' + rtcObj.date;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.log("Error, status is : " + this.status);
|
||||||
|
document.getElementById('rtcValue').innerHTML = 'ERROR';
|
||||||
|
document.getElementById('execTime').innerHTML = 'NaN';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log("Unknown state");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ajaxReqRtc.ontimeout = onTimeOut;
|
||||||
|
}
|
||||||
|
|
||||||
function onTimeOut(e)
|
function onTimeOut(e)
|
||||||
{
|
{
|
||||||
console.error("Request timed out");
|
console.error("Request timed out");
|
||||||
@ -61,21 +111,20 @@ function onConnected()
|
|||||||
console.log("Connected to Swiss Army Board");
|
console.log("Connected to Swiss Army Board");
|
||||||
document.getElementById('imgDisco').style.display = 'none';
|
document.getElementById('imgDisco').style.display = 'none';
|
||||||
document.getElementById('imgConn').style.display = 'block';
|
document.getElementById('imgConn').style.display = 'block';
|
||||||
refreshRtc();
|
refreshRtc(ajaxReqRtc);
|
||||||
refreshSysInfo();
|
refreshSysInfo();
|
||||||
refreshSigStrength();
|
refreshSigStrength();
|
||||||
sdCardSize();
|
sdCardSize();
|
||||||
getIoMode();
|
getIoMode(ajaxReqGetIoMode);
|
||||||
getIoLevel();
|
getIoLevel();
|
||||||
powerInfo();
|
powerInfo(ajaxReqPowerInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function powerInfo()
|
function powerInfo(ajaxReq)
|
||||||
{
|
{
|
||||||
console.log("Getting board power info");
|
console.log("Getting board power info");
|
||||||
|
|
||||||
var ajaxReq = new XMLHttpRequest();
|
|
||||||
ajaxReq.timeout = 5000;
|
ajaxReq.timeout = 5000;
|
||||||
ajaxReq.onreadystatechange = function()
|
ajaxReq.onreadystatechange = function()
|
||||||
{
|
{
|
||||||
@ -117,50 +166,11 @@ function powerInfo()
|
|||||||
ajaxReq.send();
|
ajaxReq.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshRtc()
|
function refreshRtc(ajaxReq)
|
||||||
{
|
{
|
||||||
console.log("Refreshing RTC");
|
console.log("Refreshing RTC");
|
||||||
var ajaxReq = new XMLHttpRequest();
|
|
||||||
ajaxReq.timeout = 5000;
|
ajaxReqRtc.open('GET',"/sab/rtc/get/datetime");
|
||||||
ajaxReq.onreadystatechange = function()
|
|
||||||
{
|
|
||||||
switch(this.readyState)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
console.log("Connection established");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
console.log("Request received");
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
console.log("Processing request");
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
console.log("Response is ready");
|
|
||||||
if(this.status != 0){onConnected(); document.getElementById('execTime').innerHTML = new Date().getTime() - execTimeStart;}
|
|
||||||
if(this.status == 200)
|
|
||||||
{
|
|
||||||
console.log("Response : " + this.responseText);
|
|
||||||
var rtcObj = JSON.parse(this.responseText);
|
|
||||||
console.log(rtcObj);
|
|
||||||
document.getElementById('rtcValue').innerHTML = rtcObj.time + ' ' + rtcObj.date;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
console.log("Error, status is : " + this.status);
|
|
||||||
document.getElementById('rtcValue').innerHTML = 'ERROR';
|
|
||||||
document.getElementById('execTime').innerHTML = 'NaN';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log("Unknown state");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ajaxReq.ontimeout = onTimeOut;
|
|
||||||
ajaxReq.open('GET',"/sab/rtc/get/datetime");
|
|
||||||
execTimeStart = new Date().getTime();
|
execTimeStart = new Date().getTime();
|
||||||
ajaxReq.send();
|
ajaxReq.send();
|
||||||
}
|
}
|
||||||
@ -405,11 +415,9 @@ function sdCardSize()
|
|||||||
ajaxReq.send();
|
ajaxReq.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getIoMode()
|
function getIoMode(ajaxReq)
|
||||||
{
|
{
|
||||||
console.log("Getting IO mode for all IO's");
|
console.log("Getting IO mode for all IO's");
|
||||||
|
|
||||||
var ajaxReq = new XMLHttpRequest();
|
|
||||||
ajaxReq.timeout = 5000;
|
ajaxReq.timeout = 5000;
|
||||||
ajaxReq.onreadystatechange = function()
|
ajaxReq.onreadystatechange = function()
|
||||||
{
|
{
|
||||||
|
335
src/app/HttpClient.cpp
Normal file
335
src/app/HttpClient.cpp
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
#include "HttpClient.h"
|
||||||
|
#include <IPAddress.h>
|
||||||
|
|
||||||
|
#define DEBUG_HTTP_CLIENT
|
||||||
|
|
||||||
|
/*
|
||||||
|
* End of HttpClientHelper
|
||||||
|
*/
|
||||||
|
|
||||||
|
HttpClient::HttpClient() : WiFiClient(), _connectionStatus(NO_ATTEMPT), _resource(NULL), _address(NULL), _port(0), _keepAlive(false), _maxRetries(5), _retries(0), _httpCode(HTTP_CODE::UNDEFINED_CODE), _bodyReadyToRead(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpClient::HttpClient(const char *address, uint16_t port) : HttpClient()
|
||||||
|
{
|
||||||
|
|
||||||
|
if(address != NULL)
|
||||||
|
{
|
||||||
|
_address = (char *)malloc(strlen(address) * sizeof(char) + 1);
|
||||||
|
strcpy(_address, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
_port = port;
|
||||||
|
|
||||||
|
connectByHostOrIp();
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpClient::HttpClient(const char *address, const char *resource, uint16_t port) : HttpClient(address, port)
|
||||||
|
{
|
||||||
|
if(resource != NULL)
|
||||||
|
{
|
||||||
|
_resource = (char *)malloc(strlen(resource) * sizeof(char) + 1);
|
||||||
|
strcpy(_resource, resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpClient::HttpClient(const HttpClient &object)
|
||||||
|
{
|
||||||
|
if(object._resource != NULL)
|
||||||
|
{
|
||||||
|
_resource = (char *)malloc(strlen(object._resource) * sizeof(char) + 1);
|
||||||
|
strcpy(_resource, object._resource);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_resource = NULL;
|
||||||
|
|
||||||
|
if(object._address != NULL)
|
||||||
|
{
|
||||||
|
_address = (char *)malloc(strlen(object._address) * sizeof(char) + 1);
|
||||||
|
strcpy(_address, object._address);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_address = NULL;
|
||||||
|
|
||||||
|
_connectionStatus = object._connectionStatus;
|
||||||
|
_keepAlive = object._keepAlive;
|
||||||
|
_maxRetries = object._maxRetries;
|
||||||
|
_retries = object._retries;
|
||||||
|
_port = object._port;
|
||||||
|
_httpCode = object._httpCode;
|
||||||
|
_bodyReadyToRead = object._bodyReadyToRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpClient::~HttpClient()
|
||||||
|
{
|
||||||
|
if(_resource != NULL)free(_resource);
|
||||||
|
if(_address != NULL)free(_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean HttpClient::connectByHostOrIp()
|
||||||
|
{
|
||||||
|
IPAddress ipAddress;
|
||||||
|
if(ipAddress.fromString(_address))
|
||||||
|
{
|
||||||
|
_connectionStatus = connect(ipAddress, _port) == 1 ? SUCCESSFUL : FAILED;
|
||||||
|
#ifdef DEBUG_HTTP_CLIENT
|
||||||
|
Serial.printf("Correct ip address. Connection status : %d\n", _connectionStatus);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_connectionStatus = connect(_address, _port) == 1 ? SUCCESSFUL : FAILED;
|
||||||
|
#ifdef DEBUG_HTTP_CLIENT
|
||||||
|
Serial.printf("Probably a hostname. Connection status : %d\n", _connectionStatus);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return _connectionStatus == SUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean HttpClient::sendHttpQuery(const char *resource, HttpRequestMethod method, Dictionary<DictionaryHelper::StringEntity> *getData, Dictionary<DictionaryHelper::StringEntity> *postData)
|
||||||
|
{
|
||||||
|
if(resource != NULL) //We overwrite the resource if it has been already defined
|
||||||
|
{
|
||||||
|
if(_resource != NULL)
|
||||||
|
free(_resource);
|
||||||
|
|
||||||
|
_resource = (char *) malloc(strlen(resource) * sizeof(char) + 1);
|
||||||
|
strcpy(_resource, resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
//We check the result
|
||||||
|
return sendHttpQuery(method, getData, postData);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean HttpClient::sendHttpQuery(HttpRequestMethod method, Dictionary<DictionaryHelper::StringEntity> *getData, Dictionary<DictionaryHelper::StringEntity> *postData)
|
||||||
|
{
|
||||||
|
_httpCode = HTTP_CODE::UNDEFINED_CODE;
|
||||||
|
_bodyReadyToRead = false;
|
||||||
|
#ifdef DEBUG_HTTP_CLIENT
|
||||||
|
Serial.printf("Link status : %d\n", status());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!connected() || _connectionStatus == FAILED)
|
||||||
|
{
|
||||||
|
if(_retries == _maxRetries) return false;
|
||||||
|
if(_connectionStatus == FAILED)
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
_retries++;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_HTTP_CLIENT
|
||||||
|
Serial.printf("Link broken, we try to reconnect : addr : %s port %u\nretries : %u\n", _address, _port, _retries);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
connectByHostOrIp();
|
||||||
|
|
||||||
|
if(_connectionStatus == FAILED)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_HTTP_CLIENT
|
||||||
|
Serial.printf("Failed to reconnect\n");
|
||||||
|
#endif
|
||||||
|
stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(connected())
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_HTTP_CLIENT
|
||||||
|
Serial.printf("Server is listening\n", status());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch(method)
|
||||||
|
{
|
||||||
|
case HttpRequestMethod::GET:
|
||||||
|
//No Content-Length in this case
|
||||||
|
printf("GET %s", _resource == NULL ? "/" : _resource);
|
||||||
|
//Here we send the parameters
|
||||||
|
sendUriWithGetParams(getData);
|
||||||
|
sendHeader();
|
||||||
|
break;
|
||||||
|
case HttpRequestMethod::POST:
|
||||||
|
//It is necessary to compute the content length
|
||||||
|
printf("POST %s", _resource == NULL ? "/" : _resource);
|
||||||
|
//Here we send the parameters
|
||||||
|
sendUriWithGetParams(getData);
|
||||||
|
sendHeader(HttpMIMEType::APPLICATION_X_WWW_FORM_URLENCODED, computeBodyLength(postData));
|
||||||
|
sendPostData(postData);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
#ifdef DEBUG_HTTP_CLIENT
|
||||||
|
Serial.printf("Http verb unspecified\n", status());
|
||||||
|
#endif
|
||||||
|
if(!_keepAlive)stop();
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpClient::HTTP_CODE HttpClient::isReplyAvailable()
|
||||||
|
{
|
||||||
|
uint32_t bytesAvailable(available());
|
||||||
|
uint8_t readBuffer[100];
|
||||||
|
uint8_t safeSize;
|
||||||
|
|
||||||
|
if(bytesAvailable && !_bodyReadyToRead)
|
||||||
|
{
|
||||||
|
safeSize = bytesAvailable > 99 ? 99 : bytesAvailable;
|
||||||
|
peekBytes(readBuffer, safeSize);
|
||||||
|
readBuffer[safeSize] = '\0';
|
||||||
|
|
||||||
|
#ifdef DEBUG_HTTP_CLIENT
|
||||||
|
Serial.printf("Data chunk from server size -> %u - %u : %s\n", safeSize, bytesAvailable, readBuffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//We try to extract the http return code:
|
||||||
|
if(_httpCode == HTTP_CODE::UNDEFINED_CODE)
|
||||||
|
{
|
||||||
|
char *code = strchr((char *)readBuffer, ' '), *endP;
|
||||||
|
|
||||||
|
if(code != NULL)
|
||||||
|
{
|
||||||
|
endP = strchr(code + 1, ' ');
|
||||||
|
if(endP != NULL)
|
||||||
|
{
|
||||||
|
*endP = '\0';
|
||||||
|
|
||||||
|
#ifdef DEBUG_HTTP_CLIENT
|
||||||
|
Serial.printf("Http code : %s\n", code + 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
_httpCode = numberToHTTP_CODE(strtoul(code+1, NULL, 10));
|
||||||
|
read(readBuffer, safeSize - 4); //To remove the peek bytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!_bodyReadyToRead)
|
||||||
|
{
|
||||||
|
char *endP = strstr((char *)readBuffer, "\r\n\r\n");
|
||||||
|
|
||||||
|
if(endP != NULL)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_HTTP_CLIENT
|
||||||
|
Serial.printf("Body found, bytes to discard : %u\n", (uint8_t *)endP - readBuffer + 4);
|
||||||
|
#endif
|
||||||
|
read(readBuffer, (uint8_t *)endP - readBuffer + 4);
|
||||||
|
_bodyReadyToRead = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
read(readBuffer, safeSize - 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_httpCode != HTTP_CODE::UNDEFINED_CODE && _bodyReadyToRead)
|
||||||
|
return _httpCode;
|
||||||
|
|
||||||
|
return HTTP_CODE::UNDEFINED_CODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t HttpClient::readHttpReply(uint8_t *buffer, uint32_t size)
|
||||||
|
{
|
||||||
|
uint32_t bytesAvailable(available());
|
||||||
|
uint8_t safeSize(0);
|
||||||
|
|
||||||
|
if(bytesAvailable)
|
||||||
|
{
|
||||||
|
safeSize = bytesAvailable > size - 1 ? size - 1 : bytesAvailable;
|
||||||
|
|
||||||
|
read(buffer, safeSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[safeSize] = '\0';
|
||||||
|
|
||||||
|
return safeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpClient::sendUriWithGetParams(Dictionary<DictionaryHelper::StringEntity> *data)
|
||||||
|
{
|
||||||
|
if(data == NULL)return;
|
||||||
|
|
||||||
|
uint8_t count(data->count());
|
||||||
|
|
||||||
|
if(count == 0)return;
|
||||||
|
print("?");
|
||||||
|
|
||||||
|
for(int i(0); i < count; i++)
|
||||||
|
{
|
||||||
|
char str[2] = "";
|
||||||
|
if(data->getAt(i) != NULL)
|
||||||
|
{
|
||||||
|
if(strlen(data->getAt(i)->getString()) > 0)
|
||||||
|
strcpy(str, "=");
|
||||||
|
}
|
||||||
|
printf("%s%s%s", data->getParameter(i), str, data->getAt(i) != NULL ? data->getAt(i)->getString() : "");
|
||||||
|
|
||||||
|
if(i < count - 1)
|
||||||
|
print("&");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpClient::sendPostData(Dictionary<DictionaryHelper::StringEntity> *data)
|
||||||
|
{
|
||||||
|
if(data == NULL)return;
|
||||||
|
|
||||||
|
uint8_t count(data->count());
|
||||||
|
|
||||||
|
if(count == 0)return;
|
||||||
|
|
||||||
|
for(int i(0); i < count; i++)
|
||||||
|
{
|
||||||
|
printf("%s=%s", data->getParameter(i), data->getAt(i) != NULL ? data->getAt(i)->getString() : "");
|
||||||
|
|
||||||
|
if(i < count - 1)
|
||||||
|
print("&");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpClient::keepAlive(boolean enabled)
|
||||||
|
{
|
||||||
|
_keepAlive = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpClient::sendHeader(HttpMIMEType contentType, uint64_t contentLength, HttpVersion httpVersion)
|
||||||
|
{
|
||||||
|
char mime[255] = "", httpVer[15] = "";
|
||||||
|
printf(" %s\r\nHost: %u.%u.%u.%u:%u\r\nConnection: %s\r\n", httpVersionToString(httpVersion, httpVer), remoteIP()[0], remoteIP()[1], remoteIP()[2], remoteIP()[3], remotePort(), _keepAlive ? "keep-alive" : "close");
|
||||||
|
if(contentLength > 0)
|
||||||
|
{
|
||||||
|
printf("Content-Length: %u\r\n", contentLength);
|
||||||
|
printf("Content-Type: %s\r\n", httpMIMETypeToString(contentType, mime));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t HttpClient::computeBodyLength(Dictionary<DictionaryHelper::StringEntity> *data)
|
||||||
|
{
|
||||||
|
uint64_t length(0);
|
||||||
|
|
||||||
|
if(data == NULL)return length;
|
||||||
|
|
||||||
|
uint8_t count(data->count());
|
||||||
|
|
||||||
|
if(count == 0)return length;
|
||||||
|
|
||||||
|
for(int i(0); i < count; i++)
|
||||||
|
{
|
||||||
|
length += data->getAt(i) != NULL ? strlen(data->getAt(i)->getString()) + 1 : 1;
|
||||||
|
length += strlen(data->getParameter(i));
|
||||||
|
|
||||||
|
if(i < count - 1)
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
68
src/app/HttpClient.h
Normal file
68
src/app/HttpClient.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#ifndef HTTPCLIENT_H
|
||||||
|
#define HTTPCLIENT_H
|
||||||
|
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include "HttpConstants.h"
|
||||||
|
#include "Dictionary.h"
|
||||||
|
|
||||||
|
namespace HttpClientHelper
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class HttpClient : public WiFiClient, public HttpConstants
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum ConnectionStatus { NO_ATTEMPT = 0, SUCCESSFUL, FAILED };
|
||||||
|
|
||||||
|
HttpClient();
|
||||||
|
HttpClient(const char *address, uint16_t port = 80);
|
||||||
|
HttpClient(const char *address, const char *resource, uint16_t port = 80);
|
||||||
|
|
||||||
|
HttpClient(const HttpClient &object);
|
||||||
|
virtual ~HttpClient();
|
||||||
|
|
||||||
|
boolean sendHttpQuery(const char *ressource, HttpRequestMethod method = HttpRequestMethod::GET, Dictionary<DictionaryHelper::StringEntity> *getData = NULL, Dictionary<DictionaryHelper::StringEntity> *postData = NULL);
|
||||||
|
boolean sendHttpQuery(HttpRequestMethod method = HttpRequestMethod::GET, Dictionary<DictionaryHelper::StringEntity> *getData = NULL, Dictionary<DictionaryHelper::StringEntity> *postData = NULL);
|
||||||
|
void keepAlive(boolean enabled);
|
||||||
|
|
||||||
|
HTTP_CODE isReplyAvailable();
|
||||||
|
|
||||||
|
uint16_t readHttpReply(uint8_t *buffer, uint32_t size);
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
boolean connectByHostOrIp();
|
||||||
|
void sendUriWithGetParams(Dictionary<DictionaryHelper::StringEntity> *data);
|
||||||
|
void sendPostData(Dictionary<DictionaryHelper::StringEntity> *data);
|
||||||
|
void sendHeader(HttpMIMEType contentType = HttpMIMEType::UNKNOWN_MIME, uint64_t contentLength = 0, HttpVersion httpVersion = HttpVersion::HTTP_1_1);
|
||||||
|
uint64_t computeBodyLength(Dictionary<DictionaryHelper::StringEntity> *data);
|
||||||
|
|
||||||
|
ConnectionStatus _connectionStatus;
|
||||||
|
char *_resource;
|
||||||
|
char *_address;
|
||||||
|
uint16_t _port;
|
||||||
|
boolean _keepAlive;
|
||||||
|
uint8_t _maxRetries;
|
||||||
|
uint8_t _retries;
|
||||||
|
HTTP_CODE _httpCode;
|
||||||
|
boolean _bodyReadyToRead;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //HTTPCLIENT_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCP status codes :
|
||||||
|
* enum tcp_state {
|
||||||
|
CLOSED = 0,
|
||||||
|
LISTEN = 1,
|
||||||
|
SYN_SENT = 2,
|
||||||
|
SYN_RCVD = 3,
|
||||||
|
ESTABLISHED = 4,
|
||||||
|
FIN_WAIT_1 = 5,
|
||||||
|
FIN_WAIT_2 = 6,
|
||||||
|
CLOSE_WAIT = 7,
|
||||||
|
CLOSING = 8,
|
||||||
|
LAST_ACK = 9,
|
||||||
|
TIME_WAIT = 10
|
||||||
|
};
|
||||||
|
*/
|
@ -6,8 +6,87 @@ class HttpConstants
|
|||||||
public:
|
public:
|
||||||
enum HttpRequestMethod {UNDEFINED, GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH};
|
enum HttpRequestMethod {UNDEFINED, GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH};
|
||||||
enum HttpVersion {UNKNOWN, HTTP_0_9, HTTP_1_1, HTTP_1_0, HTTP_2_0};
|
enum HttpVersion {UNKNOWN, HTTP_0_9, HTTP_1_1, HTTP_1_0, HTTP_2_0};
|
||||||
enum HttpMIMEType{UNKNOWN_MIME, TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT, APPLICATION_JSON, APPLICATION_X_WWW_FORM_URLENCODED, IMAGE_PNG, IMAGE_JPEG, AUDIO_MPEG, APPLICATION_OCTET_STREAM};
|
enum HttpMIMEType {UNKNOWN_MIME, TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT, APPLICATION_JSON, APPLICATION_X_WWW_FORM_URLENCODED, IMAGE_PNG, IMAGE_JPEG, AUDIO_MPEG, APPLICATION_OCTET_STREAM};
|
||||||
enum HTTP_CODE {UNDEFINED_CODE, _100, _101, _200, _400, _401, _403, _404, _405, _500, _501};
|
enum HTTP_CODE {UNDEFINED_CODE, _100, _101, _200, _400, _401, _403, _404, _405, _500, _501};
|
||||||
|
|
||||||
|
static char *httpVersionToString(HttpVersion v, char *buffer)
|
||||||
|
{
|
||||||
|
if(buffer == NULL)return NULL;
|
||||||
|
|
||||||
|
switch(v)
|
||||||
|
{
|
||||||
|
case HttpVersion::HTTP_0_9:
|
||||||
|
strcpy_P(buffer, PSTR("HTTP/0.9"));
|
||||||
|
break;
|
||||||
|
case HttpVersion::HTTP_1_1:
|
||||||
|
strcpy_P(buffer, PSTR("HTTP/1.1"));
|
||||||
|
break;
|
||||||
|
case HttpVersion::HTTP_1_0:
|
||||||
|
strcpy_P(buffer, PSTR("HTTP/1.0"));
|
||||||
|
break;
|
||||||
|
case HttpVersion::HTTP_2_0:
|
||||||
|
strcpy_P(buffer, PSTR("HTTP/2.0"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strcpy_P(buffer, PSTR("HTTP/1.1"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *httpMIMETypeToString(HttpMIMEType m, char *buffer)
|
||||||
|
{
|
||||||
|
if(buffer == NULL)return NULL;
|
||||||
|
|
||||||
|
switch(m)
|
||||||
|
{
|
||||||
|
case HttpMIMEType::TEXT_PLAIN:
|
||||||
|
sprintf_P(buffer, PSTR("text/plain"));
|
||||||
|
break;
|
||||||
|
case HttpMIMEType::APPLICATION_JSON:
|
||||||
|
sprintf_P(buffer, PSTR("application/json"));
|
||||||
|
break;
|
||||||
|
case HttpMIMEType::APPLICATION_X_WWW_FORM_URLENCODED:
|
||||||
|
sprintf_P(buffer, PSTR("application/x-www-form-urlencoded"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf_P(buffer, PSTR("text/plain"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HTTP_CODE numberToHTTP_CODE(uint32_t code)
|
||||||
|
{
|
||||||
|
switch(code)
|
||||||
|
{
|
||||||
|
case 100:
|
||||||
|
return HTTP_CODE::_100;
|
||||||
|
case 101:
|
||||||
|
return HTTP_CODE::_101;
|
||||||
|
case 200:
|
||||||
|
return HTTP_CODE::_200;
|
||||||
|
case 400:
|
||||||
|
return HTTP_CODE::_400;
|
||||||
|
case 401:
|
||||||
|
return HTTP_CODE::_401;
|
||||||
|
case 403:
|
||||||
|
return HTTP_CODE::_403;
|
||||||
|
case 404:
|
||||||
|
return HTTP_CODE::_404;
|
||||||
|
case 405:
|
||||||
|
return HTTP_CODE::_405;
|
||||||
|
case 500:
|
||||||
|
return HTTP_CODE::_500;
|
||||||
|
case 501:
|
||||||
|
return HTTP_CODE::_501;
|
||||||
|
default :
|
||||||
|
return HTTP_CODE::UNDEFINED_CODE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
@ -668,7 +668,7 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
|||||||
|
|
||||||
static char *getHTTPHeader(HttpMIMEType httpMIMEType, size_t size)
|
static char *getHTTPHeader(HttpMIMEType httpMIMEType, size_t size)
|
||||||
{
|
{
|
||||||
char *header = (char *) malloc(sizeof(char) /*strlen("HTTP/1.1 200 OK\r\nContent-Type: \r\nContent-Length: \r\nCache-Control: max-age=31536000\r\n\r\n")*/* (86 + 74/*Longest MIME-TYPE*/ + 10 /*Max unsigned long footprint*/ + 1));
|
char *header = (char *) malloc(sizeof(char) /*strlen("HTTP/1.1 200 OK\r\nContent-Type: \r\nContent-Length: \r\nCache-Control: max-age=31536000\r\n\r\n")*/* (86 + 255/*Longest MIME-TYPE that RFC allows*/ + 10 /*Max unsigned long footprint*/ + 1));
|
||||||
|
|
||||||
switch(httpMIMEType)
|
switch(httpMIMEType)
|
||||||
{
|
{
|
||||||
|
@ -17,6 +17,8 @@ ViewSTAPacket vstap = {sab.getConnectivityManager().macAddress(), sab.getConnect
|
|||||||
ViewIoInfoPacket vio = {{0},{0}};
|
ViewIoInfoPacket vio = {{0},{0}};
|
||||||
SdCardApiPacket sdCardApiPacket = {NULL, NULL};
|
SdCardApiPacket sdCardApiPacket = {NULL, NULL};
|
||||||
|
|
||||||
|
DataLogger dataLogger = {HttpClient("192.168.0.17", "/esp8266/dataLogger.php", 1234), 0, false};
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
// put your setup code here, to run once:
|
// put your setup code here, to run once:
|
||||||
@ -78,10 +80,10 @@ void setup()
|
|||||||
|
|
||||||
sab.getIoManager().setISROnIOChange(&(ioISR), GPIO_3_RX);
|
sab.getIoManager().setISROnIOChange(&(ioISR), GPIO_3_RX);
|
||||||
|
|
||||||
sab.getTaskSchedulerManager().addTask(1, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setEnabled(false), &(task1));
|
sab.getTaskSchedulerManager().addTask((uint16_t)0, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setMillis(5000), &(task_blink), &sab);
|
||||||
sab.getTaskSchedulerManager().addTask(2, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setMillis(5000)->setEnabled(false), &(task2));
|
sab.getTaskSchedulerManager().addTask(1, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setSeconds(10), &(task_batt_sensing), &v1p);
|
||||||
sab.getTaskSchedulerManager().addTask(3, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setMillis(5000), &(task_blink), &sab);
|
dataLogger.client.keepAlive(true);
|
||||||
sab.getTaskSchedulerManager().addTask(4, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setSeconds(10), &(task_batt_sensing), &v1p);
|
sab.getTaskSchedulerManager().addTask(2, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setSeconds(1)->setTriggerRightAway(false), &(task_post_data_logger), &dataLogger);
|
||||||
|
|
||||||
Serial.println("End setup");
|
Serial.println("End setup");
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,5 @@
|
|||||||
#include "tasks.h"
|
#include "tasks.h"
|
||||||
|
|
||||||
boolean task1(void *pData)
|
|
||||||
{
|
|
||||||
Serial.println("Hi, i am the task one");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean task2(void *pData)
|
|
||||||
{
|
|
||||||
Serial.println("Hi, i am the task two");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean task_blink(void *pData)
|
boolean task_blink(void *pData)
|
||||||
{
|
{
|
||||||
SAB *p = (SAB *) pData;
|
SAB *p = (SAB *) pData;
|
||||||
@ -34,4 +20,54 @@ boolean task_batt_sensing(void *pData)
|
|||||||
boolean task_esp_reset_restart(void * pData)
|
boolean task_esp_reset_restart(void * pData)
|
||||||
{
|
{
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean task_post_data_logger(void * pData)
|
||||||
|
{
|
||||||
|
DataLogger *p = (DataLogger *) pData;
|
||||||
|
//This routine is here to test the new HttpClient class
|
||||||
|
//HttpClient httpClient("192.168.0.17", "/esp8266/dataLogger.php", 1234);
|
||||||
|
|
||||||
|
if(p->counter == 0)
|
||||||
|
{
|
||||||
|
Dictionary<DictionaryHelper::StringEntity> getData;
|
||||||
|
getData.add("key1", DictionaryHelper::StringEntity("value1"));
|
||||||
|
getData.add("key2", DictionaryHelper::StringEntity(NULL));
|
||||||
|
getData.add("key3", DictionaryHelper::StringEntity("value3"));
|
||||||
|
getData.add("key4", NULL);
|
||||||
|
|
||||||
|
Dictionary<DictionaryHelper::StringEntity> postData;
|
||||||
|
postData.add("post1", DictionaryHelper::StringEntity("postvalue1"));
|
||||||
|
postData.add("post2", DictionaryHelper::StringEntity(NULL));
|
||||||
|
postData.add("post3", DictionaryHelper::StringEntity("postvalue3"));
|
||||||
|
postData.add("post4", NULL);
|
||||||
|
|
||||||
|
|
||||||
|
if(p->client.sendHttpQuery(HttpClient::HttpRequestMethod::POST, &getData, &postData))
|
||||||
|
{
|
||||||
|
Serial.println("Send successful");
|
||||||
|
p->rdy = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(p->client.isReplyAvailable() != HttpClient::HTTP_CODE::UNDEFINED_CODE && !p->rdy)
|
||||||
|
{
|
||||||
|
Serial.printf("Code : %d, counter : %u\n", p->client.isReplyAvailable(), p->counter);
|
||||||
|
p->rdy = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p->rdy)
|
||||||
|
{
|
||||||
|
char buff[100];
|
||||||
|
p->client.readHttpReply((uint8_t *)buff, 100);
|
||||||
|
Serial.print(buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
p->counter++;
|
||||||
|
|
||||||
|
if(p->counter == 30)
|
||||||
|
p->counter = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,18 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "SAB.h"
|
#include "SAB.h"
|
||||||
#include "views.h"
|
#include "views.h"
|
||||||
|
#include "HttpClient.h"
|
||||||
|
|
||||||
boolean task1(void *);
|
|
||||||
boolean task2(void *);
|
|
||||||
boolean task_blink(void *);
|
boolean task_blink(void *);
|
||||||
boolean task_batt_sensing(void *);
|
boolean task_batt_sensing(void *);
|
||||||
boolean task_esp_reset_restart(void *);
|
boolean task_esp_reset_restart(void *);
|
||||||
|
|
||||||
|
typedef struct dataLogger
|
||||||
|
{
|
||||||
|
HttpClient client;
|
||||||
|
uint8_t counter;
|
||||||
|
boolean rdy;
|
||||||
|
}DataLogger;
|
||||||
|
boolean task_post_data_logger(void *);
|
||||||
|
|
||||||
#endif //TASKS_H
|
#endif //TASKS_H
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#define SOFT_VERSION "1.3.2" //Modified TCPServer and WEBServer core logic
|
#define SOFT_VERSION "1.3.2" //Modified TCPServer and WEBServer core logic
|
||||||
#define SOFT_VERSION "1.4.0" //Added the new FTPServer
|
#define SOFT_VERSION "1.4.0" //Added the new FTPServer
|
||||||
#define SOFT_VERSION "1.4.1" //Updated FTP server to use the new SD library for the ESP8266
|
#define SOFT_VERSION "1.4.1" //Updated FTP server to use the new SD library for the ESP8266
|
||||||
#define SOFT_VERSION "1.4.2" //Added new functionalities as well as login check
|
#define SOFT_VERSION "1.4.2" //Added new functionalities to the FTP server as well as login check
|
||||||
#define SOFT_VERSION "1.4.3" //Added ICACHE_RAM_ATTR because of a strange performance hit
|
#define SOFT_VERSION "1.4.3" //Added ICACHE_RAM_ATTR because of a strange performance hit
|
||||||
#define SOFT_VERSION "1.5.0" //Added new rtcInfo view + DS3231 internal temperature
|
#define SOFT_VERSION "1.5.0" //Added new rtcInfo view + DS3231 internal temperature
|
||||||
#define SOFT_VERSION "1.5.1" //Corrected a mistake in the sendPageToClientFromSdCard method (WEBServer class)
|
#define SOFT_VERSION "1.5.1" //Corrected a mistake in the sendPageToClientFromSdCard method (WEBServer class)
|
||||||
@ -29,5 +29,6 @@
|
|||||||
#define SOFT_VERSION "1.5.4" //Updated TCPClient (using memmove instead of strcpy)
|
#define SOFT_VERSION "1.5.4" //Updated TCPClient (using memmove instead of strcpy)
|
||||||
#define SOFT_VERSION "1.5.5" //WEBServer now parsing form parameters in the post data section
|
#define SOFT_VERSION "1.5.5" //WEBServer now parsing form parameters in the post data section
|
||||||
#define SOFT_VERSION "1.5.6" //Added new SAB method to set te cpu frequency at run time
|
#define SOFT_VERSION "1.5.6" //Added new SAB method to set te cpu frequency at run time
|
||||||
|
#define SOFT_VERSION "1.6.0" //Added the new HttpClient class along with tests in a new task
|
||||||
|
|
||||||
#endif //VERSIONS_H
|
#endif //VERSIONS_H
|
||||||
|
Loading…
Reference in New Issue
Block a user