From 8513b7e2b3130d87e2119b85a5cb4971a70996e5 Mon Sep 17 00:00:00 2001 From: Keegan Crankshaw Date: Wed, 10 Mar 2021 20:59:07 +0200 Subject: [PATCH 1/7] example of struct usage for the get workspaces method --- src/Toggl.h | 25 +++++++++++++++++------- src/Toggl_ESP32.cpp | 27 +++++++++++++------------- src/Toggl_ESP8266.cpp | 45 ++++++++++++++++++++++++++++--------------- 3 files changed, 62 insertions(+), 35 deletions(-) diff --git a/src/Toggl.h b/src/Toggl.h index 38ea067..2e31050 100644 --- a/src/Toggl.h +++ b/src/Toggl.h @@ -32,10 +32,21 @@ # endif +// Define custom types +struct KVPair { + String name; + int id; +}; + +struct KVReturnPair { + int returnCode; + KVPair * KVPairs; +}; + class Toggl{ public: Toggl(); - + //Get the induvidual account settings/data const uint16_t getID(); const String getApiToken(); @@ -55,7 +66,7 @@ class Toggl{ const String getTimezone(); //Misc - const String getWorkSpace(); + KVReturnPair getWorkSpace(); const String getProject(int const& WID); //const int getPID(String const& WID ,String const& ProjectName); const String CreateTag(String const& Name, int const& WID); @@ -73,11 +84,11 @@ class Toggl{ void setAuth(String const& Token); private: - const uint32_t getCurrentTime(const String Timezone); - const String getUserData(String Input); - const String getTimerData(String Input); - String AuthorizationKey{}; - const char* Fingerprint{"41c40c6a907d364b26d40d40d24f0c1b42f126da"}; // Fingerprint valid until 22 April 2021 + const uint32_t getCurrentTime(const String Timezone); + const String getUserData(String Input); + const String getTimerData(String Input); + String AuthorizationKey{}; + const char* Fingerprint{"41c40c6a907d364b26d40d40d24f0c1b42f126da"}; // Fingerprint valid until 22 April 2021 const String BaseUrl = "https://api.track.toggl.com/api/v8"; }; diff --git a/src/Toggl_ESP32.cpp b/src/Toggl_ESP32.cpp index e9422d2..ce4ba42 100644 --- a/src/Toggl_ESP32.cpp +++ b/src/Toggl_ESP32.cpp @@ -218,30 +218,31 @@ const String Toggl::getWorkSpace(){ if(HTTP_Code >= 200 && HTTP_Code <= 226){ DynamicJsonDocument doc(1024); - StaticJsonDocument<50> filter; filter[0]["id"] = true; filter[0]["name"] = true; deserializeJson(doc, https.getString(), DeserializationOption::Filter(filter)); - - JsonArray arr = doc.as(); - - for (JsonVariant value : arr) { - - const int TmpID{value["id"]}; - Output += TmpID; - Output += "\n"; - String TmpName = value["name"]; - Output += TmpName + "\n" + "\n"; - + + JsonArray arr = doc.as(); + + TogglProject* projects = new TogglProject[arr.size()]; + int i = 0; + for (JsonVariant value : arr) { + String TmpName = value["name"]; + const int TmpID{value["id"]}; + projects[i].name = TmpName; + projects[i].id = TmpID; + i++; } doc.garbageCollect(); filter.garbageCollect(); + + return projects; } else{ - Output = ("Error: " + String(HTTP_Code)); + return NULL; } https.end(); diff --git a/src/Toggl_ESP8266.cpp b/src/Toggl_ESP8266.cpp index 939ff00..6fc8507 100644 --- a/src/Toggl_ESP8266.cpp +++ b/src/Toggl_ESP8266.cpp @@ -228,7 +228,7 @@ const String Toggl::CreateTag(String const& Name, int const& WID){ } -const String Toggl::getWorkSpace(){ +KVReturnPair Toggl::getWorkSpace(){ if ((WiFi.status() == WL_CONNECTED)) { @@ -239,7 +239,7 @@ const String Toggl::getWorkSpace(){ std::unique_ptrclient(new BearSSL::WiFiClientSecure); client->setFingerprint(Fingerprint); - + HTTPClient https; https.begin(*client, BaseUrl + "/workspaces"); @@ -256,27 +256,42 @@ const String Toggl::getWorkSpace(){ deserializeJson(doc, https.getString(), DeserializationOption::Filter(filter)); - JsonArray arr = doc.as(); - - for (JsonVariant value : arr) { - - const int TmpID{value["id"]}; - Output += TmpID; - Output += "\n"; - String TmpName = value["name"]; - Output += TmpName + "\n" + "\n"; - + JsonArray arr = doc.as(); + + KVPair* projects = new KVPair[arr.size()]; + KVReturnPair returnData { + arr.size(), + projects + }; + + int i = 0; + for (JsonVariant value : arr) { + String TmpName = value["name"]; + const int TmpID{value["id"]}; + projects[i].name = TmpName; + projects[i].id = TmpID; + i++; } doc.garbageCollect(); filter.garbageCollect(); + + return returnData; } else{ - Output = ("Error: " + String(HTTP_Code)); + KVReturnPair returnData { + 0, + NULL + }; + + return returnData; } - +KVReturnPair returnData { + 0, + NULL + }; https.end(); - return Output; + return returnData; } } From 13b8229440f78221aaa0ce644c43e51e5a9904ea Mon Sep 17 00:00:00 2001 From: Keegan Crankshaw Date: Sun, 14 Mar 2021 17:33:44 +0200 Subject: [PATCH 2/7] Work on transferring over workspaces and projects to KV pairs. ESP32 untested --- src/Toggl.h | 14 ++-- src/Toggl_ESP32.cpp | 89 ++++++++----------------- src/Toggl_ESP8266.cpp | 150 ++++++++++++++---------------------------- 3 files changed, 84 insertions(+), 169 deletions(-) diff --git a/src/Toggl.h b/src/Toggl.h index 2e31050..21fd8aa 100644 --- a/src/Toggl.h +++ b/src/Toggl.h @@ -32,14 +32,17 @@ # endif -// Define custom types +// Key/Value Pair struct KVPair { String name; int id; }; -struct KVReturnPair { - int returnCode; +// A Key/Value return struct, including HTTP code for readability/ +// This is essentially a std::arr, but there's not support for that in the default Arduino libs +struct KVReturn { + int HTTPCode; + int pairCount; KVPair * KVPairs; }; @@ -66,8 +69,8 @@ class Toggl{ const String getTimezone(); //Misc - KVReturnPair getWorkSpace(); - const String getProject(int const& WID); + KVReturn getWorkSpaces(); + KVReturn getProjects(int const& WID); //const int getPID(String const& WID ,String const& ProjectName); const String CreateTag(String const& Name, int const& WID); @@ -84,6 +87,7 @@ class Toggl{ void setAuth(String const& Token); private: + void getKVPairs(String const URL, KVReturn &data); const uint32_t getCurrentTime(const String Timezone); const String getUserData(String Input); const String getTimerData(String Input); diff --git a/src/Toggl_ESP32.cpp b/src/Toggl_ESP32.cpp index ce4ba42..1951906 100644 --- a/src/Toggl_ESP32.cpp +++ b/src/Toggl_ESP32.cpp @@ -201,8 +201,23 @@ const String Toggl::CreateTag(String const& Name, int const& WID){ } } + +KVReturn Toggl::getWorkSpaces() { + KVReturn returnData{}; + String URL = BaseUrl + "/workspaces"; + getKVPairs(URL, returnData); + return returnData; +} + +KVReturn Toggl::getProjects(int const &WID) { + KVReturn returnData{}; + String URL = BaseUrl + "/workspaces/" + String(WID) + "/projects"; + getKVPairs(URL, returnData); + return returnData; +} + //Returns Workplace ID (WID) -const String Toggl::getWorkSpace(){ +void Toggl::getKVPairs(String const URL, KVReturn &data){ if ((WiFi.status() == WL_CONNECTED)) { @@ -210,7 +225,7 @@ const String Toggl::getWorkSpace(){ uint16_t HTTP_Code{}; HTTPClient https; - https.begin(BaseUrl + "/workspaces", Fingerprint); + https.begin(URL, Fingerprint); https.addHeader("Authorization", AuthorizationKey, true); HTTP_Code = https.GET(); @@ -226,80 +241,30 @@ const String Toggl::getWorkSpace(){ JsonArray arr = doc.as(); - TogglProject* projects = new TogglProject[arr.size()]; + data = (KVReturn){HTTP_Code, arr.size(), new KVPair[arr.size()]}; int i = 0; for (JsonVariant value : arr) { - String TmpName = value["name"]; - const int TmpID{value["id"]}; - projects[i].name = TmpName; - projects[i].id = TmpID; - i++; + // directly assigning value["name"] doesn't work + String TmpName = value["name"]; + data.KVPairs[i].name = TmpName; + data.KVPairs[i].id = int(value["id"]); + i++; } doc.garbageCollect(); filter.garbageCollect(); - - return projects; } - else{ - return NULL; + data = (KVReturn){HTTP_Code, 0, NULL}; } https.end(); - return Output; - } + else { + data = (KVReturn){-1, 0, NULL}; + } } -const String Toggl::getProject(int const& WID){ - - if ((WiFi.status() == WL_CONNECTED)) { - - String Output{}; - uint16_t HTTP_Code{}; - - DynamicJsonDocument doc(1024); - - StaticJsonDocument<50> filter; - filter[0]["id"] = true; - filter[0]["name"] = true; - HTTPClient https; - https.begin("https://api.track.toggl.com/api/v8/workspaces/" + String(WID) + "/projects", Fingerprint); - https.addHeader("Authorization", AuthorizationKey, true); - - HTTP_Code = https.GET(); - - if(HTTP_Code >= 200 && HTTP_Code <= 226){ - - deserializeJson(doc, https.getString(), DeserializationOption::Filter(filter)); - - - JsonArray arr = doc.as(); - - - for (JsonVariant value : arr) { - - const int TmpID{value["id"]}; - Output += TmpID; - Output += "\n"; - String TmpName = value["name"]; - Output += TmpName + "\n" + "\n"; - - } - doc.garbageCollect(); - filter.garbageCollect(); - } - - else{ - Output = ("Error: " + String(HTTP_Code)); - } - - https.end(); - return Output; - - } -} /* //ToDo make the code somewhat nicer. diff --git a/src/Toggl_ESP8266.cpp b/src/Toggl_ESP8266.cpp index 6fc8507..201291a 100644 --- a/src/Toggl_ESP8266.cpp +++ b/src/Toggl_ESP8266.cpp @@ -228,129 +228,75 @@ const String Toggl::CreateTag(String const& Name, int const& WID){ } -KVReturnPair Toggl::getWorkSpace(){ - - if ((WiFi.status() == WL_CONNECTED)) { - - String Output{}; - uint16_t HTTP_Code{}; - uint8_t Counter{}; - - std::unique_ptrclient(new BearSSL::WiFiClientSecure); - client->setFingerprint(Fingerprint); - - - - HTTPClient https; - https.begin(*client, BaseUrl + "/workspaces"); - https.addHeader("Authorization", AuthorizationKey, true); +KVReturn Toggl::getWorkSpaces() { + KVReturn returnData{}; + String URL = BaseUrl + "/workspaces"; + getKVPairs(URL, returnData); + return returnData; +} - HTTP_Code = https.GET(); +KVReturn Toggl::getProjects(int const &WID) { + KVReturn returnData{}; + String URL = BaseUrl + "/workspaces/" + String(WID) + "/projects"; + getKVPairs(URL, returnData); + return returnData; +} - if(HTTP_Code >= 200 && HTTP_Code <= 226){ - DynamicJsonDocument doc(1024); - StaticJsonDocument<50> filter; - filter[0]["id"] = true; - filter[0]["name"] = true; - - deserializeJson(doc, https.getString(), DeserializationOption::Filter(filter)); - - JsonArray arr = doc.as(); - - KVPair* projects = new KVPair[arr.size()]; - KVReturnPair returnData { - arr.size(), - projects - }; - - int i = 0; - for (JsonVariant value : arr) { - String TmpName = value["name"]; - const int TmpID{value["id"]}; - projects[i].name = TmpName; - projects[i].id = TmpID; - i++; - } - doc.garbageCollect(); - filter.garbageCollect(); - - return returnData; - } +void Toggl::getKVPairs(String const URL, KVReturn &data) { + + if ((WiFi.status() == WL_CONNECTED)) { - else{ - KVReturnPair returnData { - 0, - NULL - }; - - return returnData; - } -KVReturnPair returnData { - 0, - NULL - }; - https.end(); - return returnData; + String Output{}; + uint16_t HTTP_Code{}; - } -} + std::unique_ptr client(new BearSSL::WiFiClientSecure); + client->setFingerprint(Fingerprint); + HTTPClient https; + https.begin(*client, URL); + https.addHeader("Authorization", AuthorizationKey, true); -// Need to solve the address problem.. -const String Toggl::getProject(int const& WID){ + HTTP_Code = https.GET(); - - if ((WiFi.status() == WL_CONNECTED)) { + if (HTTP_Code >= 200 && HTTP_Code <= 226) { - String Output{}; - uint16_t HTTP_Code{}; - DynamicJsonDocument doc(1024); - StaticJsonDocument<50> filter; filter[0]["id"] = true; filter[0]["name"] = true; - std::unique_ptrclient(new BearSSL::WiFiClientSecure); - client->setFingerprint(Fingerprint); - - HTTPClient https; - https.begin(*client, BaseUrl + "/workspaces/" + String(WID) + "/projects"); - https.addHeader("Authorization", AuthorizationKey); + deserializeJson(doc, https.getString(),DeserializationOption::Filter(filter)); - HTTP_Code = https.GET(); + JsonArray arr = doc.as(); - if(HTTP_Code >= 200 && HTTP_Code <= 226){ - - deserializeJson(doc, https.getString(), DeserializationOption::Filter(filter)); - - JsonArray arr = doc.as(); - - for (JsonVariant value : arr){ - - const int TmpID{value["id"]}; - Output += TmpID; - Output += "\n"; - String TmpName = value["name"]; - Output += TmpName + "\n" + "\n"; - } - doc.garbageCollect(); - filter.garbageCollect(); + data = (KVReturn){HTTP_Code, arr.size(), new KVPair[arr.size()]}; + int i = 0; + for (JsonVariant value : arr) { + // directly assigning value["name"] doesn't work + String TmpName = value["name"]; + data.KVPairs[i].name = TmpName; + data.KVPairs[i].id = int(value["id"]); + i++; } + + doc.garbageCollect(); + filter.garbageCollect(); - else{ - Output = ("Error: " + String(HTTP_Code)); - } - - https.end(); - return Output; - - } - + } + else { + data = (KVReturn){HTTP_Code, 0, NULL}; + } + + https.end(); + } + else { + data = (KVReturn){-1, 0, NULL}; + } } + const String Toggl::getTimerData(String Input){ if ((WiFi.status() == WL_CONNECTED)) { From 76449be44075b596df2f926434deaf0ec254b210 Mon Sep 17 00:00:00 2001 From: Keegan Crankshaw Date: Mon, 15 Mar 2021 21:27:57 +0200 Subject: [PATCH 3/7] Fixed incorrect URL being used --- src/Toggl_ESP32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Toggl_ESP32.cpp b/src/Toggl_ESP32.cpp index cf31320..093585c 100644 --- a/src/Toggl_ESP32.cpp +++ b/src/Toggl_ESP32.cpp @@ -225,7 +225,7 @@ void Toggl::getKVPairs(String const URL, KVReturn &data){ uint16_t HTTP_Code{}; HTTPClient https; - https.begin(BaseUrl + "/workspaces", root_ca); + https.begin(URL, root_ca); https.addHeader("Authorization", AuthorizationKey, true); HTTP_Code = https.GET(); From 74b7a81c650ac2d97ec8ed0e8d0cd48c8b3a5125 Mon Sep 17 00:00:00 2001 From: Keegan Crankshaw Date: Mon, 15 Mar 2021 22:06:32 +0200 Subject: [PATCH 4/7] Added example for new methods --- README.md | 18 ++++++-- .../Get_All_Projects/Get_All_Projects.ino | 45 +++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 examples/Get_All_Projects/Get_All_Projects/Get_All_Projects.ino diff --git a/README.md b/README.md index aee3084..99c096e 100644 --- a/README.md +++ b/README.md @@ -50,11 +50,23 @@ isTimerActive(); //Returns a bool if timer is active. # Misc ```c++ -getWorkSpace(); // Returns a "pretty" string of all workspaces and ID's -getProject(int const& WID); // Returns a "pretty" string of all project is specific workplace +getWorkSpaces(); // Returns a KVReturn struct of all workspaces +getProject(int const& WID); // Returns a KVReturn struct of all projects for a given workspace CreateTag(String Name, int WID); // Requires the Workspace ID ``` +The `KVReturn` struct is as follows: +```c++ +struct KVReturn { + int HTTPCode; + int pairCount; + KVPair * KVPairs; +}; +``` +It is important to `delete[]` the KVPairs after you've used what you've needed, or set it to `NULL` if you plan to use it again. See the "Get All Projects" example for more info. + + + # General Setup @@ -76,4 +88,4 @@ ESP32 default libraries - [Create a Time Entry:](https://github.com/JoeyStrandnes/Arduino-Toggl-API/tree/master/examples/Create_Time_Entry) Create a time entry with duration 1 hour. - [Button Timer:](https://github.com/JoeyStrandnes/Arduino-Toggl-API/tree/master/examples/Button_Timer) Starts a timer and LED when a button is pressed. Stops timer and turns of LED when it is pressed again. - [Advanced Button Timer:](https://github.com/JoeyStrandnes/Arduino-Toggl-API/tree/master/examples/Advanced_Button_Timer) Does everything that the regular button timer does but will "sync" with other active timers. It will know if a timer is started and will know if it is stopped. The LED and button function will adjust acording to the timer status. - +- [Get All Projects:](/examples/Get_All_Projects) Gets all projects in all workspaces for a given user. diff --git a/examples/Get_All_Projects/Get_All_Projects/Get_All_Projects.ino b/examples/Get_All_Projects/Get_All_Projects/Get_All_Projects.ino new file mode 100644 index 0000000..744087d --- /dev/null +++ b/examples/Get_All_Projects/Get_All_Projects/Get_All_Projects.ino @@ -0,0 +1,45 @@ +#include + +const char* SSID = ""; +const char* PASS = ""; + +String const Token {""}; //API Token is found in "Profile Settings" + +Toggl toggl; + +void setup() { + Serial.begin(115200); + toggl.init(SSID, PASS); + toggl.setAuth(Token); + delay(100); + Serial.println("Get all projects for all workspaces"); + KVReturn workspaces = toggl.getWorkSpaces(); + KVReturn projects; + if (workspaces.HTTPCode >= 200 && workspaces.HTTPCode <= 226) { + Serial.println("There are " + String(workspaces.pairCount) + " workspaces"); + + for (int i = 0; i < workspaces.pairCount; i++) { + projects = toggl.getProjects(workspaces.KVPairs[i].id); + if (projects.HTTPCode >= 200 && projects.HTTPCode <= 226) { + Serial.println("There are " + String(projects.pairCount) + " projects in workspace " + workspaces.KVPairs[i].name); + for (int i = 0; i < projects.pairCount; i++) { + Serial.println(String(projects.KVPairs[i].id) + ": " + projects.KVPairs[i].name); + } + projects.KVPairs = NULL; // set to null here, as we plan to use this again later. + } + else { + Serial.println("Failed to get projects with HTTPCode " + String(projects.HTTPCode)); + } + } + } + else { + Serial.println("Failed to get workspaces with HTTPCode " + String(workspaces.HTTPCode)); + } + + delete[] workspaces.KVPairs; // we're done with the workspace KVPairs + delete[] projects.KVPairs; // we're done with the project KVPairs + +} + +void loop() { +} From 98ab3938820cb84ff408f798ef40db5aae13ad50 Mon Sep 17 00:00:00 2001 From: Keegan Crankshaw Date: Mon, 15 Mar 2021 22:10:52 +0200 Subject: [PATCH 5/7] Added getTags method --- README.md | 15 +++++++++------ src/Toggl.h | 1 + src/Toggl_ESP32.cpp | 7 +++++++ src/Toggl_ESP8266.cpp | 6 ++++++ 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 99c096e..baba8bf 100644 --- a/README.md +++ b/README.md @@ -50,19 +50,22 @@ isTimerActive(); //Returns a bool if timer is active. # Misc ```c++ -getWorkSpaces(); // Returns a KVReturn struct of all workspaces -getProject(int const& WID); // Returns a KVReturn struct of all projects for a given workspace -CreateTag(String Name, int WID); // Requires the Workspace ID +getWorkSpaces(); // Returns a KVReturn struct of all workspaces +getProjects(int const& WID); // Returns a KVReturn struct of all projects for a given workspace +getTags(int const& WID); // Returns a KVReturn struct of all tags for a given workspace +CreateTag(String Name, int WID); // Requires the Workspace ID ``` The `KVReturn` struct is as follows: + ```c++ struct KVReturn { - int HTTPCode; - int pairCount; - KVPair * KVPairs; + int HTTPCode; + int pairCount; + KVPair * KVPairs; }; ``` + It is important to `delete[]` the KVPairs after you've used what you've needed, or set it to `NULL` if you plan to use it again. See the "Get All Projects" example for more info. diff --git a/src/Toggl.h b/src/Toggl.h index 967ae95..d065f46 100644 --- a/src/Toggl.h +++ b/src/Toggl.h @@ -71,6 +71,7 @@ class Toggl{ //Misc KVReturn getWorkSpaces(); KVReturn getProjects(int const& WID); + KVReturn getTags(int const& WID); //const int getPID(String const& WID ,String const& ProjectName); const String CreateTag(String const& Name, int const& WID); diff --git a/src/Toggl_ESP32.cpp b/src/Toggl_ESP32.cpp index 093585c..326f06c 100644 --- a/src/Toggl_ESP32.cpp +++ b/src/Toggl_ESP32.cpp @@ -216,6 +216,13 @@ KVReturn Toggl::getProjects(int const &WID) { return returnData; } +KVReturn Toggl::getTags(int const &WID) { + KVReturn returnData{}; + String URL = BaseUrl + "/workspaces/" + String(WID) + "/tags"; + getKVPairs(URL, returnData); + return returnData; +} + //Returns Workplace ID (WID) void Toggl::getKVPairs(String const URL, KVReturn &data){ diff --git a/src/Toggl_ESP8266.cpp b/src/Toggl_ESP8266.cpp index 201291a..136bc8d 100644 --- a/src/Toggl_ESP8266.cpp +++ b/src/Toggl_ESP8266.cpp @@ -242,6 +242,12 @@ KVReturn Toggl::getProjects(int const &WID) { return returnData; } +KVReturn Toggl::getTags(int const &WID) { + KVReturn returnData{}; + String URL = BaseUrl + "/workspaces/" + String(WID) + "/tags"; + getKVPairs(URL, returnData); + return returnData; +} void Toggl::getKVPairs(String const URL, KVReturn &data) { From c16d4c20d82be1a8f9cdfd72d7ce455d31d88f05 Mon Sep 17 00:00:00 2001 From: Keegan Crankshaw Date: Mon, 15 Mar 2021 22:18:28 +0200 Subject: [PATCH 6/7] Fix folder structure --- .../Get_All_Projects/{Get_All_Projects => }/Get_All_Projects.ino | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/Get_All_Projects/{Get_All_Projects => }/Get_All_Projects.ino (100%) diff --git a/examples/Get_All_Projects/Get_All_Projects/Get_All_Projects.ino b/examples/Get_All_Projects/Get_All_Projects.ino similarity index 100% rename from examples/Get_All_Projects/Get_All_Projects/Get_All_Projects.ino rename to examples/Get_All_Projects/Get_All_Projects.ino From 4eb3029380b0f3f3d47afe990f284a706de55f24 Mon Sep 17 00:00:00 2001 From: Keegan Crankshaw Date: Sat, 20 Mar 2021 21:07:49 +0200 Subject: [PATCH 7/7] Updated Fingerprint --- src/Toggl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Toggl.h b/src/Toggl.h index d065f46..4d8c5c5 100644 --- a/src/Toggl.h +++ b/src/Toggl.h @@ -94,7 +94,7 @@ class Toggl{ const String getUserData(String Input); const String getTimerData(String Input); String AuthorizationKey{}; - const char* Fingerprint{"41c40c6a907d364b26d40d40d24f0c1b42f126da"}; // Fingerprint valid until 22 April 2021 + const char* Fingerprint{"dac8ac00a1aab269af2149ddb4bd5c881a1a9613"}; // Fingerprint valid until 18 June 2021 const char* root_ca = \ "-----BEGIN CERTIFICATE-----\n"\ "MIIESjCCAzKgAwIBAgINAeO0nXfN9AwGGRa24zANBgkqhkiG9w0BAQsFADBMMSAw\n"\