add webserver components, some webserver fices and improvements in templating, add real time history chart

This commit is contained in:
2020-01-07 00:21:27 +01:00
parent ed53611e0f
commit ef7866a29f
50 changed files with 3594 additions and 2 deletions
+62
View File
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <esp_log.h>
static const char *TAG = "base16";
void base16_encode(uint8_t *raw, size_t len, char *encoded) {
uint8_t *raw_bytes = raw;
char *encoded_bytes = encoded;
size_t remaining = len;
for (; remaining--; encoded_bytes += 2)
snprintf(encoded_bytes, 3, "%02X", *(raw_bytes++));
}
int base16_decode(const char *encoded, uint8_t *raw) {
const char *encoded_bytes = encoded;
uint8_t *raw_bytes = raw;
char buf[3];
char *endp;
size_t len;
while (encoded_bytes[0]) {
if (!encoded_bytes[1]) {
ESP_LOGE(TAG, "Base16-encoded string \"%s\" has invalid length\n",
encoded);
return -22;
}
memcpy(buf, encoded_bytes, 2);
buf[2] = '\0';
*(raw_bytes++) = strtoul(buf, &endp, 16);
if (*endp != '\0') {
ESP_LOGE(TAG,"Base16-encoded string \"%s\" has invalid byte \"%s\"\n",
encoded, buf);
return -22;
}
encoded_bytes += 2;
}
len = (raw_bytes - raw);
return (len);
}
@@ -0,0 +1,85 @@
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include "common_utils/utils.h"
char *append(char *buf, const char *appended, size_t *pcap)
{
char c;
char *buf0 = buf;
size_t cap = *pcap;
if (buf0 == NULL) return NULL;
if (appended == NULL || appended[0] == 0) return buf0;
if (*pcap < strlen(appended)+1) {
return NULL;
}
while (cap > 1 && 0 != (c = *appended++)) {
*buf++ = c;
cap--;
}
assert(cap > 0);
*pcap = cap;
*buf = 0;
return buf;
}
bool append_realloc(char **head, size_t *cap, const char *appended) {
if (!head) return NULL;
if (!*head) return NULL;
if (!cap) return NULL;
if (!appended) return NULL;
size_t cursize = strlen(*head);
size_t needed = strlen(appended) + 1;
size_t remains = *cap - cursize;
if (remains < needed) {
size_t need_extra = needed - remains;
size_t newsize = *cap + need_extra;
char *new = realloc(*head, newsize);
if (!new) return false;
*head = new;
*cap = newsize;
}
strcpy(*head + cursize, appended);
return true;
}
bool fd_is_valid(int fd)
{
return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
}
bool parse_boolean_arg(const char *str)
{
if (0 == strcasecmp(str, "on")) return true;
if (0 == strcmp(str, "1")) return true;
if (0 == strcasecmp(str, "yes")) return true;
if (0 == strcasecmp(str, "enable")) return true;
if (0 == strcasecmp(str, "en")) return true;
if (0 == strcasecmp(str, "y")) return true;
if (0 == strcasecmp(str, "a")) return true;
return false;
}
bool parse_boolean_arg_false(const char *str)
{
if (0 == strcasecmp(str, "off")) return true;
if (0 == strcmp(str, "0")) return true;
if (0 == strcasecmp(str, "no")) return true;
if (0 == strcasecmp(str, "disable")) return true;
if (0 == strcasecmp(str, "dis")) return true;
if (0 == strcasecmp(str, "n")) return true;
return false;
}
+110
View File
@@ -0,0 +1,110 @@
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "common_utils/datetime.h"
const char *DT_WKDAY_NAMES[] = {
[MONDAY] = "Mon",
[TUESDAY] = "Tue",
[WEDNESDAY] = "Wed",
[THURSDAY] = "Thu",
[FRIDAY] = "Fri",
[SATURDAY] = "Sat",
[SUNDAY] = "Sun"
};
const char *DT_WKDAY_NAMES_FULL[] = {
[MONDAY] = "Monday",
[TUESDAY] = "Tuesday",
[WEDNESDAY] = "Wednesday",
[THURSDAY] = "Thursday",
[FRIDAY] = "Friday",
[SATURDAY] = "Saturday",
[SUNDAY] = "Sunday"
};
const char *DT_MONTH_NAMES[] = {
[JANUARY] = "Jan",
[FEBRUARY] = "Feb",
[MARCH] = "Mar",
[APRIL] = "Apr",
[MAY] = "May",
[JUNE] = "Jun",
[JULY] = "Jul",
[AUGUST] = "Aug",
[SEPTEMBER] = "Sep",
[OCTOBER] = "Oct",
[NOVEMBER] = "Nov",
[DECEMBER] = "Dec"
};
const char *DT_MONTH_NAMES_FULL[] = {
[JANUARY] = "January",
[FEBRUARY] = "February",
[MARCH] = "March",
[APRIL] = "April",
[MAY] = "May",
[JUNE] = "June",
[JULY] = "July",
[AUGUST] = "August",
[SEPTEMBER] = "September",
[OCTOBER] = "October",
[NOVEMBER] = "November",
[DECEMBER] = "December"
};
static const uint16_t MONTH_LENGTHS[] = { /* 1-based, normal year */
[JANUARY]=31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
_Static_assert(sizeof(MONTH_LENGTHS) / sizeof(uint16_t) == 13, "Months array length");
static const uint16_t MONTH_YEARDAYS[] = { /* 1-based */
[JANUARY]=0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 // // days until 1st of month
};
_Static_assert(sizeof(MONTH_YEARDAYS) / sizeof(uint16_t) == 13, "Months array length");
_Static_assert(MONDAY < SUNDAY, "Weekday ordering");
bool datetime_is_valid(const datetime_t *dt)
{
if (dt == NULL) return false;
// check month first to avoid out-of-bounds read from the MONTH_LENGTHS table
if (!(dt->month >= JANUARY && dt->month <= DECEMBER)) return false;
int monthlen = MONTH_LENGTHS[dt->month];
if (dt->month == FEBRUARY && is_leap_year(dt->year)) {
monthlen = 29;
}
return dt->sec < 60 &&
dt->min < 60 &&
dt->hour < 24 &&
dt->wkday >= MONDAY &&
dt->wkday <= SUNDAY &&
dt->year >= DT_START_YEAR &&
dt->year <= DT_END_YEAR &&
dt->day >= 1 &&
dt->day <= monthlen;
}
bool datetime_set_weekday(datetime_t *dt)
{
dt->wkday = MONDAY; // prevent the validator func erroring out on invalid weekday
if (!datetime_is_valid(dt)) return false;
dt->wkday = date_weekday(dt->year, dt->month, dt->day);
return true;
}
enum weekday date_weekday(uint16_t year, enum month month, uint8_t day)
{
uint16_t days = (DT_START_WKDAY - MONDAY) + (year - DT_START_YEAR) * 365 + MONTH_YEARDAYS[month] + (day - 1);
for (uint16_t i = DT_START_YEAR; i <= year; i++) {
if (is_leap_year(i) && (i < year || month > FEBRUARY)) days++;
}
return MONDAY + days % 7;
}
+72
View File
@@ -0,0 +1,72 @@
/*
* util.c
*
* Created on: Aug 12, 2009
* Author: johan
*/
// adapted from libgomspace
#include <string.h>
#include <stdio.h>
#include "common_utils/hexdump.h"
//! Dump memory to debugging output
/**
* Dumps a chunk of memory to the screen
*/
void hex_dump(FILE * fp, void *src, int len) {
int i, j=0, k;
char text[17];
text[16] = '\0';
//printf("Hex dump:\r\n");
fprintf(fp, "%p : ", src);
for(i=0; i<len; i++) {
j++;
fprintf(fp, "%02X ", ((volatile unsigned char *)src)[i]);
if(j == 8)
fputc(' ', fp);
if(j == 16) {
j = 0;
memcpy(text, &((char *)src)[i-15], 16);
for(k=0; k<16; k++) {
if((text[k] < 32) || (text[k] > 126)) {
text[k] = '.';
}
}
fprintf(fp, " |%s|\n\r", text);
if(i<len-1) {
fprintf(fp, "%p : ", src+i+1);
}
}
}
if (i % 16)
fprintf(fp, "\r\n");
}
void hex_dump_buff_line(FILE *fp, int addr_size, unsigned pos, char *line, unsigned len)
{
unsigned i;
fprintf(fp, "%0*x", addr_size, pos);
for (i = 0; i < HEX_DUMP_LINE_BUFF_SIZ; i++)
{
if (!(i % 8))
fputc(' ', fp);
if (i < len)
fprintf(fp, " %02x", (unsigned char)line[i]);
else
fputs(" ", fp);
}
fputs(" |", fp);
for (i = 0; i < HEX_DUMP_LINE_BUFF_SIZ && i < len; i++)
{
if (line[i] >= 32 && line[i] <= 126)
fprintf(fp, "%c", (unsigned char)line[i]);
else
fputc('.', fp);
}
fputs("|\r\n", fp);
}