remove cloud stuff for standalone mode #16

pull/1/head
Thomas Ballmann 4 years ago
parent 79c1aa5f87
commit c0bb7f6237

1
.gitignore vendored

@ -5,3 +5,4 @@
.vscode/ipch .vscode/ipch
.DS_Store .DS_Store
/data/dist /data/dist
/test

@ -1,7 +1,7 @@
{ {
// See http://go.microsoft.com/fwlink/?LinkId=827846 // See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format // for the documentation about the extensions.json format
"recommendations": [ "recommendations": [
"platformio.platformio-ide" "platformio.platformio-ide"
] ]
} }

@ -5,6 +5,44 @@
"istream": "cpp", "istream": "cpp",
"ostream": "cpp", "ostream": "cpp",
"sstream": "cpp", "sstream": "cpp",
"functional": "cpp" "functional": "cpp",
"array": "cpp",
"bitset": "cpp",
"initializer_list": "cpp",
"regex": "cpp",
"utility": "cpp",
"deque": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"cstdint": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"limits": "cpp",
"memory": "cpp",
"new": "cpp",
"numeric": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp"
} }
} }

@ -12,4 +12,15 @@ yarn --cwd app build
# upload to device filesystem # upload to device filesystem
platformio run --target uploadfs platformio run --target uploadfs
```
# send a picture to display over json
curl -F 'myImage=@blackPNG.png' http://192.168.178.62/api/face
# erase flash memory
pio run --target erase
```
## access fs over http
> get photos from calendar face
http://192.168.178.65/fs/calendarPhoto.png

