Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,26 @@ 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
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;
};
```

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
Expand All @@ -76,4 +91,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.
45 changes: 45 additions & 0 deletions examples/Get_All_Projects/Get_All_Projects.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <Toggl.h>

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() {
}
33 changes: 25 additions & 8 deletions src/Toggl.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,24 @@

# endif

// Key/Value Pair
struct KVPair {
String name;
int id;
};

// 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;
};

class Toggl{
public:
Toggl();

//Get the induvidual account settings/data
const uint16_t getID();
const String getApiToken();
Expand All @@ -55,8 +69,9 @@ class Toggl{
const String getTimezone();

//Misc
const String getWorkSpace();
const String getProject(int const& WID);
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);

Expand All @@ -73,11 +88,13 @@ 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

void getKVPairs(String const URL, KVReturn &data);
const uint32_t getCurrentTime(const String Timezone);
const String getUserData(String Input);
const String getTimerData(String Input);
String AuthorizationKey{};
const char* Fingerprint{"dac8ac00a1aab269af2149ddb4bd5c881a1a9613"}; // Fingerprint valid until 18 June 2021
const char* root_ca = \
"-----BEGIN CERTIFICATE-----\n"\
"MIIESjCCAzKgAwIBAgINAeO0nXfN9AwGGRa24zANBgkqhkiG9w0BAQsFADBMMSAw\n"\
Expand Down
105 changes: 38 additions & 67 deletions src/Toggl_ESP32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,103 +201,74 @@ 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;
}

KVReturn Toggl::getTags(int const &WID) {
KVReturn returnData{};
String URL = BaseUrl + "/workspaces/" + String(WID) + "/tags";
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)) {

String Output{};
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();

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<JsonArray>();

for (JsonVariant value : arr) {

const int TmpID{value["id"]};
Output += TmpID;
Output += "\n";

JsonArray arr = doc.as<JsonArray>();

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"];
Output += TmpName + "\n" + "\n";

data.KVPairs[i].name = TmpName;
data.KVPairs[i].id = int(value["id"]);
i++;
}
doc.garbageCollect();
filter.garbageCollect();
}

else{
Output = ("Error: " + String(HTTP_Code));
data = (KVReturn){HTTP_Code, 0, NULL};
}

https.end();
return Output;

}
}


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", root_ca);
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<JsonArray>();


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;

}
else {
data = (KVReturn){-1, 0, NULL};
}
}

/*
Expand Down
Loading