środa, 1 kwietnia 2020

[8] ESP32 - Arduino - Pobranie danych z przypadkami koronowirusa

Ten post chciałbym poświęcić na przygotowanie programu pobierającego dane o koronowirusie.

Znalezione obrazy dla zapytania arduino esp32
[Źródło: http://paulobrien.co.nz/2017/03/16/esp32-programming-with-arduino-on-windows/]

W celu pobrania aktualnych danych posłużę się następującym serwerem NovelCovid. Link do strony na githubie: https://github.com/novelcovid/api

Aby pobrać aktualne dane dla Polski należy wysłać następujące żądanie:

  1. https://corona.lmao.ninja/countries/poland

W odpowiedzi wyświetlą się następujące informacje w formacie JSON:

  1. {
  2.     "country":"Poland",
  3.     "cases":425,
  4.     "todayCases":70,
  5.     "deaths":5,
  6.     "todayDeaths":0,
  7.     "recovered":13,
  8.     "active":407,
  9.     "critical":3,
  10.     "casesPerOneMillion":11
  11. }

Powyższa ramka jest już nieaktualna. Została zastąpiona następującą:

  1. {
  2.     "country":"Poland",
  3.     "countryInfo
  4.     {
  5.         "_id":616,
  6.         "iso2":"PL",
  7.         "iso3":"POL",
  8.         "lat":52,
  9.         "long":20,
  10.       "flag":"https://raw.githubusercontent.com/NovelCOVID/API/master/assets/flags/pl.png"
  11.     },
  12.     "cases":2055,
  13.     "todayCases":193,
  14.     "deaths":31,
  15.     "todayDeaths":9,
  16.     "recovered":7,
  17.     "active":2017,
  18.     "critical":3,
  19.     "casesPerOneMillion":54,
  20.     "deathsPerOneMillion":0.8,
  21.     "updated":1585600658521
  22. }

Zmiany polegają na dodaniu dokładniejszych informacji o kraju, ilości śmierci na milion mieszkańców oraz czas aktualizacji.

Innym sposobem jest pobranie wszystkich wyników z całego świata:

  1. https://corona.lmao.ninja/all

Odczytana odpowiedź to:

  1. {
  2.     "cases":776069,
  3.     "deaths":37126,
  4.     "recovered":164622,
  5.     "updated":1585601858656,
  6.     "active":574321
  7. }

//---------------------------------------------------------------------------------------------------------------------

###AKTUALIZACJA###:


Adres strony został zmieniony. Tym razem dane można pobrać wykorzystując następujące linki:

  1. https://corona.lmao.ninja/v2/countries/
  2. https://corona.lmao.ninja/v2/all/

Dodatkowo ilość danych dla wszystkich krajów została zwiększona. Teraz JSON wygląda następująco:

  1. {
  2.     "updated":1587114100141,
  3.     "cases":2190317,
  4.     "todayCases":9009,
  5.     "deaths":147027,
  6.     "todayDeaths":1556,
  7.     "recovered":553672,
  8.     "active":1489618,
  9.     "critical":56601,
  10.     "casesPerOneMillion":281,
  11.     "deathsPerOneMillion":18,
  12.     "tests":18455619,
  13.     "testsPerOneMillion":2367.7,
  14.     "affectedCountries":212
  15. }

//---------------------------------------------------------------------------------------------------------------------

Pozostałe opcje można sprawdzić na stronie projektu na Githubie.

Poniżej przykładowy program wypisujący dane w przez uart:

Powyższy przykład pozwala na wyciągnięcie danych dla trzech krajów oraz dla danych globalnych.

  1. #include <ArduinoJson.h>
  2. #include <WiFi.h>
  3. #include <HTTPClient.h>
  4. //-------------------------------------------------
  5. #define JSON_BUFF_DIMENSION 500
  6. //---------------------------------------------------
  7. #define POLAND "poland"
  8. #define ITALY "italy"
  9. #define GERMANY "germany"
  10. //---------------------------------------------------
  11. const char* ssid = "SSID";
  12. const char* password =  "PASSWORD";
  13. //---------------------------------------------------
  14. const String COUNTRIES_STRING = "https://corona.lmao.ninja/v2/countries/";
  15. const String GLOBAL_DATA_STRING = "https://corona.lmao.ninja/v2/all";
  16. //---------------------------------------------------
  17. String jsonStringText;
  18. String countryArray[3] = {POLAND, ITALY, GERMANY};
  19. //---------------------------------------------------
  20. void setup() {
  21.   Serial.begin(115200);
  22.   WiFi.begin(ssid, password);
  23.   while (WiFi.status() != WL_CONNECTED) {
  24.     delay(1000);
  25.     Serial.print("Connection with WIFI Network....");
  26.   }
  27.   Serial.println("Connected!");
  28.   jsonStringText.reserve(JSON_BUFF_DIMENSION);
  29. }
  30. //---------------------------------------------------
  31. void loop(){
  32.   if ((WiFi.status() == WL_CONNECTED))
  33.   {
  34.     HTTPClient http;
  35.    
  36.     for(uint8_t i=0;i<3;i++)
  37.     {
  38.       http.begin(COUNTRIES_STRING + countryArray[i]); //Specify the URL
  39.       int httpResponseCode = http.GET();  //Make the request
  40.      
  41.       if (httpResponseCode > 0)
  42.       {
  43.         jsonStringText = http.getString();
  44.         Serial.println(httpResponseCode);
  45.         Serial.println(jsonStringText);
  46.         parseCountryJsonData(jsonStringText.c_str());
  47.       }
  48.       else
  49.       {
  50.         Serial.println("Http Request Error");
  51.       }
  52.     }
  53.     http.begin(GLOBAL_DATA_STRING); //Specify the URL
  54.     int httpResponseCode = http.GET();  //Make the request
  55.      
  56.     if (httpResponseCode > 0)
  57.     {
  58.       jsonStringText = http.getString();
  59.       Serial.println(httpResponseCode);
  60.       Serial.println(jsonStringText);
  61.       parseGlobalJsonData(jsonStringText.c_str());
  62.     }
  63.     else
  64.     {
  65.       Serial.println("Http Request Error");
  66.     }
  67.     http.end();
  68.   }
  69.   delay(100000);
  70. }
  71. void parseGlobalJsonData(const char * jsonString)
  72. {
  73.   DynamicJsonDocument jsonBuffer(1000);
  74.   auto error = deserializeJson(jsonBuffer, jsonString);
  75.   if (error) {
  76.     Serial.println("Deserialize error");
  77.     Serial.println(error.c_str());
  78.     return;
  79.   }
  80.   else
  81.   {
  82.     Serial.println("Deserialize OK!");
  83.   }
  84.   //---------------------------------------------------
  85.   size_t len = measureJson(jsonBuffer);
  86.   Serial.println("Msg Len: " + String(len));
  87.   Serial.println("********************************************************");
  88.   Serial.println("Global data:");
  89.   int cases = jsonBuffer["cases"];
  90.   Serial.println("1 - Cases: " + String(cases));
  91.   int deaths = jsonBuffer["deaths"];
  92.   Serial.println("2 - Deaths: " + String(deaths));
  93.   int recovered = jsonBuffer["recovered"];
  94.   Serial.println("3 - Recovered: " + String(recovered));
  95.    
  96.   Serial.println("********************************************************");
  97. }
  98. void parseCountryJsonData(const char * jsonString)
  99. {
  100.   //----------------------------------------------------
  101.   DynamicJsonDocument jsonBuffer(1500);
  102.   auto error = deserializeJson(jsonBuffer, jsonString);
  103.   //----------------------------------------------------
  104.   if (error) {
  105.     Serial.println("Deserialize error");
  106.     Serial.println(error.c_str());
  107.     return;
  108.   }
  109.   else
  110.   {
  111.     Serial.println("Deserialize OK!");
  112.   }
  113.   //---------------------------------------------------
  114.   size_t len = measureJson(jsonBuffer);
  115.   Serial.println("Msg Len: " + String(len));
  116.   //---------------------------------------------------
  117.   Serial.println("********************************************************");
  118.   String country = jsonBuffer["country"];
  119.   Serial.println("1 - Country: " + country);
  120.   int cases = jsonBuffer["cases"];
  121.   Serial.println("2 - Cases: " + String(cases));
  122.   int todayCases = jsonBuffer["todayCases"];
  123.   Serial.println("3 - Today cases: " + String(todayCases));
  124.   int deaths = jsonBuffer["deaths"];
  125.   Serial.println("4 - Deaths: " + String(deaths));
  126.   int todayDeaths = jsonBuffer["todayDeaths"];
  127.   Serial.println("5 - Today deaths: " + String(todayDeaths));
  128.   int recovered = jsonBuffer["recovered"];
  129.   Serial.println("6 - Recovered: " + String(recovered));
  130.   int active = jsonBuffer["active"];
  131.   Serial.println("7 - Active: " + String(active));
  132.   int critical = jsonBuffer["critical"];
  133.   Serial.println("8 - Critical: " + String(critical));
  134.   int casesPerOneMillion = jsonBuffer["casesPerOneMillion"];
  135.   Serial.println("8 - Case Per One Million: " + String(casesPerOneMillion));
  136.   Serial.println("********************************************************");
  137. }

Dla powyższego programu dane zostaną wyświetlone w konsoli. Poniżej otrzymane wyniki operacji dla trzech wybranych krajów.


Dane dla wszystkich przypadków:


Do lepszej prezentacji danych można wykorzystać np. wyświetlacz 2x16 lub inny dostępny.

Ja wykorzystałem wyświetlacz TFT 4'3 cala o rozdzielczości 480x272 (producent AV-Display). Sterowanie wyświetlaczem odbywa się przez interfejs UART (sklep, dokumentacja).

Głównym powodem jego wykorzystania jest prosta obsługa oraz to, że akurat mam taki model nieużywany.

Sterowanie odbywa się przez przesłanie odpowiedniej ramki danych do wyświetlacza.

Chciałbym tutaj jeszcze zaznaczyć, że wykorzystuje czcionki podstawowe bez polskich znaków. Dlatego teksty wyświetlane na ekranie będą w języku angielskim.

Głównym powodem zastosowania języka angielskiego jest dosyć mozolny i nieprzyjemny proces przygotowania czcionki z polskimi znakami. Jest to oczywiście możliwe, natomiast zajmuje sporo czasu i trzeba poświecić sporo uwagi na obsługę programu w języku chińskim.

Tak więc w celu wyświetlenia tekstu na ekranie należy przesłać:

  1. HZBXX Xa Ya C Cb Str

Gdzie XX oznacza wielkość czcionki:

  • 16,
  • 24,
  • 32,
  • 48,
  • 64.

W celu wyświetlenia tekstu należy podać kolor jakim zostanie uzupełnione tło pod napisem. Niestety nie widzę w dokumentacji możliwości wyświetlenia tekstu w transparentnego. Co oznacza, że najlepiej jako tło pod tekstem zastosować jednolity kolor dostępny na wyświetlaczu zamiast np. zdjęcia.

Załadowanie zdjęcia umieszczonego na karcie SD przy wyświetlaczu:

  1. LOAD Xa Ya Path

Wyświetlacz pozwala na wyświetlenie plików jpg, gif, png itp. w tym plików png transparentnych.

ESP32 posiada następujące interfejsy UART:

UART0 - RX: GPIO3; TX: GPIO1;
UART1 - RX: GPIO9; TX: GPIO10;
UART2 - RX: GPIO3; TX: GPIO17;

Interfejs UART0 wykorzystywany jest przez podłączenie kablem USB. Wobec tego wykorzystam UART1. Głównym powodem jest chęć zostawienia łatwego interfejsu UART w celu debugowania bądź wyświetlania danych po transmisji szeregowej.

Należy także pamiętać, że w ESP32 min. linie UART mogą zostać przypisane przez użytkownika do innych wyprowadzeń w dowolny sposób.

Do przesłania danych przygotowuję osobny plik description.h zawierający dostępne wartości czcionek:

  1. enum enum_FontSize {
  2.   FontSize_16 = 16,
  3.   FontSize_24 = 24,
  4.   FontSize_32 = 32,
  5.   FontSize_48 = 48,
  6.   FontSize_64 = 64
  7. };

Funkcje odpowiedzialne za sterowanie wyświetlaczem:

  1. void LCD_PrintStringWithBg(const char * str, const uint16_t len, const enum enum_FontSize fontSize,
  2.                            const uint16_t posX, const uint16_t posY, const uint16_t textColor, const uint16_t bgColor) {
  3.   uint8_t text[len + 1];
  4.   memset(text, 0, sizeof text);
  5.   memcpy(text, str, len);
  6.   char bufferOut[64];
  7.   int bufSize = sprintf(bufferOut, "HZB%d %d %d %d %d %s\n\r", fontSize, posX, posY, textColor, bgColor, text);
  8.   Serial2.write((uint8_t *)bufferOut, bufSize);
  9. }
  10. void LCD_LoadPicture(const char * path, const uint16_t posX, const uint16_t posY) {
  11.   char bufferOut[64];
  12.   memset(bufferOut, 0, sizeof bufferOut);
  13.   int bufSize = sprintf(bufferOut, "LOAD %d %d %s\n\r", posX, posY, path);
  14.   Serial2.write((uint8_t *)bufferOut, bufSize);
  15. }
  16. int LCD_ClearScreen(uint16_t bgColor) {
  17.   if(bgColor > 65535) {
  18.     return 0;
  19.   }
  20.   char bufferOut[16];
  21.   int bufSize = sprintf(bufferOut, "CLS %d\n\r", bgColor);
  22.   Serial2.write((uint8_t *)bufferOut, bufSize);
  23.   return bufSize;
  24. }

Poniżej całość programu:

  1. #include <ArduinoJson.h>
  2. #include <WiFi.h>
  3. #include <HTTPClient.h>
  4. #include "declaration.h"
  5. //-------------------------------------------------
  6. #define COLOR_AQUA        (uint16_t)0x07FF
  7. #define COLOR_BLACK       (uint16_t)0x0000
  8. #define COLOR_BLUE        (uint16_t)0x001F
  9. #define COLOR_FUCHSIA     (uint16_t)0xF81F
  10. #define COLOR_GREEN       (uint16_t)0x0400
  11. #define COLOR_GREY        (uint16_t)0x8410
  12. #define COLOR_LIME        (uint16_t)0x07E0
  13. #define COLOR_MAROON      (uint16_t)0x8000
  14. #define COLOR_NAVY        (uint16_t)0x0010
  15. #define COLOR_OLIVE       (uint16_t)0x8400
  16. #define COLOR_PURPLE      (uint16_t)0xC00F
  17. #define COLOR_RED         (uint16_t)0x9800
  18. #define COLOR_SILVER      (uint16_t)0xC618
  19. #define COLOR_TEAL        (uint16_t)0x0410
  20. #define COLOR_YELLOW      (uint16_t)0xFF40
  21. #define COLOR_WHITE       (uint16_t)0xFFFF  
  22. //-------------------------------------------------
  23. #define JSON_BUFF_DIMENSION 500
  24. //---------------------------------------------------
  25. #define POLAND "poland"
  26. #define ITALY "italy"
  27. #define GERMANY "germany"
  28. #define USA "usa"
  29. //---------------------------------------------------
  30. typedef struct CountryData{
  31.   String country;
  32.   int cases;
  33.   int todayCases;
  34.   int deaths;
  35.   int todayDeaths;
  36.   int recovered;
  37.   int active;
  38.   int critical;
  39.   int casesPerOneMillion;
  40. }CountryDataTypeDef;
  41. CountryDataTypeDef CountryData[5];  //[0] Polska
  42.                                     //[1] Włochy
  43.                                     //[2] Niemcy
  44.                                     //[3] USA
  45.                                     //[4] Świat
  46. //---------------------------------------------------
  47. const char* ssid = "SSID";
  48. const char* password =  "PASSWORD";
  49. //---------------------------------------------------
  50. const String COUNTRIES_STRING = "https://corona.lmao.ninja/v2/countries/";
  51. const String GLOBAL_DATA_STRING = "https://corona.lmao.ninja/v2/all";
  52. //---------------------------------------------------
  53. String jsonStringText;
  54. String countryArray[4] = {POLAND, ITALY, GERMANY, USA};
  55. //---------------------------------------------------
  56. int period = 0;
  57. unsigned long time_now = 0;
  58. //---------------------------------------------------
  59. String command;
  60. //---------------------------------------------------
  61. int touchCounter = 0;
  62. int displayCountry = 0;
  63. int errorCounter = 0;
  64. //---------------------------------------------------
  65. void setup() {
  66.   Serial.begin(115200);
  67.   Serial2.begin(115200, SERIAL_8N1, 16, 17);
  68.   /* Czas potrzebny do uruchomienia wyświetlacza po starcie zasilania */
  69.   delay(3000);
  70.   WiFi.begin(ssid, password);
  71.   while (WiFi.status() != WL_CONNECTED) {
  72.     delay(1000);
  73.     Serial.print("Connection with WIFI Network....");
  74.   }
  75.   Serial.println("Connected!");
  76.   jsonStringText.reserve(JSON_BUFF_DIMENSION);
  77.   LCD_ClearScreen(COLOR_NAVY);
  78.   LCD_PrintStringWithBg("Pobieranie danych...", 17, FontSize_32, 10, 5, COLOR_WHITE, COLOR_NAVY);
  79. }
  80. //---------------------------------------------------
  81. void loop(){
  82.   if(Serial2.available()){
  83.      command = Serial2.readStringUntil('\n');
  84.      if(command.indexOf("XY") > 0) {
  85.       touchCounter++;
  86.      }
  87.      if(touchCounter == 5) {
  88.       touchCounter = 0;
  89.       displayCountry++;
  90.      
  91.       if(displayCountry == 5)
  92.       {
  93.         displayCountry = 0;
  94.       }
  95.       LCD_ClearScreen(COLOR_NAVY);
  96.       LoadSettingsIntoScreen(displayCountry);
  97.       LCD_LoadPicture("jpg/cvlog.jpg", 44, 175);
  98.      }
  99.   }
  100.   if ((WiFi.status() == WL_CONNECTED) && (millis() - time_now > period))
  101.   {
  102.     HTTPClient http;
  103.     errorCounter = 0;
  104.     for(uint8_t i=0;i<4;i++)
  105.     {
  106.       http.begin(COUNTRIES_STRING + countryArray[i]); //Specify the URL
  107.       int httpResponseCode = http.GET();  //Make the request
  108.      
  109.       if (httpResponseCode > 0)
  110.       {
  111.         errorCounter=0;
  112.         jsonStringText = http.getString();
  113.         Serial.println(httpResponseCode);
  114.         Serial.println(jsonStringText);
  115.         parseCountryJsonData(jsonStringText.c_str(), i);
  116.       }
  117.       else
  118.       {
  119.         errorCounter++;
  120.         if(errorCounter == 2)
  121.         {
  122.           errorCounter=0;
  123.         }
  124.         else
  125.         {
  126.           i--;
  127.         }
  128.         Serial.println("Http Request Error");
  129.       }
  130.     }
  131.     http.begin(GLOBAL_DATA_STRING); //Specify the URL
  132.     int httpResponseCode = http.GET();  //Make the request
  133.      
  134.     if (httpResponseCode > 0)
  135.     {
  136.       jsonStringText = http.getString();
  137.       Serial.println(httpResponseCode);
  138.       Serial.println(jsonStringText);
  139.       parseGlobalJsonData(jsonStringText.c_str());
  140.     }
  141.     else
  142.     {
  143.       Serial.println("Http Request Error");
  144.     }
  145.     http.end();
  146.     LCD_ClearScreen(COLOR_NAVY);
  147.     LoadSettingsIntoScreen(0);
  148.     LCD_LoadPicture("jpg/cvlog.jpg", 44, 175);
  149.     time_now = millis();
  150.     period = 200000;
  151.   }
  152. }
  153. void parseGlobalJsonData(const char * jsonString)
  154. {
  155.   DynamicJsonDocument jsonBuffer(1000);
  156.   auto error = deserializeJson(jsonBuffer, jsonString);
  157.   if (error) {
  158.     Serial.println("Deserialize error");
  159.     Serial.println(error.c_str());
  160.     return;
  161.   }
  162.   else
  163.   {
  164.     Serial.println("Deserialize OK!");
  165.   }
  166.   //---------------------------------------------------
  167.   size_t len = measureJson(jsonBuffer);
  168.   Serial.println("Msg Len: " + String(len));
  169.   Serial.println("********************************************************");
  170.   Serial.println("Global data:");
  171.   CountryData[4].country = "World";
  172.   CountryData[4].todayCases = 0;
  173.   CountryData[4].todayDeaths = 0;
  174.   CountryData[4].critical = 0;
  175.   CountryData[4].casesPerOneMillion = 0;
  176.   CountryData[4].cases = jsonBuffer["cases"];;
  177.   Serial.println("1 - Cases: " + String(CountryData[4].cases));
  178.   CountryData[4].deaths = jsonBuffer["deaths"];
  179.   Serial.println("2 - Deaths: " + String(CountryData[4].deaths));
  180.   CountryData[4].recovered = jsonBuffer["recovered"];
  181.   Serial.println("3 - Recovered: " + String(CountryData[4].recovered ));
  182.   CountryData[4].active = jsonBuffer["active"];
  183.   Serial.println("4 - Active: " + String(CountryData[4].active));
  184.   Serial.println("********************************************************");
  185. }
  186. void parseCountryJsonData(const char * jsonString, int structPosition)
  187. {
  188.   //----------------------------------------------------
  189.   DynamicJsonDocument jsonBuffer(1500);
  190.   auto error = deserializeJson(jsonBuffer, jsonString);
  191.   //----------------------------------------------------
  192.   if (error) {
  193.     Serial.println("Deserialize error");
  194.     Serial.println(error.c_str());
  195.     return;
  196.   }
  197.   else
  198.   {
  199.     Serial.println("Deserialize OK!");
  200.   }
  201.   //---------------------------------------------------
  202.   size_t len = measureJson(jsonBuffer);
  203.   Serial.println("Msg Len: " + String(len));
  204.   //---------------------------------------------------
  205.   Serial.println("********************************************************");
  206.   String country = (jsonBuffer["country"]);
  207.   CountryData[structPosition].country = country;
  208.   Serial.println("1 - Country: " + CountryData[structPosition].country );
  209.   CountryData[structPosition].cases = jsonBuffer["cases"];
  210.   Serial.println("2 - Cases: " + String(CountryData[structPosition].cases));
  211.   CountryData[structPosition].todayCases = jsonBuffer["todayCases"];
  212.   Serial.println("3 - Today cases: " + String(CountryData[structPosition].todayCases));
  213.   CountryData[structPosition].deaths = jsonBuffer["deaths"];
  214.   Serial.println("4 - Deaths: " + String(CountryData[structPosition].deaths));
  215.   CountryData[structPosition].todayDeaths = jsonBuffer["todayDeaths"];
  216.   Serial.println("5 - Today deaths: " + String(CountryData[structPosition].todayDeaths));
  217.   CountryData[structPosition].recovered = jsonBuffer["recovered"];
  218.   Serial.println("6 - Recovered: " + String(CountryData[structPosition].recovered));
  219.   CountryData[structPosition].active = jsonBuffer["active"];
  220.   Serial.println("7 - Active: " + String(CountryData[structPosition].active));
  221.   CountryData[structPosition].critical = jsonBuffer["critical"];
  222.   Serial.println("8 - Critical: " + String(CountryData[structPosition].critical));
  223.   CountryData[structPosition].casesPerOneMillion = jsonBuffer["casesPerOneMillion"];
  224.   Serial.println("8 - Case Per One Million: " + String(CountryData[structPosition].casesPerOneMillion));
  225.   Serial.println("********************************************************");
  226. }
  227. void LoadSettingsIntoScreen(int structPosCountryNumber)
  228. {
  229.   char dataToDisplay[50] = {0x00};
  230.   int bufferSize = sprintf(dataToDisplay, "Country: %s", &CountryData[structPosCountryNumber].country[0]);
  231.   LCD_PrintStringWithBg(dataToDisplay, bufferSize - 1, FontSize_32, 10, 5, COLOR_WHITE, COLOR_NAVY);
  232.   bufferSize = sprintf(dataToDisplay, "Cases: %d", CountryData[structPosCountryNumber].cases);
  233.   LCD_PrintStringWithBg(dataToDisplay, bufferSize - 1, FontSize_24, 10, 35, COLOR_WHITE, COLOR_NAVY);
  234.   bufferSize = sprintf(dataToDisplay, "Today cases: %d", CountryData[structPosCountryNumber].todayCases);
  235.   LCD_PrintStringWithBg(dataToDisplay, bufferSize - 1,  FontSize_24, 210, 35, COLOR_WHITE, COLOR_NAVY);
  236.   bufferSize = sprintf(dataToDisplay, "Deaths: %d", CountryData[structPosCountryNumber].deaths);
  237.   LCD_PrintStringWithBg(dataToDisplay, bufferSize - 1, FontSize_24, 10, 65, COLOR_WHITE, COLOR_NAVY);
  238.   bufferSize = sprintf(dataToDisplay, "Today deaths: %d", CountryData[structPosCountryNumber].todayDeaths);
  239.   LCD_PrintStringWithBg(dataToDisplay, bufferSize - 1, FontSize_24, 210, 65, COLOR_WHITE, COLOR_NAVY);
  240.   bufferSize = sprintf(dataToDisplay, "Recover: %d", CountryData[structPosCountryNumber].recovered);
  241.   LCD_PrintStringWithBg(dataToDisplay, bufferSize - 1, FontSize_24, 10, 95, COLOR_WHITE, COLOR_NAVY);
  242.   bufferSize = sprintf(dataToDisplay, "Active: %d", CountryData[structPosCountryNumber].active);
  243.   LCD_PrintStringWithBg(dataToDisplay, bufferSize - 1, FontSize_24, 210, 95, COLOR_WHITE, COLOR_NAVY);
  244.   bufferSize = sprintf(dataToDisplay, "Critical: %d", CountryData[structPosCountryNumber].critical);
  245.   LCD_PrintStringWithBg(dataToDisplay, bufferSize - 1, FontSize_24, 10, 130, COLOR_WHITE, COLOR_NAVY);
  246. }
  247. //----------------------------------------------------------------------------
  248. /* Display Functions */
  249. void LCD_PrintStringWithBg(const char * str, const uint16_t len, const enum enum_FontSize fontSize,
  250.                            const uint16_t posX, const uint16_t posY, const uint16_t textColor, const uint16_t bgColor) {
  251.   uint8_t text[len + 1];
  252.   memset(text, 0, sizeof text);
  253.   memcpy(text, str, len);
  254.   char bufferOut[64];
  255.   int bufSize = sprintf(bufferOut, "HZB%d %d %d %d %d %s\n\r", fontSize, posX, posY, textColor, bgColor, str);
  256.   Serial2.write((uint8_t *)bufferOut, bufSize);
  257.   Serial.write((uint8_t *)bufferOut, bufSize);
  258. }
  259. void LCD_LoadPicture(const char * path, const uint16_t posX, const uint16_t posY) {
  260.   char bufferOut[64];
  261.   memset(bufferOut, 0, sizeof bufferOut);
  262.   int bufSize = sprintf(bufferOut, "LOAD %d %d %s\n\r", posX, posY, path);
  263.   Serial2.write((uint8_t *)bufferOut, bufSize);
  264. }
  265. int LCD_ClearScreen(uint16_t bgColor) {
  266.   if(bgColor > 65535) { return 0; }
  267.   char bufferOut[16];
  268.   int bufSize = sprintf(bufferOut, "CLS %d\n\r", bgColor);
  269.   Serial2.write((uint8_t *)bufferOut, bufSize);
  270.   return bufSize;
  271. }

Poniżej zdjęcie ekranu głównego po załadowaniu danych:


Po podłączeniu do sieci WIFI urządzenie czeka na pobranie wszystkich informacji. Domyślnie pierwszym wyświetlanym krajem jest Polska.

Gdy nastąpi przytrzymanie palca na ekranie to po chwili zostaną załadowane dane z wartościami z następnego kraju. Po zdefiniowanym interwale czasowym następuje ponowne pobranie danych. Po aktualizacji ekran główny wyświetli informację z Polski.