@ -8,7 +8,7 @@ module.exports = {
devServer: { devServer: {
proxy: { proxy: {
'^/': { '^/': {
target: 'http://192.168.178.62:80', target: 'http://192.168.178.65:80',
ws: true, ws: true,
changeOrigin: true changeOrigin: true
}, },

@ -0,0 +1,6 @@
#ifndef DOWNLOAD_H
#define DOWNLOAD_H
bool downloadFile(String url, const char *path);
#endif

@ -1,6 +1,24 @@
#ifndef FACE_WEATHER_H #ifndef FACE_WEATHER_H
#define FACE_WEATHER_H #define FACE_WEATHER_H
// TODO
struct faceWeatherData
{
//char hostname[64];
//int port;
char current_icon[4];
char current_description[20];
char location[20];
// current
int current_temp;
int today_min;
int today_max;
// forecast
};
void setupFaceWeather(); void setupFaceWeather();
void loopFaceWeather(); void loopFaceWeather();

@ -3,7 +3,13 @@ platform = espressif32
board = lolin32 board = lolin32
framework = arduino framework = arduino
monitor_speed = 115200 monitor_speed = 115200
; https://camo.githubusercontent.com/62eafe3a5c9bf3cdc31d6db740b7e58eaa1a3ab1/687474703a2f2f7777772e6275696c646c6f672e6e65742f626c6f672f77702d636f6e74656e742f75706c6f6164732f323032302f30322f6964655f73732e706e67
; https://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
; https://github.com/espressif/arduino-esp32/tree/master/tools/partitions
; https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/partition-tables.html
board_build.partitions = no_ota.csv
# OTA
;upload_port = 192.168.178.60 ;upload_port = 192.168.178.60
# lolin32 # lolin32
@ -12,7 +18,9 @@ monitor_speed = 115200
# lolin32 lite # lolin32 lite
upload_speed = 115200 upload_speed = 115200
upload_port = /dev/cu.wchusbserial1460 ;upload_port = /dev/cu.wchusbserial1460
upload_port = /dev/cu.wchusbserial1410
lib_deps = lib_deps =
GxEPD2@~1.2.4 GxEPD2@~1.2.4

@ -20,7 +20,6 @@ const char *setting_HeaderKeys[] = {
// execute firmware update url // execute firmware update url
"X-UpdateFirmware"}; "X-UpdateFirmware"};
HTTPClient http;
void requestCloud(); void requestCloud();
bool isCloudSetupComplete(); bool isCloudSetupComplete();
@ -28,6 +27,8 @@ void updateInterval(unsigned long interval);
void setupCloud() void setupCloud()
{ {
HTTPClient http;
Serial.println("setup cloud"); Serial.println("setup cloud");
updateInterval(10); updateInterval(10);
@ -106,6 +107,9 @@ void updateInterval(unsigned long interval)
*/ */
void requestCloud() void requestCloud()
{ {
/*
HTTPClient http;
String config_Url = NVS.getString("cloud.url"); String config_Url = NVS.getString("cloud.url");
Serial.println(config_Url); Serial.println(config_Url);
@ -260,4 +264,5 @@ void requestCloud()
// clean up // clean up
http.end(); http.end();
*/
} }

@ -0,0 +1,93 @@
#include <HTTPClient.h>
#include <SPIFFS.h>
#include "download.h"
HTTPClient http;
bool downloadFile(String url, const char *path)
{
// @note duration time: 200kb = 35sec write to flash
Serial.println("Download file: " + url);
bool hasError = false;
String tmpFile = path;
tmpFile += ".tmp";
http.useHTTP10(true); // http1.1 chunked übertragung funktioniert irgendwie nicht
http.setTimeout(7000);
http.begin(url);
int httpCode = http.GET();
if (httpCode != HTTP_CODE_OK)
{
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode != HTTP_CODE_OK && httpCode).c_str());
hasError = true;
}
else
{
// track duration
long startMills = millis();
// get lenght of document (is -1 when Server sends no Content-Length header)
int len = http.getSize();
// create buffer for read
uint8_t buff[1024] = {0};
// get tcp stream
WiFiClient *stream = http.getStreamPtr();
// persist image
SPIFFS.begin();
File file = SPIFFS.open(tmpFile, FILE_WRITE);
if (!file)
{
Serial.println("Failed to open file for writing");
hasError = true;
}
// read all data from server
while (http.connected() && (len > 0 || len == -1))
{
// get available data size
size_t size = stream->available();
if (size)
{
// read up to xxx byte
int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
// write to storage
if (file)
{
file.write(buff, c);
}
if (len > 0)
{
len -= c;
}
}
delay(1);
}
// done
if (file)
{
file.close();
SPIFFS.remove(path);
SPIFFS.rename(tmpFile, path);
SPIFFS.end();
}
Serial.print("download completed in: ");
Serial.println(millis() - startMills);
}
// clean up
http.end();
return !hasError;
}

@ -1,23 +1,27 @@
#include <HTTPClient.h>
#include <SPIFFS.h>
#include <pngle.h>
#include "faceCalendar.h" #include "faceCalendar.h"
#include "display.h" #include "display.h"
#include "datetime.h" #include "datetime.h"
#include "SPIFFS.h"
#include "pngle.h"
#include "tools.h" #include "tools.h"
#include "image.h"
#include "download.h"
#include <Fonts/FreeMono12pt7b.h> // weekday - month year #include <Fonts/FreeMono12pt7b.h> // weekday - month year
#include <Fonts/FreeSansBold24pt7b.h> // current day #include <Fonts/FreeSansBold24pt7b.h> // current day
void downloadRandomePicture(); void downloadRandomePicture();
void showFaceCalendar();
void display_calender(); void display_calender();
void display_picture(); void display_picture();
void display_time(); void display_time();
void on_draw2(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]); void on_draw2(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]);
using std::uint8_t; const char faceCalendarPicture[] = "/calendarPhoto.png";
// TODO use dynamic display width // TODO use dynamic display width
static constexpr int MAX_WIDTH = 640 - 250; static constexpr int MAX_WIDTH = 640 - 250;
static constexpr int MAX_HEIGHT = 384;
static int16_t curRowDelta[MAX_WIDTH + 1]; static int16_t curRowDelta[MAX_WIDTH + 1];
static int16_t nextRowDelta[MAX_WIDTH + 1]; static int16_t nextRowDelta[MAX_WIDTH + 1];
@ -27,22 +31,20 @@ void setupFaceCalendar()
void loopFaceCalendar() void loopFaceCalendar()
{ {
EVERY_N_SECONDS(300) // TODO update picture every x seconds
{ showFaceCalendar();
Serial.println("TODO download new image"); }
}
void showFaceCalendar()
{
display.setRotation(0); display.setRotation(0);
display.setFullWindow(); display.setFullWindow();
display.firstPage(); display.firstPage();
display.fillScreen(GxEPD_WHITE); display.fillScreen(GxEPD_WHITE);
// draw...
display_picture(); display_picture();
display_calender(); display_calender();
Serial.println("displayFlush");
display.nextPage(); display.nextPage();
} }
@ -50,7 +52,21 @@ void downloadRandomePicture()
{ {
// https://images.unsplash.com/photo-1580886349729-1bd109928600?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjExMDM0OH0&w=640&h=200&fm=png&fit=crop // https://images.unsplash.com/photo-1580886349729-1bd109928600?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjExMDM0OH0&w=640&h=200&fm=png&fit=crop
// https://images.unsplash.com/photo-1580886349729-1bd109928600?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjExMDM0OH0&w=390&h=384&fm=png&fit=crop&colorquant=2 // https://images.unsplash.com/photo-1580886349729-1bd109928600?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjExMDM0OH0&w=390&h=384&fm=png&fit=crop&colorquant=2
// https://images.unsplash.com/photo-1581307385098-a0338263e357?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjExMDM0OH0&w=640&h=384&fm=png&fit=crop&duotone=000000,FFFFFF
// final filter: &w=390&h=384&fm=png&fit=crop&duotone=000000,FFFFFF // final filter: &w=390&h=384&fm=png&fit=crop&duotone=000000,FFFFFF
Serial.println("TODO download new image");
// TODO download json file
String pictureUrl = "https://images.unsplash.com/photo-1582910587039-b4f085805c86?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjExMDM0OH0";
pictureUrl += "&w=390&h=384"; // size
pictureUrl += "&fm=png"; // format
pictureUrl += "&fit=crop"; // crop to needed size
pictureUrl += "&duotone=000000,FFFFFF"; // grayscale to save bytes
downloadFile(pictureUrl, faceCalendarPicture); // /face/calendar/bg.png
Serial.println("TODO download new image ---- done");
} }
void display_calender() void display_calender()
@ -129,7 +145,7 @@ void display_picture()
pngle_t *pngle = pngle_new(); pngle_t *pngle = pngle_new();
pngle_set_draw_callback(pngle, on_draw2); pngle_set_draw_callback(pngle, on_draw2);
File file = SPIFFS.open("/calendarPhoto.png", "r"); File file = SPIFFS.open(faceCalendarPicture, "r");
if (!file) if (!file)
{ {
Serial.println(" file not found"); Serial.println(" file not found");
@ -143,12 +159,14 @@ void display_picture()
} }
file.close(); file.close();
/*
Serial.print(" width: "); Serial.print(" width: ");
Serial.print(pngle_get_width(pngle)); Serial.print(pngle_get_width(pngle));
Serial.print(" height: "); Serial.print(" height: ");
Serial.println(pngle_get_height(pngle)); Serial.println(pngle_get_height(pngle));
Serial.println(" read png done"); Serial.println(" read png done");
*/
pngle_destroy(pngle); pngle_destroy(pngle);
} }

