GxEPD2_WiFi_Example.ino 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  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. void showBitmapFrom_HTTP(const char* host, const char* path, const char* filename, uint8_t x, uint8_t y)
  209. {
  210. WiFiClient client;
  211. uint8_t buffer[512]; // buffer for at least one row
  212. bool valid = false; // valid format to be handled
  213. bool flip = true; // bitmap is stored bottom-to-top
  214. uint32_t startTime = millis();
  215. if ((x >= display.width()) || (y >= display.height())) return;
  216. Serial.print("connecting to ");
  217. Serial.println(host);
  218. if (!client.connect(host, httpPort))
  219. {
  220. Serial.println("connection failed");
  221. return;
  222. }
  223. Serial.print("requesting URL: ");
  224. Serial.println(String("http://") + host + path + filename);
  225. client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
  226. "Host: " + host + "\r\n" +
  227. "User-Agent: GxEPD2_Spiffs_Loader\r\n" +
  228. "Connection: close\r\n\r\n");
  229. Serial.println("request sent");
  230. bool ok = false;
  231. while (client.connected())
  232. {
  233. String line = client.readStringUntil('\n');
  234. if (!ok)
  235. {
  236. ok = line.startsWith("HTTP/1.1 200 OK");
  237. if (ok) Serial.println(line);
  238. //if (!ok) Serial.println(line);
  239. }
  240. if (!ok) Serial.println(line);
  241. //Serial.println(line);
  242. if (line == "\r")
  243. {
  244. Serial.println("headers received");
  245. break;
  246. }
  247. }
  248. if (!ok) return;
  249. // Parse BMP header
  250. if (read16(client) == 0x4D42) // BMP signature
  251. {
  252. uint32_t fileSize = read32(client);
  253. uint32_t creatorBytes = read32(client);
  254. uint32_t imageOffset = read32(client); // Start of image data
  255. uint32_t headerSize = read32(client);
  256. uint32_t width = read32(client);
  257. uint32_t height = read32(client);
  258. uint16_t planes = read16(client);
  259. uint16_t depth = read16(client); // bits per pixel
  260. uint32_t format = read32(client);
  261. uint32_t bytes_read = 7 * 4 + 3 * 2; // read so far
  262. if ((planes == 1) && (format == 0)) // uncompressed is handled
  263. {
  264. Serial.print("File size: "); Serial.println(fileSize);
  265. Serial.print("Image Offset: "); Serial.println(imageOffset);
  266. Serial.print("Header size: "); Serial.println(headerSize);
  267. Serial.print("Bit Depth: "); Serial.println(depth);
  268. Serial.print("Image size: ");
  269. Serial.print(width);
  270. Serial.print('x');
  271. Serial.println(height);
  272. // BMP rows are padded (if needed) to 4-byte boundary
  273. uint32_t rowSize = (width * depth / 8 + 3) & ~3;
  274. if (height < 0)
  275. {
  276. height = -height;
  277. flip = false;
  278. }
  279. uint16_t w = width;
  280. uint16_t h = height;
  281. if ((x + w - 1) >= display.width()) w = display.width() - x;
  282. if ((y + h - 1) >= display.height()) h = display.height() - y;
  283. uint32_t skip = (flip ? (imageOffset + (height - h) * rowSize) : imageOffset) - bytes_read;
  284. if (skip > 0) bytes_read += client.read(buffer, skip);
  285. //Serial.print("skip "); Serial.println(skip);
  286. if (((depth == 1) || (depth == 24)) && (rowSize < sizeof(buffer))) // handle with direct drawing
  287. {
  288. valid = true;
  289. display.writeScreenBuffer();
  290. for (uint16_t row = 0; row < h; row++) // for each line
  291. {
  292. delay(1); // yield() to avoid WDT
  293. uint32_t got = client.read(buffer, rowSize);
  294. while ((got < rowSize) && client.connected())
  295. {
  296. delay(1); // yield() to avoid WDT
  297. got += client.read(buffer + got, rowSize - got);
  298. }
  299. bytes_read += got;
  300. if (depth == 24)
  301. {
  302. uint8_t out_byte = 0;
  303. uint32_t out_idx = 0;
  304. uint32_t in_idx = 0;
  305. for (uint16_t col = 0; col < w; col++)
  306. {
  307. uint16_t b = buffer[in_idx++];
  308. uint16_t g = buffer[in_idx++];
  309. uint16_t r = buffer[in_idx++];
  310. if ((r + g + b) / 3 > 0xFF / 2)
  311. {
  312. out_byte |= 0x80 >> col % 8;
  313. }
  314. if (7 == col % 8)
  315. {
  316. buffer[out_idx++] = out_byte;
  317. out_byte = 0;
  318. }
  319. }
  320. }
  321. uint16_t y = flip ? h - row - 1 : row;
  322. display.writeImage(buffer, 0, y, w, 1);
  323. }
  324. display.refresh();
  325. }
  326. }
  327. Serial.print("bytes read "); Serial.println(bytes_read);
  328. //Serial.print("available "); Serial.println(client.available());
  329. }
  330. if (valid)
  331. {
  332. Serial.print("loaded in ");
  333. Serial.print(millis() - startTime);
  334. Serial.println(" ms");
  335. }
  336. else
  337. {
  338. Serial.println("bitmap format not handled.");
  339. }
  340. }
  341. void showBitmapFrom_HTTPS(const char* host, const char* path, const char* filename, const char* fingerprint, uint8_t x, uint8_t y)
  342. {
  343. // Use WiFiClientSecure class to create TLS connection
  344. WiFiClientSecure client;
  345. uint8_t buffer[512]; // buffer for at least one row
  346. bool valid = false; // valid format to be handled
  347. bool flip = true; // bitmap is stored bottom-to-top
  348. uint32_t startTime = millis();
  349. if ((x >= display.width()) || (y >= display.height())) return;
  350. Serial.print("connecting to ");
  351. Serial.println(host);
  352. if (!client.connect(host, httpsPort))
  353. {
  354. Serial.println("connection failed");
  355. return;
  356. }
  357. if (fingerprint)
  358. {
  359. if (client.verify(fingerprint, host))
  360. {
  361. Serial.println("certificate matches");
  362. }
  363. else
  364. {
  365. Serial.println("certificate doesn't match");
  366. return;
  367. }
  368. }
  369. Serial.print("requesting URL: ");
  370. Serial.println(String("https://") + host + path + filename);
  371. client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
  372. "Host: " + host + "\r\n" +
  373. "User-Agent: GxEPD2_Spiffs_Loader\r\n" +
  374. "Connection: close\r\n\r\n");
  375. Serial.println("request sent");
  376. bool ok = false;
  377. while (client.connected())
  378. {
  379. String line = client.readStringUntil('\n');
  380. if (!ok)
  381. {
  382. ok = line.startsWith("HTTP/1.1 200 OK");
  383. if (ok) Serial.println(line);
  384. //if (!ok) Serial.println(line);
  385. }
  386. if (!ok) Serial.println(line);
  387. //Serial.println(line);
  388. if (line == "\r")
  389. {
  390. Serial.println("headers received");
  391. break;
  392. }
  393. }
  394. if (!ok) return;
  395. // Parse BMP header
  396. if (read16(client) == 0x4D42) // BMP signature
  397. {
  398. uint32_t fileSize = read32(client);
  399. uint32_t creatorBytes = read32(client);
  400. uint32_t imageOffset = read32(client); // Start of image data
  401. uint32_t headerSize = read32(client);
  402. uint32_t width = read32(client);
  403. uint32_t height = read32(client);
  404. uint16_t planes = read16(client);
  405. uint16_t depth = read16(client); // bits per pixel
  406. uint32_t format = read32(client);
  407. uint32_t bytes_read = 7 * 4 + 3 * 2; // read so far
  408. if ((planes == 1) && (format == 0)) // uncompressed is handled
  409. {
  410. Serial.print("File size: "); Serial.println(fileSize);
  411. Serial.print("Image Offset: "); Serial.println(imageOffset);
  412. Serial.print("Header size: "); Serial.println(headerSize);
  413. Serial.print("Bit Depth: "); Serial.println(depth);
  414. Serial.print("Image size: ");
  415. Serial.print(width);
  416. Serial.print('x');
  417. Serial.println(height);
  418. // BMP rows are padded (if needed) to 4-byte boundary
  419. uint32_t rowSize = (width * depth / 8 + 3) & ~3;
  420. if (height < 0)
  421. {
  422. height = -height;
  423. flip = false;
  424. }
  425. uint16_t w = width;
  426. uint16_t h = height;
  427. if ((x + w - 1) >= display.width()) w = display.width() - x;
  428. if ((y + h - 1) >= display.height()) h = display.height() - y;
  429. uint32_t skip = (flip ? (imageOffset + (height - h) * rowSize) : imageOffset) - bytes_read;
  430. if (skip > 0) bytes_read += client.read(buffer, skip);
  431. //Serial.print("skip "); Serial.println(skip);
  432. if (((depth == 1) || (depth == 24)) && (rowSize < sizeof(buffer))) // handle with direct drawing
  433. {
  434. valid = true;
  435. display.writeScreenBuffer();
  436. for (uint16_t row = 0; row < h; row++) // for each line
  437. {
  438. delay(1); // yield() to avoid WDT
  439. uint32_t got = client.read(buffer, rowSize);
  440. while ((got < rowSize) && client.connected())
  441. {
  442. delay(1); // yield() to avoid WDT
  443. got += client.read(buffer + got, rowSize - got);
  444. }
  445. bytes_read += got;
  446. if (depth == 24)
  447. {
  448. uint8_t out_byte = 0;
  449. uint32_t out_idx = 0;
  450. uint32_t in_idx = 0;
  451. for (uint16_t col = 0; col < w; col++)
  452. {
  453. uint16_t b = buffer[in_idx++];
  454. uint16_t g = buffer[in_idx++];
  455. uint16_t r = buffer[in_idx++];
  456. if ((r + g + b) / 3 > 0xFF / 2)
  457. {
  458. out_byte |= 0x80 >> col % 8;
  459. }
  460. if (7 == col % 8)
  461. {
  462. buffer[out_idx++] = out_byte;
  463. out_byte = 0;
  464. }
  465. }
  466. }
  467. uint16_t y = flip ? h - row - 1 : row;
  468. display.writeImage(buffer, 0, y, w, 1);
  469. }
  470. display.refresh();
  471. }
  472. }
  473. Serial.print("bytes read "); Serial.println(bytes_read);
  474. //Serial.print("available "); Serial.println(client.available());
  475. }
  476. if (valid)
  477. {
  478. Serial.print("loaded in ");
  479. Serial.print(millis() - startTime);
  480. Serial.println(" ms");
  481. }
  482. else
  483. {
  484. Serial.println("bitmap format not handled.");
  485. }
  486. }
  487. uint16_t read16(WiFiClient& client)
  488. {
  489. // BMP data is stored little-endian, same as Arduino.
  490. uint16_t result;
  491. ((uint8_t *)&result)[0] = client.read(); // LSB
  492. ((uint8_t *)&result)[1] = client.read(); // MSB
  493. return result;
  494. }
  495. uint32_t read32(WiFiClient& client)
  496. {
  497. // BMP data is stored little-endian, same as Arduino.
  498. uint32_t result;
  499. ((uint8_t *)&result)[0] = client.read(); // LSB
  500. ((uint8_t *)&result)[1] = client.read();
  501. ((uint8_t *)&result)[2] = client.read();
  502. ((uint8_t *)&result)[3] = client.read(); // MSB
  503. return result;
  504. }