GxEPD2_WiFi_Example.ino 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. // GxEPD2_WiFi_Example : Display Library example for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
  2. // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
  3. //
  4. // Display Library based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
  5. //
  6. // Author: Jean-Marc Zingg
  7. //
  8. // Version: see library.properties
  9. //
  10. // Library: https://github.com/ZinggJM/GxEPD2
  11. // Supporting Arduino Forum Topics:
  12. // Waveshare e-paper displays with SPI: http://forum.arduino.cc/index.php?topic=487007.0
  13. // Good Dispay ePaper for Arduino : https://forum.arduino.cc/index.php?topic=436411.0
  14. // mapping suggestion from Waveshare SPI e-Paper to Wemos D1 mini
  15. // BUSY -> D2, RST -> D4, DC -> D3, CS -> D8, CLK -> D5, DIN -> D7, GND -> GND, 3.3V -> 3.3V
  16. // mapping suggestion from Waveshare SPI e-Paper to generic ESP8266
  17. // BUSY -> GPIO4, RST -> GPIO2, DC -> GPIO0, CS -> GPIO15, CLK -> GPIO14, DIN -> GPIO13, GND -> GND, 3.3V -> 3.3V
  18. // mapping of Waveshare e-Paper ESP8266 Driver Board
  19. // BUSY -> GPIO16, RST -> GPIO5, DC -> GPIO4, CS -> GPIO15, CLK -> GPIO14, DIN -> GPIO13, GND -> GND, 3.3V -> 3.3V
  20. // mapping suggestion for ESP32, e.g. LOLIN32, see .../variants/.../pins_arduino.h for your board
  21. // NOTE: there are variants with different pins for SPI ! CHECK SPI PINS OF YOUR BOARD
  22. // BUSY -> 4, RST -> 16, DC -> 17, CS -> SS(5), CLK -> SCK(18), DIN -> MOSI(23), GND -> GND, 3.3V -> 3.3V
  23. // new mapping suggestion for STM32F1, e.g. STM32F103C8T6 "BluePill"
  24. // BUSY -> A1, RST -> A2, DC -> A3, CS-> A4, CLK -> A5, DIN -> A7
  25. // mapping suggestion for AVR, UNO, NANO etc.
  26. // BUSY -> 7, RST -> 9, DC -> 8, CS-> 10, CLK -> 13, DIN -> 11
  27. //
  28. #include <GxEPD2_BW.h>
  29. #include <GxEPD2_3C.h>
  30. #define EPD_CS SS
  31. #if defined (ESP8266)
  32. // select one and adapt to your mapping, can use full buffer size (full HEIGHT)
  33. //GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  34. //GxEPD2_BW<GxEPD2_213, GxEPD2_213::HEIGHT> display(GxEPD2_213(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  35. //GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  36. //GxEPD2_BW<GxEPD2_270, GxEPD2_270::HEIGHT> display(GxEPD2_270(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  37. //GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  38. // can use only half buffer size
  39. //GxEPD2_BW < GxEPD2_583, GxEPD2_583::HEIGHT / 2 > display(GxEPD2_583(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  40. //GxEPD2_BW < GxEPD2_750, GxEPD2_750::HEIGHT / 2 > display(GxEPD2_750(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  41. // 3-color e-papers
  42. //GxEPD2_3C<GxEPD2_154c, GxEPD2_154c::HEIGHT> display(GxEPD2_154c(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  43. //GxEPD2_3C<GxEPD2_213c, GxEPD2_213c::HEIGHT> display(GxEPD2_213c(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  44. //GxEPD2_3C<GxEPD2_290c, GxEPD2_290c::HEIGHT> display(GxEPD2_290c(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  45. //GxEPD2_3C<GxEPD2_270c, GxEPD2_270c::HEIGHT> display(GxEPD2_270c(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  46. // can use only half buffer size
  47. //GxEPD2_3C<GxEPD2_420c, GxEPD2_420c::HEIGHT / 2> display(GxEPD2_420c(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  48. // can use only quarter buffer size
  49. //GxEPD2_3C<GxEPD2_583c, GxEPD2_583c::HEIGHT / 4> display(GxEPD2_583c(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  50. //GxEPD2_3C<GxEPD2_750c, GxEPD2_750c::HEIGHT / 4> display(GxEPD2_750c(/*CS=D8*/ EPD_CS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  51. // ***** for mapping of Waveshare e-Paper ESP8266 Driver Board *****
  52. // select one , can use full buffer size (full HEIGHT)
  53. //GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  54. //GxEPD2_BW<GxEPD2_213, GxEPD2_213::HEIGHT> display(GxEPD2_213(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  55. //GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  56. //GxEPD2_BW<GxEPD2_270, GxEPD2_270::HEIGHT> display(GxEPD2_270(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  57. //GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  58. // can use only half buffer size
  59. //GxEPD2_BW < GxEPD2_583, GxEPD2_583::HEIGHT / 2 > display(GxEPD2_583(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  60. //GxEPD2_BW < GxEPD2_750, GxEPD2_750::HEIGHT / 2 > display(GxEPD2_750(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  61. // 3-color e-papers
  62. //GxEPD2_3C<GxEPD2_154c, GxEPD2_154c::HEIGHT> display(GxEPD2_154c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  63. //GxEPD2_3C<GxEPD2_213c, GxEPD2_213c::HEIGHT> display(GxEPD2_213c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  64. //GxEPD2_3C<GxEPD2_290c, GxEPD2_290c::HEIGHT> display(GxEPD2_290c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  65. //GxEPD2_3C<GxEPD2_270c, GxEPD2_270c::HEIGHT> display(GxEPD2_270c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  66. // can use only half buffer size
  67. //GxEPD2_3C<GxEPD2_420c, GxEPD2_420c::HEIGHT / 2> display(GxEPD2_420c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  68. // can use only quarter buffer size
  69. //GxEPD2_3C<GxEPD2_583c, GxEPD2_583c::HEIGHT / 4> display(GxEPD2_583c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  70. //GxEPD2_3C<GxEPD2_750c, GxEPD2_750c::HEIGHT / 4> display(GxEPD2_750c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
  71. #endif
  72. #if defined(ESP32)
  73. // select one and adapt to your mapping, can use full buffer size (full HEIGHT)
  74. //GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=5*/ EPD_CS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  75. //GxEPD2_BW<GxEPD2_213, GxEPD2_213::HEIGHT> display(GxEPD2_213(/*CS=5*/ EPD_CS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  76. //GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/*CS=5*/ EPD_CS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  77. //GxEPD2_BW<GxEPD2_270, GxEPD2_270::HEIGHT> display(GxEPD2_270(/*CS=5*/ EPD_CS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  78. //GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ EPD_CS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  79. //GxEPD2_BW<GxEPD2_750, GxEPD2_750::HEIGHT> display(GxEPD2_750(/*CS=5*/ EPD_CS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  80. // 3-color e-papers
  81. //GxEPD2_3C<GxEPD2_154c, GxEPD2_154c::HEIGHT> display(GxEPD2_154c(/*CS=5*/ EPD_CS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  82. //GxEPD2_3C<GxEPD2_213c, GxEPD2_213c::HEIGHT> display(GxEPD2_213c(/*CS=5*/ EPD_CS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  83. //GxEPD2_3C<GxEPD2_290c, GxEPD2_290c::HEIGHT> display(GxEPD2_290c(/*CS=5*/ EPD_CS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  84. //GxEPD2_3C<GxEPD2_270c, GxEPD2_270c::HEIGHT> display(GxEPD2_270c(/*CS=5*/ EPD_CS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  85. //GxEPD2_3C<GxEPD2_420c, GxEPD2_420c::HEIGHT> display(GxEPD2_420c(/*CS=5*/ EPD_CS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  86. //GxEPD2_3C<GxEPD2_750c, GxEPD2_750c::HEIGHT> display(GxEPD2_750c(/*CS=5*/ EPD_CS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  87. #endif
  88. #if defined(_BOARD_GENERIC_STM32F103C_H_)
  89. #define MAX_DISPAY_BUFFER_SIZE (400 * 300) // ~5k is a good compromise
  90. #define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPAY_BUFFER_SIZE / 8 / EPD::WIDTH ? EPD::HEIGHT : MAX_DISPAY_BUFFER_SIZE / 8 / EPD::WIDTH)
  91. // select one and adapt to your mapping
  92. //GxEPD2_BW<GxEPD2_154, MAX_HEIGHT(GxEPD2_154)> display(GxEPD2_154(/*CS=4*/ EPD_CS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
  93. //GxEPD2_BW<GxEPD2_213, MAX_HEIGHT(GxEPD2_213)> display(GxEPD2_213(/*CS=4*/ EPD_CS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
  94. //GxEPD2_BW<GxEPD2_290, MAX_HEIGHT(GxEPD2_290)> display(GxEPD2_290(/*CS=4*/ EPD_CS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
  95. //GxEPD2_BW<GxEPD2_270, MAX_HEIGHT(GxEPD2_270)> display(GxEPD2_270(/*CS=4*/ EPD_CS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
  96. //GxEPD2_BW<GxEPD2_420, MAX_HEIGHT(GxEPD2_420)> display(GxEPD2_420(/*CS=4*/ EPD_CS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
  97. //GxEPD2_BW<GxEPD2_750, MAX_HEIGHT(GxEPD2_750)> display(GxEPD2_750(/*CS=4*/ EPD_CS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
  98. // 3-color e-papers
  99. //GxEPD2_3C<GxEPD2_154c, MAX_HEIGHT(GxEPD2_154c)> display(GxEPD2_154c(/*CS=4*/ EPD_CS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
  100. //GxEPD2_3C<GxEPD2_213c, MAX_HEIGHT(GxEPD2_213c)> display(GxEPD2_213c(/*CS=4*/ EPD_CS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
  101. //GxEPD2_3C<GxEPD2_290c, MAX_HEIGHT(GxEPD2_290c)> display(GxEPD2_290c(/*CS=4*/ EPD_CS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
  102. //GxEPD2_3C<GxEPD2_270c, MAX_HEIGHT(GxEPD2_270c)> display(GxEPD2_270c(/*CS=4*/ EPD_CS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
  103. //GxEPD2_3C<GxEPD2_420c, MAX_HEIGHT(GxEPD2_420c)> display(GxEPD2_420c(/*CS=4*/ EPD_CS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
  104. //GxEPD2_3C<GxEPD2_750c, MAX_HEIGHT(GxEPD2_750c)> display(GxEPD2_750c(/*CS=4*/ EPD_CS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
  105. #endif
  106. #if defined(__AVR)
  107. #define MAX_DISPAY_BUFFER_SIZE 1000 // half of available RAM as a compromise
  108. #define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPAY_BUFFER_SIZE / 8 / EPD::WIDTH ? EPD::HEIGHT : MAX_DISPAY_BUFFER_SIZE / 8 / EPD::WIDTH)
  109. // select one and adapt to your mapping
  110. //GxEPD2_BW<GxEPD2_154, MAX_HEIGHT(GxEPD2_154)> display(GxEPD2_154(/*CS=10*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
  111. //GxEPD2_BW<GxEPD2_213, MAX_HEIGHT(GxEPD2_213)> display(GxEPD2_213(/*CS=10*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
  112. //GxEPD2_BW<GxEPD2_290, MAX_HEIGHT(GxEPD2_290)> display(GxEPD2_290(/*CS=10*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
  113. //GxEPD2_BW<GxEPD2_270, MAX_HEIGHT(GxEPD2_270)> display(GxEPD2_270(/*CS=10*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
  114. //GxEPD2_BW<GxEPD2_420, MAX_HEIGHT(GxEPD2_420)> display(GxEPD2_420(/*CS=10*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
  115. //GxEPD2_BW<GxEPD2_750, MAX_HEIGHT(GxEPD2_750)> display(GxEPD2_750(/*CS=10*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
  116. // 3-color e-papers
  117. //GxEPD2_3C<GxEPD2_154c, MAX_HEIGHT(GxEPD2_154c)> display(GxEPD2_154c(/*CS=10*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
  118. //GxEPD2_3C<GxEPD2_213c, MAX_HEIGHT(GxEPD2_213c)> display(GxEPD2_213c(/*CS=10*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
  119. //GxEPD2_3C<GxEPD2_290c, MAX_HEIGHT(GxEPD2_290c)> display(GxEPD2_290c(/*CS=10*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
  120. //GxEPD2_3C<GxEPD2_270c, MAX_HEIGHT(GxEPD2_270c)> display(GxEPD2_270c(/*CS=10*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
  121. //GxEPD2_3C<GxEPD2_420c, MAX_HEIGHT(GxEPD2_420c)> display(GxEPD2_420c(/*CS=10*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
  122. //GxEPD2_3C<GxEPD2_750c, MAX_HEIGHT(GxEPD2_750c)> display(GxEPD2_750c(/*CS=10*/ EPD_CS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
  123. #endif
  124. #include <ESP8266WiFi.h>
  125. #include <WiFiClient.h>
  126. #include <WiFiClientSecure.h>
  127. const char* ssid = "........";
  128. const char* password = "........";
  129. const int httpPort = 80;
  130. const int httpsPort = 443;
  131. const char* fp_api_github_com = "35 85 74 EF 67 35 A7 CE 40 69 50 F3 C0 F6 80 CF 80 3B 2E 19";
  132. const char* fp_github_com = "ca 06 f5 6b 25 8b 7a 0d 4f 2b 05 47 09 39 47 86 51 15 19 84";
  133. const char* fp_rawcontent = "cc aa 48 48 66 46 0e 91 53 2c 9c 7c 23 2a b1 74 4d 29 9d 33";
  134. const char* host_rawcontent = "raw.githubusercontent.com";
  135. const char* path_rawcontent = "/ZinggJM/GxEPD2/master/extras/bitmaps/";
  136. void setup()
  137. {
  138. Serial.begin(115200);
  139. Serial.println();
  140. Serial.println("GxEPD2_WiFi_Example");
  141. display.init();
  142. #ifdef RE_INIT_NEEDED
  143. WiFi.persistent(true);
  144. WiFi.mode(WIFI_STA); // switch off AP
  145. WiFi.setAutoConnect(true);
  146. WiFi.setAutoReconnect(true);
  147. WiFi.disconnect();
  148. #endif
  149. if (!WiFi.getAutoConnect() || ( WiFi.getMode() != WIFI_STA) || ((WiFi.SSID() != ssid) && String(ssid) != "........"))
  150. {
  151. Serial.println();
  152. Serial.print("WiFi.getAutoConnect()=");
  153. Serial.println(WiFi.getAutoConnect());
  154. Serial.print("WiFi.SSID()=");
  155. Serial.println(WiFi.SSID());
  156. WiFi.mode(WIFI_STA); // switch off AP
  157. Serial.print("Connecting to ");
  158. Serial.println(ssid);
  159. WiFi.begin(ssid, password);
  160. }
  161. int ConnectTimeout = 30; // 15 seconds
  162. while (WiFi.status() != WL_CONNECTED)
  163. {
  164. delay(500);
  165. Serial.print(".");
  166. Serial.print(WiFi.status());
  167. if (--ConnectTimeout <= 0)
  168. {
  169. Serial.println();
  170. Serial.println("WiFi connect timeout");
  171. return;
  172. }
  173. }
  174. Serial.println();
  175. Serial.println("WiFi connected");
  176. // Print the IP address
  177. Serial.println(WiFi.localIP());
  178. showBitmapsFromWiFi();
  179. }
  180. void loop(void)
  181. {
  182. }
  183. void showBitmapsFromWiFi()
  184. {
  185. showBitmapFrom_HTTP("www.squix.org", "/blog/wunderground/", "chanceflurries.bmp", 0, 0);
  186. delay(2000);
  187. //return;
  188. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "logo200x200.bmp", fp_rawcontent, 0, 0);
  189. delay(2000);
  190. //return;
  191. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "first200x200.bmp", fp_rawcontent, 0, 0);
  192. delay(2000);
  193. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "second200x200.bmp", fp_rawcontent, 0, 0);
  194. delay(2000);
  195. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "third200x200.bmp", fp_rawcontent, 0, 0);
  196. delay(2000);
  197. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "fourth200x200.bmp", fp_rawcontent, 0, 0);
  198. delay(2000);
  199. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "fifth200x200.bmp", fp_rawcontent, 0, 0);
  200. delay(2000);
  201. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "sixth200x200.bmp", fp_rawcontent, 0, 0);
  202. delay(2000);
  203. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "seventh200x200.bmp", fp_rawcontent, 0, 0);
  204. delay(2000);
  205. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "eighth200x200.bmp", fp_rawcontent, 0, 0);
  206. delay(2000);
  207. }
  208. static const uint16_t max_row_width = 640; // for up to 7.5" display
  209. uint8_t row_buffer[3 * max_row_width]; // buffer for at least one row (of up to 24bit BMP)
  210. void showBitmapFrom_HTTP(const char* host, const char* path, const char* filename, uint8_t x, uint8_t y)
  211. {
  212. WiFiClient client;
  213. bool valid = false; // valid format to be handled
  214. bool flip = true; // bitmap is stored bottom-to-top
  215. uint32_t startTime = millis();
  216. if ((x >= display.width()) || (y >= display.height())) return;
  217. Serial.print("connecting to ");
  218. Serial.println(host);
  219. if (!client.connect(host, httpPort))
  220. {
  221. Serial.println("connection failed");
  222. return;
  223. }
  224. Serial.print("requesting URL: ");
  225. Serial.println(String("http://") + host + path + filename);
  226. client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
  227. "Host: " + host + "\r\n" +
  228. "User-Agent: GxEPD2_Spiffs_Loader\r\n" +
  229. "Connection: close\r\n\r\n");
  230. Serial.println("request sent");
  231. bool ok = false;
  232. while (client.connected())
  233. {
  234. String line = client.readStringUntil('\n');
  235. if (!ok)
  236. {
  237. ok = line.startsWith("HTTP/1.1 200 OK");
  238. if (ok) Serial.println(line);
  239. //if (!ok) Serial.println(line);
  240. }
  241. if (!ok) Serial.println(line);
  242. //Serial.println(line);
  243. if (line == "\r")
  244. {
  245. Serial.println("headers received");
  246. break;
  247. }
  248. }
  249. if (!ok) return;
  250. // Parse BMP header
  251. if (read16(client) == 0x4D42) // BMP signature
  252. {
  253. uint32_t fileSize = read32(client);
  254. uint32_t creatorBytes = read32(client);
  255. uint32_t imageOffset = read32(client); // Start of image data
  256. uint32_t headerSize = read32(client);
  257. uint32_t width = read32(client);
  258. uint32_t height = read32(client);
  259. uint16_t planes = read16(client);
  260. uint16_t depth = read16(client); // bits per pixel
  261. uint32_t format = read32(client);
  262. uint32_t bytes_read = 7 * 4 + 3 * 2; // read so far
  263. if ((planes == 1) && (format == 0)) // uncompressed is handled
  264. {
  265. Serial.print("File size: "); Serial.println(fileSize);
  266. Serial.print("Image Offset: "); Serial.println(imageOffset);
  267. Serial.print("Header size: "); Serial.println(headerSize);
  268. Serial.print("Bit Depth: "); Serial.println(depth);
  269. Serial.print("Image size: ");
  270. Serial.print(width);
  271. Serial.print('x');
  272. Serial.println(height);
  273. // BMP rows are padded (if needed) to 4-byte boundary
  274. uint32_t rowSize = (width * depth / 8 + 3) & ~3;
  275. if (height < 0)
  276. {
  277. height = -height;
  278. flip = false;
  279. }
  280. uint16_t w = width;
  281. uint16_t h = height;
  282. if ((x + w - 1) >= display.width()) w = display.width() - x;
  283. if ((y + h - 1) >= display.height()) h = display.height() - y;
  284. uint32_t skip = (flip ? (imageOffset + (height - h) * rowSize) : imageOffset) - bytes_read;
  285. //Serial.print("skip "); Serial.println(skip);
  286. while ((skip > 0) && client.connected())
  287. {
  288. client.read(); bytes_read++; skip--;
  289. }
  290. if (((depth == 1) || (depth == 24)) && (rowSize < sizeof(row_buffer))) // handle with direct drawing
  291. {
  292. valid = true;
  293. display.writeScreenBuffer();
  294. for (uint16_t row = 0; row < h; row++) // for each line
  295. {
  296. delay(1); // yield() to avoid WDT
  297. uint32_t got = client.read(row_buffer, rowSize);
  298. while ((got < rowSize) && client.connected())
  299. {
  300. delay(1); // yield() to avoid WDT
  301. got += client.read(row_buffer + got, rowSize - got);
  302. }
  303. bytes_read += got;
  304. if (depth == 24)
  305. {
  306. uint8_t out_byte = 0;
  307. uint32_t out_idx = 0;
  308. uint32_t in_idx = 0;
  309. for (uint16_t col = 0; col < w; col++)
  310. {
  311. uint16_t b = row_buffer[in_idx++];
  312. uint16_t g = row_buffer[in_idx++];
  313. uint16_t r = row_buffer[in_idx++];
  314. if ((r + g + b) / 3 > 0xFF / 2)
  315. {
  316. out_byte |= 0x80 >> col % 8;
  317. }
  318. if (7 == col % 8)
  319. {
  320. row_buffer[out_idx++] = out_byte;
  321. out_byte = 0;
  322. }
  323. }
  324. }
  325. uint16_t y = flip ? h - row - 1 : row;
  326. display.writeImage(row_buffer, 0, y, w, 1);
  327. }
  328. display.refresh();
  329. }
  330. }
  331. Serial.print("bytes read "); Serial.println(bytes_read);
  332. //Serial.print("available "); Serial.println(client.available());
  333. }
  334. if (valid)
  335. {
  336. Serial.print("loaded in ");
  337. Serial.print(millis() - startTime);
  338. Serial.println(" ms");
  339. }
  340. else
  341. {
  342. Serial.println("bitmap format not handled.");
  343. }
  344. }
  345. void showBitmapFrom_HTTPS(const char* host, const char* path, const char* filename, const char* fingerprint, uint8_t x, uint8_t y)
  346. {
  347. // Use WiFiClientSecure class to create TLS connection
  348. WiFiClientSecure client;
  349. bool valid = false; // valid format to be handled
  350. bool flip = true; // bitmap is stored bottom-to-top
  351. uint32_t startTime = millis();
  352. if ((x >= display.width()) || (y >= display.height())) return;
  353. Serial.print("connecting to ");
  354. Serial.println(host);
  355. if (!client.connect(host, httpsPort))
  356. {
  357. Serial.println("connection failed");
  358. return;
  359. }
  360. if (fingerprint)
  361. {
  362. if (client.verify(fingerprint, host))
  363. {
  364. Serial.println("certificate matches");
  365. }
  366. else
  367. {
  368. Serial.println("certificate doesn't match");
  369. return;
  370. }
  371. }
  372. Serial.print("requesting URL: ");
  373. Serial.println(String("https://") + host + path + filename);
  374. client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
  375. "Host: " + host + "\r\n" +
  376. "User-Agent: GxEPD2_Spiffs_Loader\r\n" +
  377. "Connection: close\r\n\r\n");
  378. Serial.println("request sent");
  379. bool ok = false;
  380. while (client.connected())
  381. {
  382. String line = client.readStringUntil('\n');
  383. if (!ok)
  384. {
  385. ok = line.startsWith("HTTP/1.1 200 OK");
  386. if (ok) Serial.println(line);
  387. //if (!ok) Serial.println(line);
  388. }
  389. if (!ok) Serial.println(line);
  390. //Serial.println(line);
  391. if (line == "\r")
  392. {
  393. Serial.println("headers received");
  394. break;
  395. }
  396. }
  397. if (!ok) return;
  398. // Parse BMP header
  399. if (read16(client) == 0x4D42) // BMP signature
  400. {
  401. uint32_t fileSize = read32(client);
  402. uint32_t creatorBytes = read32(client);
  403. uint32_t imageOffset = read32(client); // Start of image data
  404. uint32_t headerSize = read32(client);
  405. uint32_t width = read32(client);
  406. uint32_t height = read32(client);
  407. uint16_t planes = read16(client);
  408. uint16_t depth = read16(client); // bits per pixel
  409. uint32_t format = read32(client);
  410. uint32_t bytes_read = 7 * 4 + 3 * 2; // read so far
  411. if ((planes == 1) && (format == 0)) // uncompressed is handled
  412. {
  413. Serial.print("File size: "); Serial.println(fileSize);
  414. Serial.print("Image Offset: "); Serial.println(imageOffset);
  415. Serial.print("Header size: "); Serial.println(headerSize);
  416. Serial.print("Bit Depth: "); Serial.println(depth);
  417. Serial.print("Image size: ");
  418. Serial.print(width);
  419. Serial.print('x');
  420. Serial.println(height);
  421. // BMP rows are padded (if needed) to 4-byte boundary
  422. uint32_t rowSize = (width * depth / 8 + 3) & ~3;
  423. if (height < 0)
  424. {
  425. height = -height;
  426. flip = false;
  427. }
  428. uint16_t w = width;
  429. uint16_t h = height;
  430. if ((x + w - 1) >= display.width()) w = display.width() - x;
  431. if ((y + h - 1) >= display.height()) h = display.height() - y;
  432. uint32_t skip = (flip ? (imageOffset + (height - h) * rowSize) : imageOffset) - bytes_read;
  433. //Serial.print("skip "); Serial.println(skip);
  434. while ((skip > 0) && client.connected())
  435. {
  436. client.read(); bytes_read++; skip--;
  437. }
  438. if (((depth == 1) || (depth == 24)) && (rowSize < sizeof(row_buffer))) // handle with direct drawing
  439. {
  440. valid = true;
  441. display.writeScreenBuffer();
  442. for (uint16_t row = 0; row < h; row++) // for each line
  443. {
  444. delay(1); // yield() to avoid WDT
  445. uint32_t got = client.read(row_buffer, rowSize);
  446. while ((got < rowSize) && client.connected())
  447. {
  448. delay(1); // yield() to avoid WDT
  449. got += client.read(row_buffer + got, rowSize - got);
  450. }
  451. bytes_read += got;
  452. if (depth == 24)
  453. {
  454. uint8_t out_byte = 0;
  455. uint32_t out_idx = 0;
  456. uint32_t in_idx = 0;
  457. for (uint16_t col = 0; col < w; col++)
  458. {
  459. uint16_t b = row_buffer[in_idx++];
  460. uint16_t g = row_buffer[in_idx++];
  461. uint16_t r = row_buffer[in_idx++];
  462. if ((r + g + b) / 3 > 0xFF / 2)
  463. {
  464. out_byte |= 0x80 >> col % 8;
  465. }
  466. if (7 == col % 8)
  467. {
  468. row_buffer[out_idx++] = out_byte;
  469. out_byte = 0;
  470. }
  471. }
  472. }
  473. uint16_t y = flip ? h - row - 1 : row;
  474. display.writeImage(row_buffer, 0, y, w, 1);
  475. }
  476. display.refresh();
  477. }
  478. }
  479. Serial.print("bytes read "); Serial.println(bytes_read);
  480. //Serial.print("available "); Serial.println(client.available());
  481. }
  482. if (valid)
  483. {
  484. Serial.print("loaded in ");
  485. Serial.print(millis() - startTime);
  486. Serial.println(" ms");
  487. }
  488. else
  489. {
  490. Serial.println("bitmap format not handled.");
  491. }
  492. }
  493. uint16_t read16(WiFiClient& client)
  494. {
  495. // BMP data is stored little-endian, same as Arduino.
  496. uint16_t result;
  497. ((uint8_t *)&result)[0] = client.read(); // LSB
  498. ((uint8_t *)&result)[1] = client.read(); // MSB
  499. return result;
  500. }
  501. uint32_t read32(WiFiClient& client)
  502. {
  503. // BMP data is stored little-endian, same as Arduino.
  504. uint32_t result;
  505. ((uint8_t *)&result)[0] = client.read(); // LSB
  506. ((uint8_t *)&result)[1] = client.read();
  507. ((uint8_t *)&result)[2] = client.read();
  508. ((uint8_t *)&result)[3] = client.read(); // MSB
  509. return result;
  510. }