@ -1,11 +1,16 @@
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <HTTPClient.h> #include <SPIFFS.h>
#include "faceWeather.h" #include "faceWeather.h"
#include "faceWeatherIcons.h" #include "faceWeatherIcons.h"
#include "display.h" #include "display.h"
#include "download.h"
#include <Fonts/FreeSansBold24pt7b.h> // current day #include <Fonts/FreeSansBold24pt7b.h> // current day
const char faceWeatherCurrent[] = "/weatherCurrent.json";
const char faceWeatherForecast[] = "/weatherForecast.json";
faceWeatherData weatherData;
// TODO use theme color // TODO use theme color
void display_current(); void display_current();
@ -15,6 +20,27 @@ void setupFaceWeather()
{ {
} }
void updateData()
{
String url;
// http://api.openweathermap.org/data/2.5/weather?id=2766824&APPID=883b3c87223430d6f3a399645f8ba12b&lang=de&cnt=3&units=metric
// http://api.openweathermap.org/data/2.5/forecast?id=2766824&APPID=883b3c87223430d6f3a399645f8ba12b&lang=de
// https://openweathermap.org/current
url = "http://api.openweathermap.org/data/2.5/weather?";
url += "APPID=883b3c87223430d6f3a399645f8ba12b"; // api key
url += "&id=2766824"; // location
url += "&lang=de&units=metric"; // settings
downloadFile(url, faceWeatherCurrent);
// https://openweathermap.org/forecast5
url = "http://api.openweathermap.org/data/2.5/forecast?";
url += "APPID=883b3c87223430d6f3a399645f8ba12b"; // api key
url += "&id=2766824"; // location
url += "&lang=de&cnt=3&units=metric"; // settings
downloadFile(url, faceWeatherForecast);
}
void loopFaceWeather() void loopFaceWeather()
{ {
display.setRotation(0); display.setRotation(0);
@ -24,15 +50,12 @@ void loopFaceWeather()
display.setTextColor(GxEPD_WHITE); display.setTextColor(GxEPD_WHITE);
display.setTextSize(1); display.setTextSize(1);
display_current(); display_current();
display_forecast(); display_forecast();
display.nextPage(); display.nextPage();
} }
void display_current() void display_current()
{ {
// temperature // temperature
@ -42,19 +65,17 @@ void display_current()
display.println(""); display.println("");
// icon // icon
const uint *icon = getIconById("02n", 192); // 192 const uint *icon = getIconById("02n", 192); // 192
if (icon) if (icon)
{ {
display.drawBitmap(272, 30, (uint8_t *)icon + 4, icon[0], icon[1], GxEPD_WHITE); display.drawBitmap(272, 30, (uint8_t *)icon + 4, icon[0], icon[1], GxEPD_WHITE);
} }
// text // text
display.setTextSize(1); display.setTextSize(1);
display.setCursor(400, 300); display.setCursor(400, 300);
//display.println("Ein paar Wolken"); //display.println("Ein paar Wolken");
// high // high
display.setTextSize(1); display.setTextSize(1);
display.setCursor(500, 30); display.setCursor(500, 30);
@ -63,10 +84,8 @@ void display_current()
// low // low
display.setCursor(500, 60); display.setCursor(500, 60);
display.println("-3°"); display.println("-3°");
} }
void display_forecast() void display_forecast()
{ {
const uint *icon; const uint *icon;
@ -79,70 +98,66 @@ void display_forecast()
display.drawLine(420, 250, 420, 384, GxEPD_WHITE); display.drawLine(420, 250, 420, 384, GxEPD_WHITE);
// 210 per block // 210 per block
// day +1 // day +1
icon = getIconById("03d", 96); icon = getIconById("03d", 96);
if (icon) if (icon)
{ {
display.drawBitmap(0 +57, 260, (uint8_t *)icon + 4, icon[0], icon[1], GxEPD_WHITE); display.drawBitmap(0 + 57, 260, (uint8_t *)icon + 4, icon[0], icon[1], GxEPD_WHITE);
} }
// day +2 // day +2
icon = getIconById("09d", 96); icon = getIconById("09d", 96);
if (icon) if (icon)
{ {
display.drawBitmap(210 +57, 260, (uint8_t *)icon + 4, icon[0], icon[1], GxEPD_WHITE); display.drawBitmap(210 + 57, 260, (uint8_t *)icon + 4, icon[0], icon[1], GxEPD_WHITE);
} }
// day +3 // day +3
icon = getIconById("13d", 96); icon = getIconById("13d", 96);
if (icon) if (icon)
{ {
display.drawBitmap(410 +57, 260, (uint8_t *)icon + 4, icon[0], icon[1], GxEPD_WHITE); display.drawBitmap(410 + 57, 260, (uint8_t *)icon + 4, icon[0], icon[1], GxEPD_WHITE);
} }
} }
void loadConfiguration()
/*
bool loadWeatherData(const char *type)
{ {
HTTPClient http; SPIFFS.begin();
String url = "http://api.openweathermap.org/data/2.5/forecast?"; // weather | forecast File file;
url += "id=2766824"; DeserializationError error;
url += "&lang=de";
url += "&cnt=3"; // current weather
url += "&units=metric"; file = SPIFFS.open(faceWeatherCurrent);
url += "&APPID=883b3c87223430d6f3a399645f8ba12b"; StaticJsonDocument<976> docCurrent; // Use arduinojson.org/v6/assistant to compute the capacity.
// "/data/2.5/" + RequestType + "?q=" + City + "," + Country + "&APPID=" + apikey + "&mode=json&units=" + units + "&lang=" + Language; error = deserializeJson(docCurrent, file);
if (error)
//http.begin(client, server, 80, uri);
http.begin(url);
int httpCode = http.GET();
if (httpCode != HTTP_CODE_OK)
{ {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode != HTTP_CODE_OK && httpCode).c_str()); Serial.println(F("Failed to read file, using default configuration"));
} }
else
// TODO Copy values from the JsonDocument to the Config
weatherData.current_temp = 12;
/*
config.port = doc["port"] | 2731;
strlcpy(config.hostname, // <- destination
doc["hostname"] | "example.com", // <- source
sizeof(config.hostname)); // <- destination's capacity
*/
file.close();
// forecast
file = SPIFFS.open(faceWeatherForecast);
StaticJsonDocument<2180> docForecast; // Use arduinojson.org/v6/assistant to compute the capacity.
error = deserializeJson(docForecast, file);
if (error)
{ {
// TODO read... Serial.println(F("Failed to read file, using default configuration"));
DynamicJsonDocument doc(1024 * 35);
DeserializationError error = deserializeJson(doc, http.getStream());
if (error)
{
Serial.print(F("deserializeJson() failed with code "));
Serial.println(error.c_str());
return false;
}
JsonObject root = doc.as<JsonObject>();
} }
http.end(); // TODO get values
}
file.close();
*/ SPIFFS.end();
}

