Male zmeny v index.html

- prerobenie  settings handleru
- presunutie do ~/data folderu
- odstranenie starych suborov
- pridanie parsovania settings.json
- obsluha SPFFS
This commit is contained in:
2020-04-19 18:55:08 +02:00
parent 55b69b9a8d
commit 1b38f5b129
4 changed files with 296 additions and 232 deletions

View File

@@ -81,7 +81,9 @@
$(function () { $(function () {
settings = [ { "kedy": 0 , "cas": "6:38", "datum": null, "edit": true}, { "kedy": 0 , "cas": "17:00", "datum": null, "edit":false} ]; settings = %%SETTINGS%%;
settings = settings["data"];
when = { 0 : "Pracovne dni", when = { 0 : "Pracovne dni",
1 : "Vikendy", 1 : "Vikendy",
2 : "Zajtra", 2 : "Zajtra",
@@ -112,8 +114,16 @@
}, },
postChanges: function () { postChanges: function () {
console.log("SAVE CHANGES TO ESP"); console.log("SAVE CHANGES TO ESP");
axios.get('https://api.coindesk.com/v1/bpi/currentprice.json')
.then(response => (console.log(response))); axios.post('/settings', {
data: this.settings
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
} }
} }
}) })

1
data/settings.json Normal file
View File

@@ -0,0 +1 @@
{ "data": [ { "kedy": 0, "cas": "", "datum":"", "edit": true} ] }

View File

@@ -1,166 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- <link rel="stylesheet" type="text/css" href="css/bootstrap-datetimepicker.css"> -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.1/moment.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.43/css/bootstrap-datetimepicker.min.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.43/css/bootstrap-datetimepicker-standalone.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.43/js/bootstrap-datetimepicker.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/3.1.0/mustache.min.js"></script>
</head>
<body>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/3.1.4/js/bootstrap-datetimepicker.min.js" integrity="sha256-sU6nRhzXDAC31Wdrirz7X2A2rSRWj10WnP9CA3vpYKw=" crossorigin="anonymous"></script>
<div class="container">
<h1 align="center">Budík</h1>
<div class="row">
<div data-form-number=0 class='form-row'>
<div class="form-group col-sm-3">
<select data-form="type" class="form-control mr-sm-2" id="inlineFormCustomSelect">
<option value="0" selected>Pracovne dni</option>
<option value="1">Vikendy</option>
<option value="2">Zajtra</option>
<option value="3">Iba raz</option>
</select>
</div>
<div class="form-group col-sm-3">
<div class='input-group time' id='datetimepicker2'>
<input data-form="time" type='text' class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-time"></span>
</span>
</div>
</div>
<div class="form-group col-sm-3">
<div class='input-group time' id='datetimepicker3'>
<input data-form="date" type='text' class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-time"></span>
</span>
</div>
</div>
<div class="btn-toolbar col-sm-3" role="toolbar" aria-label="Toolbar with button groups">
<div class="btn-group mr-2" role="group" aria-label="First group">
<button data-button=1 type="button" class="btn btn-secondary glyphicon glyphicon-plus"></button>
<button data-button=2 type="button" class="btn btn-secondary glyphicon glyphicon-minus"></button>
<button data-button=3 type="button" class="btn btn-secondary glyphicon glyphicon-edit"></button>
<button data-button=4 type="button" class="btn btn-secondary glyphicon glyphicon-save"></button>
</div>
</div>
</div>
<script type="text/javascript">
var nf = 0;
var when = { 0 : "Pracovne dni",
1 : "Vikendy",
2 : "Zajtra",
3 : "Iba raz"
};
var when_rev = {};
function add_to_end(s) {
h = $('.btn-toolbar')[0].outerHTML;
$('.container')
.append('<div class="row"><div class="col-sm-3">'+ when[s.kedy] +'</div><div class="col-sm-3">'+ s.cas +'</div><div class="col-sm-3">'+ s.datum +'</div>' + h + '</div>');
}
function set_datepicker() {
$('#datetimepicker3').datetimepicker({
pickTime: false,
format: "D.M.YYYY"
});
$('#datetimepicker2').datetimepicker({
format : 'HH:mm',
pickDate: false
});
}
function set_click_handler() {
$('.glyphicon-plus').click(function() {
console.log('PLUS');
nf++;
form = $('*[data-form-number=0]').html();
html1 = "<div class='row'><div data-form-number=" + nf + " class='form-row'>" + form + "</div></div>";
$('.container').append(html1);
set_datepicker();
});
$('.glyphicon-minus').click(function(el) {
console.log('MINUS');
$(this.parentNode.parentNode.parentNode).remove();
});
$('.glyphicon-edit').click(function() {
console.log('EDIT');
data = $(this.parentNode.parentNode.parentNode);
type = data.children().html();
time = data.children().next().html();
date = data.children().next().next().html();
if (date == "null") date = "";
nf++;
form = $('*[data-form-number=0]').html();
html1 = "<div data-form-number=" + nf + " class='form-row'>" + form + "</div>";
$(this.parentNode.parentNode.parentNode).html(html1);
$('*[data-form-number='+ nf +']').find('*[data-form="type"]').val(when_rev[type]);
$('*[data-form-number='+ nf +']').find('*[data-form="time"]').val(time);
$('*[data-form-number='+ nf +']').find('*[data-form="date"]').val(date);
set_datepicker();
});
$('.glyphicon-save').click(function() {
console.log('SAVE');
forms = $(this.parentNode.parentNode.parentNode);
type = forms.find('*[data-form="type"]').val();
time = forms.find('*[data-form="time"]').val();
date = forms.find('*[data-form="date"]').val();
h = $('.btn-toolbar')[0].outerHTML;
forms.replaceWith('<div class="col-sm-3">'+ when[type] +'</div><div class="col-sm-3">'+ time +'</div><div class="col-sm-3">'+ date+'</div>' + h + '</div>');
});
}
for (var key in when) {
when_rev[when[key]] = key;
};
$(function () {
settings = [ { "kedy": 0 , "cas": "6:38", "datum": null}, { "kedy": 0 , "cas": "17:00", "datum": null} ];
settings.forEach(s => add_to_end(s));
set_datepicker();
set_click_handler();
$('.container').append('<button type="button" class="btn btn-dark">Nastav</button>');
$('.container > button').click(function() {
console.log('SET SETTINGS');
})
});
</script>
</div>
</div>
</body>
</html>

