Paperd.Ink Library 0.0.5
Library for interacting with Paperd.Ink devices.
Loading...
Searching...
No Matches
todo_list.cpp
Go to the documentation of this file.
1#include <WiFiClientSecure.h>
2#include <HTTPClient.h>
3
4#include "todo_list.h"
5#include "taiga_parser.h"
6#include "todoist_parser.h"
7
8// Taiga
9String taiga_auth_url = "https://api.taiga.io/api/v1/auth";
10String taiga_slug_url = "https://api.taiga.io/api/v1/projects/by_slug?slug={0}-{1}";
11String taiga_tasks_url = "https://api.taiga.io/api/v1/userstories?include_tasks=1&status__is_archived=false&project=";
12String taiga_post_data = "{ \"type\": \"normal\", \"username\": \"{0}\", \"password\": \"{1}\" }";
14
15// Valid till 14 Apr 2023
16static const char *taiga_cert = "-----BEGIN CERTIFICATE-----\n" \
17 "MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB\n" \
18 "iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl\n" \
19 "cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV\n" \
20 "BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw\n" \
21 "MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV\n" \
22 "BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU\n" \
23 "aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy\n" \
24 "dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK\n" \
25 "AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B\n" \
26 "3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY\n" \
27 "tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/\n" \
28 "Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2\n" \
29 "VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT\n" \
30 "79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6\n" \
31 "c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT\n" \
32 "Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l\n" \
33 "c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee\n" \
34 "UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE\n" \
35 "Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd\n" \
36 "BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G\n" \
37 "A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF\n" \
38 "Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO\n" \
39 "VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3\n" \
40 "ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs\n" \
41 "8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR\n" \
42 "iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze\n" \
43 "Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ\n" \
44 "XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/\n" \
45 "qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB\n" \
46 "VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB\n" \
47 "L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG\n" \
48 "jjxDah2nGN59PRbxYvnKkKj9\n" \
49 "-----END CERTIFICATE-----\n";
50
51// Todoist
52String todoist_url = "https://api.todoist.com/rest/v2/tasks";
54
55// Valid till 9 July 2023
56static const char *todoist_cert = "-----BEGIN CERTIFICATE-----\n" \
57 "MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF\n" \
58 "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" \
59 "b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL\n" \
60 "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\n" \
61 "b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\n" \
62 "ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\n" \
63 "9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\n" \
64 "IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\n" \
65 "VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\n" \
66 "93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\n" \
67 "jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\n" \
68 "AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA\n" \
69 "A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI\n" \
70 "U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs\n" \
71 "N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv\n" \
72 "o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU\n" \
73 "5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy\n" \
74 "rqXRfboQnoZsG4q5WTP468SQvvG5\n" \
75 "-----END CERTIFICATE-----\n";
76
77int8_t PaperdinkUITodoListTaigaClass::fetch_data(const char *project_name, const char *project_username, const char *project_password)
78{
79 int httpCode, ret = 0;
80 String payload;
81
82 WiFiClientSecure *client = new WiFiClientSecure;
83 client->setCACert(taiga_cert);
84
85 {
86 HTTPClient https;
87 /* Authenticate with Taiga server */
88 https.begin(*client, taiga_auth_url.c_str());
89 https.addHeader("Content-Type", "application/json", 0, 0);
90
91 taiga_post_data.replace("{0}", project_username);
92 taiga_post_data.replace("{1}", project_password);
93 httpCode = https.POST(taiga_post_data);
94
95 if (httpCode == HTTP_CODE_OK) {
96 DEBUG.printf("[HTTP] AUTH SUCCESS\r\n");
97 //String payload = https.getString();
98 //Serial.println(payload);
100 parser.setListener(&taiga_todo_listener);
101 https.writeToStream(&parser);
102 } else {
103 DEBUG.printf("[HTTP] AUTH... failed, error: %s\r\n", https.errorToString(httpCode).c_str());
104 ret = -1;
105 }
106
107 https.end();
108 }
109
110 if (ret != 0) {
111 delete client;
112 return ret;
113 }
114
115 /* Get the slug */
116 taiga_slug_url.replace("{0}", project_username);
117 taiga_slug_url.replace("{1}", project_name);
118
119 {
120 HTTPClient https;
121 https.begin(*client, taiga_slug_url.c_str());
122 https.addHeader("Authorization", token, 0, 0);
123 httpCode = https.GET();
124
125 if (httpCode == HTTP_CODE_OK) {
126 DEBUG.printf("[HTTP] SLUG SUCCESS\r\n");
127 //payload = https.getString();
128 //DEBUG.println(payload);
129 ArudinoStreamParser parser;
130 parser.setListener(&taiga_todo_listener);
131 https.writeToStream(&parser);
132 } else {
133 DEBUG.printf("[HTTP] SLUG... failed, error: %s\r\n", https.errorToString(httpCode).c_str());
134 ret = -1;
135 }
136 https.end();
137 }
138
139 if (ret != 0) {
140 delete client;
141 return ret;
142 }
143
144 /* Get the tasks list */
146
147 {
148 HTTPClient https;
149 https.begin(*client, taiga_tasks_url.c_str());
150 https.addHeader("Authorization", token, 0, 0);
151 httpCode = https.GET();
152
153 if (httpCode == HTTP_CODE_OK) {
154 DEBUG.printf("[HTTP] TASKS SUCCESS\r\n");
155 //payload = https.getString();
156 //DEBUG.println(payload);
157 ArudinoStreamParser parser;
158 parser.setListener(&taiga_todo_listener);
159 https.writeToStream(&parser);
160 } else {
161 DEBUG.printf("[HTTP] TASKS... failed, error: %s\r\n", https.errorToString(httpCode).c_str());
162 }
163
164 https.end();
165 }
166
167 delete client;
168 return ret;
169}
170
172{
173 int httpCode, ret = 0;
174 String payload;
175
176 WiFiClientSecure *client = new WiFiClientSecure;
177 client->setCACert(todoist_cert);
178
179 {
180 HTTPClient https;
181 /* Authenticate with Todoist server */
182 https.begin(*client, todoist_url.c_str());
183 https.addHeader("Content-Type", "application/json", 0, 0);
184 https.addHeader("Authorization", token, 0, 0);
185
186 httpCode = https.GET();
187
188 if (httpCode == HTTP_CODE_OK) {
189 DEBUG.printf("[HTTP] AUTH SUCCESS\r\n");
190 //String payload = https.getString();
191 //Serial.println(payload);
192 ArudinoStreamParser parser;
193 parser.setListener(&todoist_todo_listener);
194 https.writeToStream(&parser);
195 } else {
196 DEBUG.printf("[HTTP] AUTH... failed, error: %d::%s\r\n", httpCode, https.errorToString(httpCode).c_str());
197 ret = -1;
198 }
199
200 https.end();
201 }
202
203 delete client;
204 return ret;
205}
206
207void PaperdinkUITodoListClass::display_list_style1(GxEPD2_GFX& display, int16_t x, int16_t y, int16_t rows, int16_t columns, uint16_t max_line_width)
208{
209 int16_t xt, yt;
210 uint16_t wt, ht, char_ht, prev_height = y, prev_width = x;
211 uint16_t i = 0, j = 0, start_height = 0;
212
213 display.setFont(font_bold);
214 display.setTextColor(primary_color);
215 display.setTextSize(1);
216
217 display.getTextBounds(F("To-Do List"), 0, 0, &xt, &yt, &wt, &ht);
218 display.setCursor(prev_width + 5, prev_height + ht);
219 prev_height += ht;
220 prev_width += 5;
221 display.println(F("To-Do List"));
222
223 display.setFont(font);
224 display.setTextColor(primary_color);
225 display.getTextBounds("W", 0, 0, &xt, &yt, &wt, &char_ht);
226
227 // Display tasks
228 start_height = prev_height + ht + 5;
229 for (j = 0; j < columns; j++) {
230 prev_height = start_height;
231 for (i = 0; i + (j * rows) < task_count && i < rows; i++) {
232 String task = tasks[i + (j * rows)];
233 uint16_t cnt = task.length();
234 do{
235 task = task.substring(0, cnt);
236 display.getTextBounds(task.c_str(), 0, 0, &xt, &yt, &wt, &ht);
237 }while (wt > max_line_width && cnt-- > 0);
238
239 DEBUG.printf("Task: %s\r\n", task.c_str());
240 display.setCursor(prev_width, prev_height);
241 display.printf("%s", task.c_str());
242 prev_height += char_ht + 7;
243 }
244 prev_width += max_line_width + 10;
245 }
246}
247
const GFXfont * font
Definition ui_base.h:9
const GFXfont * font_bold
Definition ui_base.h:10
void display_list_style1(GxEPD2_GFX &display, int16_t x, int16_t y, int16_t rows=TODO_LIST_MAX_TASKS, int16_t columns=1, uint16_t max_line_width=400)
char tasks[TODO_LIST_MAX_TASKS][TODO_LIST_MAX_TODO_STR_LENGTH+1]
Definition todo_list.h:14
int8_t fetch_data(const char *project_name, const char *project_username, const char *project_password)
Definition todo_list.cpp:77
int8_t fetch_data(const char *token)
String taiga_post_data
Definition todo_list.cpp:12
String taiga_tasks_url
Definition todo_list.cpp:11
TodoTodoistJsonListener todoist_todo_listener
Definition todo_list.cpp:53
String todoist_url
Definition todo_list.cpp:52
PaperdinkUITodoListTodoistClass Paperdink_TodoListTodoist
String taiga_auth_url
Definition todo_list.cpp:9
TodoTaigaJsonListener taiga_todo_listener
Definition todo_list.cpp:13
PaperdinkUITodoListTaigaClass Paperdink_TodoListTaiga
String taiga_slug_url
Definition todo_list.cpp:10
#define DEBUG
Definition todo_list.h:6