@ -4,17 +4,17 @@
#include "wlan.h" #include "wlan.h"
#include "display.h" #include "display.h"
#include "settings.h" #include "settings.h"
#include "cloud.h" //#include "cloud.h"
#include "datetime.h"
#include "playlist.h"
#include "app.h" #include "app.h"
#include "imagePNG.h" #include "imagePNG.h"
#include "imageWBMP.h" #include "imageWBMP.h"
void gotoDeepSleep(); void gotoDeepSleep();
String getWakeupReason(); String getWakeupReason();
void setup() void setup()
{ {
// put your setup code here, to run once: // put your setup code here, to run once:
@ -26,18 +26,21 @@ void setup()
Serial.println(); Serial.println();
setupDisplay(); setupDisplay();
//setupImagePNG();
//setupImageWBMP();
setupSettings(); setupSettings();
setupDevice(); setupDevice();
setupWlan(); setupWlan();
if (wlan_isConnected()) if (wlan_isConnected())
{ {
setupCloud(); if (!setupDateTime())
{
// re-try
setupDateTime();
}
setupPlaylist();
//setupCloud();
} }
setupApp(); setupApp();
@ -52,8 +55,9 @@ void loop()
if (wlan_isConnected()) if (wlan_isConnected())
{ {
loopCloud(); loopPlaylist();
//loopCloud();
} }
loopDevice(); //loopDevice();
} }
Loading…
Cancel
Save