View File

@@ -1,4 +1,3 @@
#include <NTPClient.h>
// change next line to use with another board/shield // change next line to use with another board/shield
#include <WiFi.h> #include <WiFi.h>
#include <SPI.h> #include <SPI.h>
@@ -12,11 +11,13 @@
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <DateTime.h> #include <DateTime.h>
#include <IotWebConf.h> #include <IotWebConf.h>
#include <NTP.h>
#include <SPIFFS.h>
#include <time.h>
#include "calendar.h" #include "calendar.h"
#ifndef PSTR #ifndef PSTR
#define PSTR // Make Arduino Due happy #define PSTR // Make Arduino Due happy
#endif #endif
#define COMMAND_PARAMETER_LENGTH 30 #define COMMAND_PARAMETER_LENGTH 30
@@ -37,26 +38,68 @@ DNSServer dnsServer;
WebServer server(80); WebServer server(80);
IotWebConf iotWebConf(thingName, &dnsServer, &server, wifiInitialApPassword); IotWebConf iotWebConf(thingName, &dnsServer, &server, wifiInitialApPassword);
enum Lines_names
enum Lines_names { TIME_LINE, DATE_LINE, WEATHER_LINE, NAMES_LINE, LAST_LINE }; {
TIME_LINE,
DATE_LINE,
WEATHER_LINE,
NAMES_LINE,
LAST_LINE
};
String Lines[LAST_LINE]; String Lines[LAST_LINE];
Adafruit_NeoMatrix *matrix; Adafruit_NeoMatrix *matrix;
const uint16_t colors[] = { const uint16_t colors[] = {
Adafruit_NeoMatrix::Color(255, 0, 0), Adafruit_NeoMatrix::Color(0, 255, 0), Adafruit_NeoMatrix::Color(0, 0, 255) }; Adafruit_NeoMatrix::Color(255, 0, 0), Adafruit_NeoMatrix::Color(0, 255, 0), Adafruit_NeoMatrix::Color(0, 0, 255)};
WiFiUDP ntpUDP; WiFiUDP ntpUDP;
// You can specify the time server pool and the offset (in seconds, can be // You can specify the time server pool and the offset (in seconds, can be
// changed later with setTimeOffset() ). Additionaly you can specify the // changed later with setTimeOffset() ). Additionaly you can specify the
// update interval (in milliseconds, can be changed using setUpdateInterval() ). // update interval (in milliseconds, can be changed using setUpdateInterval() ).
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000); bool initialized = false;
NTP ntp(ntpUDP);
HTTPClient client; HTTPClient client;
DynamicJsonDocument doc(1024); DynamicJsonDocument doc(1024);
String settings;
String get_name_of_day(int m,int d) { enum when_names {
for (int i=0;i<sizeof(cal_names)/sizeof(cal_names[0]); i++) { WORK_DAYS,
if (cal_names[i].m == m && cal_names[i].d ==d) WEEKENDS,
TOMOROW,
ONCE
};
struct timer_def {
int when; int h; int m; int d; int mh; int y;
};
int ntimers;
#define MAX_TIMERS 10
timer_def Timers[MAX_TIMERS];
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = { 0, -1 };
int maxIndex = data.length() - 1;
for (int i = 0; i <= maxIndex && found <= index; i++) {
if (data.charAt(i) == separator || i == maxIndex) {
found++;
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}
String get_name_of_day(int m, int d)
{
for (int i = 0; i < sizeof(cal_names) / sizeof(cal_names[0]); i++)
{
if (cal_names[i].m == m && cal_names[i].d == d)
return String(cal_names[i].name); return String(cal_names[i].name);
} }
return String("Sviatok"); return String("Sviatok");
@@ -66,9 +109,11 @@ String get_weather_line()
{ {
client.begin("http://api.openweathermap.org/data/2.5/weather?q=Trnava,sk&lang=sk&APPID=d15c61931a053026e98769dd9fc46ba3"); client.begin("http://api.openweathermap.org/data/2.5/weather?q=Trnava,sk&lang=sk&APPID=d15c61931a053026e98769dd9fc46ba3");
int code = client.GET(); int code = client.GET();
if (code > 0) { if (code > 0)
{
if(code == HTTP_CODE_OK) { if (code == HTTP_CODE_OK)
{
float temp; float temp;
String w; String w;
String desc; String desc;
@@ -80,32 +125,37 @@ String get_weather_line()
w = obj["weather"][0]["main"].as<String>(); w = obj["weather"][0]["main"].as<String>();
desc = obj["weather"][0]["description"].as<String>(); desc = obj["weather"][0]["description"].as<String>();
temp -= 273.15; temp -= 273.15;
return String(temp) + String("C ") + desc; return String(temp) + String("C ") + desc;
} }
} }
return "Error"; return "Error";
} }
String get_time_line(){ String get_time_line()
return String(DateTime.format("%H:%M")); {
return String(ntp.formattedTime("%H:%M"));
} }
String get_date_line(){ String get_date_line()
return String(DateTime.format("%d.%m")); {
return String(ntp.formattedTime("%d.%m"));
} }
String get_names_line() { String get_names_line()
{
int d = DateTime.getParts().getMonthDay(); int d = DateTime.getParts().getMonthDay();
int m = DateTime.getParts().getMonth();m++; int m = DateTime.getParts().getMonth();
return get_name_of_day(m,d); m++;
return get_name_of_day(m, d);
} }
void setup_matrix() { void setup_matrix()
{
matrix = new Adafruit_NeoMatrix(32, 8, PIN, matrix = new Adafruit_NeoMatrix(32, 8, PIN,
NEO_MATRIX_BOTTOM + NEO_MATRIX_RIGHT + NEO_MATRIX_BOTTOM + NEO_MATRIX_RIGHT +
NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG, NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
NEO_GBR + NEO_KHZ800); NEO_GBR + NEO_KHZ800);
matrix->begin(); matrix->begin();
matrix->setTextWrap(false); matrix->setTextWrap(false);
@@ -113,47 +163,192 @@ void setup_matrix() {
matrix->setTextColor(colors[1]); matrix->setTextColor(colors[1]);
} }
void setup(){ void returnOK() {
server.send(200, "text/plain", "");
}
void handleSave() {
String data;
Serial.println(server.uri());
Serial.println(server.method());
Serial.println(server.argName(0));
Serial.println(server.arg(0));
if (server.uri() != "/settings" && server.method() != HTTP_POST) {
return;
}
data = server.arg(0);
Serial.println("Data:" + data);
File file = SPIFFS.open("/settings.json", "w");
if (!file)
{
Serial.println("Failed to open file for writing");
return;
}
settings = data;
file.print(data.c_str());
file.close();
server.send(200, "text/plain", "");
}
void read_config()
{
File file = SPIFFS.open("/settings.json", "r");
if (!file)
{
Serial.println("Failed to open settings file for reading");
return;
}
Serial.println("====File Content SETTINGS====");
String s;
while (file.available())
{
s += (char)file.read();
}
Serial.print(s);
file.close();
ntimers = 0;
settings = s;
Serial.println("SETTINGS: " + settings);
deserializeJson(doc, settings);
JsonObject obj = doc.as<JsonObject>();
for (int i=0;i < obj["data"].size(); i++) {
int t = obj["data"][i]["kedy"].as<int>();
String c = obj["data"][i]["cas"].as<String>();
String datum = obj["data"][i]["datum"].as<String>();
int h = getValue(c,':',0).toInt();
int m = getValue(c,':',1).toInt();
int d = 0;
int mh = 0;
int y = 0;
Serial.println(t);
Serial.println(c);
Serial.println(datum);
if (datum != NULL) {
d = getValue(datum,'.',0).toInt();
mh = getValue(datum,'.',1).toInt();
y = getValue(datum,'.',2).toInt();
}
Timers[ntimers].when = t;
Timers[ntimers].h = h;
Timers[ntimers].m = m;
Timers[ntimers].d = d;
Timers[ntimers].mh = mh;
Timers[ntimers].y = y;
ntimers++;
}
Serial.println("N timers:" + ntimers);
}
void calculate_timers()
{
timer_def *t;
struct tm tm;
for (int i=0; i<ntimers ; i++)
{
t = &Timers[i];
tm.tm_sec = 0;
tm.tm_min = t->m;
tm.tm_hour = t->h;
if (t->d !=0) {
tm.tm_mday = t->d;
tm.tm_mon = t->mh;
tm.tm_year = t->y;
} else {
tm.tm_mday = 0;
tm.tm_mon = 0;
tm.tm_year = 0;
}
if (t->d == 0) {
if (t->when == WORK_DAYS) {
} else if (t->when == WEEKENDS) {
} else if (t->when == TOMOROW ) {
}
}
}
}
void setup()
{
Serial.begin(115200); Serial.begin(115200);
//iotWebConf.setStatusPin(PIN); //iotWebConf.setStatusPin(PIN);
iotWebConf.init(); iotWebConf.init();
// -- Set up required URL handlers on the web server. if (!SPIFFS.begin(true))
{
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
// -- Set up required URL handlers on the web server.
server.on("/", handleRoot); server.on("/", handleRoot);
server.on("/config", []{ iotWebConf.handleConfig(); }); server.on("/config", [] { iotWebConf.handleConfig(); });
server.onNotFound([](){ iotWebConf.handleNotFound(); }); server.on("/settings", HTTP_POST, handleSave);
server.onNotFound([]() { iotWebConf.handleNotFound(); });
setup_matrix(); setup_matrix();
read_config();
} }
void scroll_line(String line) { void scroll_line(String line)
int x = 0, mx = 32; {
int y = 0; int x = 0, mx = 32;
int y = 0;
if (line.length() * 6 > mx) { if (line.length() * 6 > mx)
for (x = 0; x < line.length()*6 - mx; x++) { {
matrix->fillScreen(0); for (x = 0; x < line.length() * 6 - mx; x++)
matrix->setCursor(-x, y); {
matrix->setTextColor(colors[1]);
matrix->print(line);
matrix->show();
if (x == 0) delay(300);
else delay(100);
}
delay(1000);
} else {
matrix->fillScreen(0); matrix->fillScreen(0);
matrix->setCursor(x, y); matrix->setCursor(-x, y);
matrix->setTextColor(colors[1]); matrix->setTextColor(colors[1]);
matrix->print(line); matrix->print(line);
matrix->show(); matrix->show();
delay(3000); if (x == 0)
delay(300);
else
delay(100);
} }
delay(1000);
}
else
{
matrix->fillScreen(0);
matrix->setCursor(x, y);
matrix->setTextColor(colors[1]);
matrix->print(line);
matrix->show();
delay(3000);
}
} }
void handleRoot() void handleRoot()
{ {
// -- Let IotWebConf test and handle captive portal requests. // -- Let IotWebConf test and handle captive portal requests.
@@ -162,36 +357,60 @@ void handleRoot()
// -- Captive portal request were already served. // -- Captive portal request were already served.
return; return;
} }
String s = "<!DOCTYPE html><html lang=\"en\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\"/>";
s += "<title>IotWebConf 02 Status and Reset</title></head><body>Hello world!"; File file = SPIFFS.open("/index.html", "r");
s += "Go to <a href='config'>configure page</a> to change settings."; if (!file)
s += "</body></html>\n"; {
Serial.println("Failed to open file for reading");
return;
}
Serial.println("====File Content====");
String s;
while (file.available())
{
s += (char)file.read();
}
s.replace("%%SETTINGS%%",settings);
Serial.print(s);
file.close();
server.send(200, "text/html", s); server.send(200, "text/html", s);
} }
void loop() { void loop()
{
unsigned long sec; unsigned long sec;
unsigned long n=0; unsigned long n = 0;
// -- doLoop should be called as frequently as possible. // -- doLoop should be called as frequently as possible.
iotWebConf.doLoop(); iotWebConf.doLoop();
if (WiFi.status() == WL_CONNECTED) { if (WiFi.status() == WL_CONNECTED)
timeClient.begin(); {
timeClient.update(); if (initialized == false)
sec = timeClient.getEpochTime(); {
ntp.ruleDST("CEST", Last, Sun, Mar, 2, 120); // last sunday in march 2:00, timetone +120min (+1 GMT + 1h summertime offset)
ntp.ruleSTD("CET", Last, Sun, Oct, 3, 60); // last sunday in october 3:00, timezone +60min (+1 GMT)
ntp.begin();
initialized = true;
}
sec = ntp.epoch();
DateTime.setTime(sec); DateTime.setTime(sec);
if (n++ % 25 == 0) Lines[WEATHER_LINE] = get_weather_line(); if (n++ % 25 == 0)
Lines[WEATHER_LINE] = get_weather_line();
Lines[TIME_LINE] = get_time_line(); Lines[TIME_LINE] = get_time_line();
Lines[DATE_LINE] = get_date_line(); Lines[DATE_LINE] = get_date_line();
Lines[NAMES_LINE] = get_names_line(); Lines[NAMES_LINE] = get_names_line();
for (int i=0;i<LAST_LINE;i++) { for (int i = 0; i < LAST_LINE; i++)
{
Serial.println(Lines[i]); Serial.println(Lines[i]);
scroll_line(Lines[i]); scroll_line(Lines[i]);
iotWebConf.doLoop();
} }
} }
} }