diff --git a/include/imagePNG.h b/include/imagePNG.h index 3d55cb1..552f9f2 100644 --- a/include/imagePNG.h +++ b/include/imagePNG.h @@ -1,6 +1,12 @@ #ifndef IMAGE_PNG_H #define IMAGE_PNG_H +// @see http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html +const char ImageHeaderPNG[] = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"; + void setupImagePNG(); +void pngOpenFramebuffer(); +void pngWriteFramebuffer(int offset, uint8_t bitmap[], int c); +void pngFlushFramebuffer(); #endif \ No newline at end of file diff --git a/include/imageWBMP.h b/include/imageWBMP.h index 14d66df..d3fa54a 100644 --- a/include/imageWBMP.h +++ b/include/imageWBMP.h @@ -3,6 +3,10 @@ #include +// @see https://en.wikipedia.org/wiki/Wireless_Application_Protocol_Bitmap_Format +// 0 0 133 0 131 0 +const char ImageHeaderWBMP[] = "\x0\x0\x85\x0\x83\x0"; + void setupImageWBMP(); void wbmpOpenFramebuffer(); diff --git a/src/cloud.cpp b/src/cloud.cpp index 5299e55..8c74db7 100644 --- a/src/cloud.cpp +++ b/src/cloud.cpp @@ -4,17 +4,11 @@ #include #include "settings.h" -#include "display.h" -#include "imageWBMP.h" #include "device.h" +#include "display.h" -// TODO SMART SIGN CONFIG ======== -//#define config_PullServer "http://paperdash.sonic.da-tom.com/gateway.php/" // pull server address -String config_UUID = "22805938-2280-8022-3822-385980225980"; // TODO - -//#define config_PullServer = NVS.getString("cloud_server"); -//String config_UUID = NVS.getString("cloud_server"); -// SMART SIGN CONFIG ======== +#include "imageWBMP.h" +#include "imagePNG.h" unsigned long requestInterval = 1000; // 1 sec unsigned long previousTime = 0; @@ -22,9 +16,9 @@ unsigned long previousTime = 0; // runtime data const char *setting_HeaderKeys[] = { // update deep sleep interval - "DeepSleepInterval", + "X-DeepSleepInterval", // execute firmware update url - "UpdateFirmware"}; + "X-UpdateFirmware"}; HTTPClient http; @@ -44,6 +38,13 @@ void setupCloud() http.setTimeout(7000); http.collectHeaders(setting_HeaderKeys, sizeof(setting_HeaderKeys) / sizeof(char *)); + if (isCloudSetupComplete()) + { + //config_Url = NVS.getString("cloud_server"); // + "/" + NVS.getString("cloud_uuid"); + //config_Url = "http://paperdash.sonic.da-tom.com/api/device/22805938-2280-8022-3822-385980225980/image.png"; + Serial.println(" cloud setup complete"); + } + Serial.println("setup cloud - done"); } @@ -70,13 +71,12 @@ void loopCloud() requestCloud(); } } - } } bool isCloudSetupComplete() { - return NVS.getString("cloud_server") != "" && config_UUID != ""; + return NVS.getString("cloud_server") != "" && NVS.getString("cloud_uuid") != ""; } /** @@ -92,7 +92,6 @@ void updateInterval(unsigned long interval) Serial.println(" set deep sleep interval from: " + String(deviceGetSleepInterval()) + " to " + interval); Serial.println("###### config update"); - // active wait state requestInterval = interval * 1000; @@ -107,12 +106,10 @@ void updateInterval(unsigned long interval) */ void requestCloud() { + String config_Url = NVS.getString("cloud_server"); - //String pullUrl = String(config_PullServer) + "/" + config_UUID; // + "?deep-sleep=" + String(config_DeepSleepInterval) + "&wakeup=" + getWakeupReason(); - String pullUrl = NVS.getString("cloud_server") + "/" + config_UUID; // + "?deep-sleep=" + String(config_DeepSleepInterval) + "&wakeup=" + getWakeupReason(); - - Serial.println(pullUrl); - http.begin(pullUrl); + Serial.println(config_Url); + http.begin(config_Url); int httpCode = http.GET(); if (httpCode != HTTP_CODE_OK && httpCode != HTTP_CODE_NOT_MODIFIED) { @@ -121,7 +118,7 @@ void requestCloud() else { // update poll interval - String DeepSleepInterval = http.header("DeepSleepInterval"); + String DeepSleepInterval = http.header("X-DeepSleepInterval"); if (false && DeepSleepInterval.toInt() == 0) { // disable deep sleep @@ -144,6 +141,9 @@ void requestCloud() { // update image + // track duration + long startMills = millis(); + // get lenght of document (is -1 when Server sends no Content-Length header) int len = http.getSize(); @@ -154,12 +154,10 @@ void requestCloud() WiFiClient *stream = http.getStreamPtr(); // reset image buffer - //memset(displayImageBuffer, 0, sizeof(displayImageBuffer)); - int imageBufferOffset = 0; - wbmpOpenFramebuffer(); + size_t imageFormat = 0; // persist image to display - File file = SPIFFS.open("/currentImage.bin", FILE_WRITE); + File file = SPIFFS.open("/currentImage.tmp", FILE_WRITE); if (!file) { Serial.println("Failed to open file for writing"); @@ -182,9 +180,48 @@ void requestCloud() file.write(buff, c); } + // initial detect format + if (imageFormat == 0) + { + if (memcmp(buff, ImageHeaderWBMP, sizeof(ImageHeaderWBMP) - 1) == 0) + { + Serial.println(" image format: WBMP"); + imageFormat = 2; + + wbmpOpenFramebuffer(); + } + else if (memcmp(buff, ImageHeaderPNG, sizeof(ImageHeaderPNG) - 1) == 0) + { + Serial.println(" image format: PNG"); + imageFormat = 3; + + pngOpenFramebuffer(); + } + else + { + imageFormat = 1; + Serial.println(" unkown image format. first header are:"); + Serial.println(buff[0]); + Serial.println(buff[1]); + Serial.println(buff[2]); + Serial.println(buff[3]); + Serial.println(buff[4]); + Serial.println(buff[5]); + } + } + // write display frame - wbmpWriteFramebuffer(imageBufferOffset, buff, c); - imageBufferOffset += c; + switch (imageFormat) + { + // WBMP + case 2: + wbmpWriteFramebuffer(0, buff, c); + break; + // PNG + case 3: + pngWriteFramebuffer(0, buff, c); + break; + } if (len > 0) { @@ -195,13 +232,29 @@ void requestCloud() delay(1); } + // done if (file) { file.close(); + SPIFFS.remove("/currentImage.bin"); + SPIFFS.rename("/currentImage.tmp", "/currentImage.bin"); } - // done - wbmpFlushFramebuffer(); + // update display + switch (imageFormat) + { + // WBMP + case 2: + wbmpFlushFramebuffer(); + break; + // PNG + case 3: + pngFlushFramebuffer(); + break; + } + + Serial.print("update completed in: "); + Serial.println(millis() - startMills); } } } \ No newline at end of file diff --git a/src/imagePNG.cpp b/src/imagePNG.cpp index 23dfc72..42b3d08 100644 --- a/src/imagePNG.cpp +++ b/src/imagePNG.cpp @@ -4,11 +4,41 @@ #include "SPIFFS.h" #include "display.h" +pngle_t *pngle; void on_draw(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]); void setupImagePNG() { + Serial.println("setupPNG"); + + Serial.println("setupPNG done"); +} + +void pngOpenFramebuffer() +{ + //Serial.println("pngOpenFramebuffer"); + displayOpen(); + + pngle = pngle_new(); + pngle_set_draw_callback(pngle, on_draw); +} + +void pngWriteFramebuffer(int offset, uint8_t bitmap[], int c) +{ + int fed = pngle_feed(pngle, bitmap, c); + if (fed < 0) + { + Serial.println(pngle_error(pngle)); + } +} + +void pngFlushFramebuffer() +{ + //Serial.println("pngFlushFramebuffer"); + pngle_destroy(pngle); + displayFlush(); +/* SPIFFS.begin(); displayOpen(); @@ -45,14 +75,55 @@ void setupImagePNG() pngle_destroy(pngle); displayFlush(); + */ } +/* +void setupImagePNG__demo() +{ + SPIFFS.begin(); + displayOpen(); + + pngle_t *pngle = pngle_new(); + pngle_set_draw_callback(pngle, on_draw); + + File file = SPIFFS.open("/blackPNG.png", "r"); + if (!file) + { + Serial.println(" file not found"); + } + + // get filesize + long size = file.size(); + + // read contents of the file into the vector + char *buffer = (char *)malloc((unsigned long)size); + if (!buffer) + { + file.close(); + Serial.println(" allow failedd"); + } + file.readBytes(buffer, (size_t)size); + file.close(); + Serial.println(" read png"); + int ret = pngle_feed(pngle, buffer, size); + + //Serial.println(" return: " + ret); + //Serial.println(" width: " + pngle_get_width(pngle)); + //Serial.println(" height: " + pngle_get_height(pngle)); + + Serial.println(" read png done"); + pngle_destroy(pngle); + + displayFlush(); +} +*/ void on_draw(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]) { uint8_t r = rgba[0]; // 0 - 255 - uint8_t g = rgba[1]; // 0 - 255 - uint8_t b = rgba[2]; // 0 - 255 + //uint8_t g = rgba[1]; // 0 - 255 + //uint8_t b = rgba[2]; // 0 - 255 uint8_t a = rgba[3]; // 0: fully transparent, 255: fully opaque if (a) @@ -65,5 +136,4 @@ void on_draw(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uin displayWritePixel(x, y, r); } -} - +} \ No newline at end of file diff --git a/src/imageWBMP.cpp b/src/imageWBMP.cpp index 589780b..3e756d0 100644 --- a/src/imageWBMP.cpp +++ b/src/imageWBMP.cpp @@ -2,30 +2,39 @@ #include "display.h" uint8_t _buffer[(GxEPD2_750::WIDTH / 8) * GxEPD2_750::HEIGHT]; - +size_t _bufferOffset = 0; void setupImageWBMP() { Serial.println("setupWBMP"); - Serial.println("setupWBMP done"); } void wbmpOpenFramebuffer() { - Serial.println("wbmpOpenFramebuffer"); + //Serial.println("wbmpOpenFramebuffer"); displayOpen(); memset(_buffer, 0, sizeof(_buffer)); + _bufferOffset = 0; } - // TODO do it better :-) void wbmpWriteFramebuffer(int offset, uint8_t bitmap[], int c) { + // skip header... for (int i = 0; i < c; i++) { - _buffer[offset + i] = bitmap[i]; + //_buffer[offset + i] = bitmap[i]; + + if (_bufferOffset == 0) + { + // skip header + i = 5; + } + + _buffer[_bufferOffset] = bitmap[i]; + _bufferOffset++; } /* @@ -41,10 +50,9 @@ void wbmpWriteFramebuffer(int offset, uint8_t bitmap[], int c) */ } - void wbmpFlushFramebuffer() { - Serial.println("wbmpFlushFramebuffer"); + //Serial.println("wbmpFlushFramebuffer"); displayWriteFramebuffer(_buffer); displayFlush(); } \ No newline at end of file