-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathP5_NTP_JS_FINAL.ino
417 lines (350 loc) · 15.8 KB
/
P5_NTP_JS_FINAL.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
// NodeMCU ESP8266 - P5 NTP PRAYER/SALAT TIME
#include <ESP8266WiFi.h>
#include <ezTime.h>
#include <PxMatrix.h>
#include <Ticker.h>
#include <WiFiManager.h>
#include <WiFiUdp.h>
#include <ArduinoJson.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h>
#include <Fonts/Org_01.h>
#include <Fonts/Picopixel.h>
#include <Fonts/Tiny3x3a2pt7b.h>
#include <Fonts/TomThumb.h>
// Adjustable parameters
const char* sketchName = "P5_NTP_JS_FINAL";
const char* t_zone = "Asia/Jakarta"; // See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
const char* ntp_pool = "id.pool.ntp.org"; // NTP Server pool address
const int id_kota = 1301; // See https://api.myquran.com/v2/sholat/kota/semua
const int brightness = 50; // Display brightness level
String new_hostname = "p5-ntp-js";
// Buffers for string to character conversion from JSON payload
char b_imsak[10], b_subuh[10], b_terbit[10], b_dhuha[10], b_dzuhur[10], b_ashar[10], b_maghrib[10], b_isya[10];
// day of the week (dow) and it's absolute x position array
// Bahasa Indonesia
char dow_matrix[7][10] = { "AHAD", "SENIN", "SELASA", "RABU", "KAMIS", "JUMAT", "SABTU" };
// byte dow_x_pos[7] = {48, 44, 40, 48, 44, 44, 44};
// English
// char loc_dow_array[7][10] = {"SUN","MON","TUE","WED","THU","FRI","SAT"};
// byte x_pos[7] = {16, 16, 16, 16, 16, 16, 16};
// Deutsch
// char loc_dow_array[7][10] = {"SON","MON","DIE","MIT","DON","FRE","SAM"};
// byte x_pos[7] = {16, 16, 16, 16, 16, 16, 16};
static byte prev_loc_dow = 0;
int prev_hour = -1;
int prev_minute = -1;
int sync_result, sync_age;
Timezone my_tz; // local timezone variable
time_t loc_time; // current & displayed local time
Ticker display_ticker;
// NTP Sync definitions
// NTP Sync status displayed as clock separator (:)
#define SYNC_MARGINAL 3600 // yellow if no sync for 1 hour
#define SYNC_LOST 86400 // red if no sync for 1 day
// Pin assignment for LED MATRIX
#define P_A 5 // pin A on LED MATRIX is connected to GPIO 5
#define P_B 4 // pin B on LED MATRIX is connected to GPIO 4
#define P_C 15 // pin C on LED MATRIX is connected to GPIO 15
#define P_D 12 // pin D on LED MATRIX is connected to GPIO 12
#define P_E 0 // for 1/32 scan only
#define P_LAT 16 // pin LAT on LED MATRIX is connected to GPIO 16
#define P_OE 2 // pin OE on LED MATRIX is connected to GPIO 2
// Display matrix size in pixels
#define p5_width 64
#define p5_height 32
// This defines the 'on' time of the display in us (microsecond).
// The larger this number, the brighter the display.
// If too large the ESP will crash
uint8_t display_draw_time = 40; //30-70 is usually fine
PxMATRIX p5_display(64, 32, P_LAT, P_OE, P_A, P_B, P_C, P_D);
// COLOR DEFINITION
uint16_t p5_BLACK = p5_display.color565(0, 0, 0);
uint16_t p5_WHITE = p5_display.color565(255, 255, 255);
uint16_t p5_RED = p5_display.color565(255, 0, 0);
uint16_t p5_DMRED = p5_display.color565(96, 0, 0);
uint16_t p5_GREEN = p5_display.color565(0, 255, 0);
uint16_t p5_DMGREEN = p5_display.color565(0, 128, 0);
uint16_t p5_BLUE = p5_display.color565(0, 0, 255);
uint16_t p5_YELLOW = p5_display.color565(255, 255, 0);
uint16_t p5_DMYELLOW = p5_display.color565(255, 255, 0);
uint16_t p5_CYAN = p5_display.color565(0, 255, 255);
uint16_t p5_DMCYAN = p5_display.color565(0, 128, 128);
uint16_t p5_GREY = p5_display.color565(128, 128, 128);
uint16_t p5_DMGREY = p5_display.color565(96, 96, 96);
uint16_t p5_MAGENTA = p5_display.color565(255, 0, 255);
uint16_t p5_DMMAGENTA = p5_display.color565(96, 0, 96);
// DISPLAY_UPDATER FUNCTION
void display_updater()
{
p5_display.display(display_draw_time);
}
void display_update_enable(bool is_enable)
{
if (is_enable)
display_ticker.attach(0.004, display_updater);
else
display_ticker.detach();
}
// STATIC_DISPLAY FUNCTION
void static_display()
{
p5_display.setFont(&TomThumb);
// display praying time header
p5_display.setTextSize(1); // size 1 == 8 pixels high 6 pixels wide
p5_display.setTextColor(p5_DMCYAN);
p5_display.setCursor(0, 25); // start at x=0 y=25, with 8 pixel of spacing
p5_display.print("S");
p5_display.setCursor(22, 25); // start at x=22 y=25, with 8 pixel of spacing
p5_display.print("T");
p5_display.setCursor(44, 25); // start at x=44 y=25, with 8 pixel of spacing
p5_display.print("D");
p5_display.setCursor(0, 31); // start at x=0 y=31, with 8 pixel of spacing
p5_display.print("A");
p5_display.setCursor(22, 31); // start at x=22 y=31, with 8 pixel of spacing
p5_display.print("M");
p5_display.setCursor(44, 31); // start at x=44 y=31, with 8 pixel of spacing
p5_display.print("I");
}
// NTP_CLOCK FUNCTION
void ntp_clock()
{
// sync time now
loc_time = my_tz.now();
// call ntp_status function
ntp_status();
// display clock separator ":" with ntp_status color
p5_display.setTextSize(2); // size 2 == 10 pixels high 8 pixels wide
p5_display.setTextColor(sync_result);
p5_display.fillRect(21, 8, 2, 10, p5_BLACK);
p5_display.setCursor(21, 18); // start at x=21 y=18, with 8 pixel of spacing
p5_display.print(":");
p5_display.fillRect(41, 8, 2, 10, p5_BLACK);
p5_display.setCursor(41, 18); // start at x=41 y=18, with 8 pixel of spacing
p5_display.print(":");
// display time - second (SS)
p5_display.setTextSize(2); // size 2 == 10 pixels high 8 pixels wide
p5_display.setTextColor(p5_GREY);
p5_display.fillRect(45, 8, 16, 10, p5_BLACK);
p5_display.setCursor(45, 18); // start at x=45 y=18, with 8 pixel of spacing
p5_display.printf("%02u", second(loc_time));
// display time - minute (MM)
if (prev_minute != minute(loc_time))
{
prev_minute = minute(loc_time);
p5_display.fillRect(25, 8, 16, 10, p5_BLACK);
p5_display.setCursor(25, 18); // start at x=25 y=18, with 8 pixel of spacing
p5_display.printf("%02u", minute(loc_time));
}
// display time - hour (HH)
if (prev_hour != hour(loc_time))
{
prev_hour = hour(loc_time);
p5_display.fillRect(5, 8, 16, 10, p5_BLACK);
p5_display.setCursor(5, 18); // start at x=5 y=18, with 8 pixel of spacing
p5_display.printf("%02u", hour(loc_time));
}
if (prev_loc_dow != weekday(loc_time))
{
// call jadwal_sholat function every day
jadwal_sholat();
// display day of the week (dow)
prev_loc_dow = weekday(loc_time);
p5_display.setTextSize(1); // size 1 == 8 pixels high 6 pixels wide
p5_display.setTextColor(p5_BLUE);
p5_display.fillRect(1, 1, 24, 6, p5_BLACK);
p5_display.setCursor(1, 6); // start at x=1 y=6
// p5_display.setCursor(dow_x_pos[prev_loc_dow-1], 6); // start at top left, with 8 pixel of spacing
p5_display.println(dow_matrix[prev_loc_dow - 1]);
// display date (DD/MM/YY)
p5_display.setTextSize(1); // size 1 == 8 pixels high 6 pixels wide
p5_display.setTextColor(p5_DMCYAN);
p5_display.fillRect(32, 1, 30, 6, p5_BLACK);
p5_display.setCursor(32, 6); // start at x=22 y=6, with 8 pixel of spacing
p5_display.printf("%02u/%02u/%02u", day(loc_time), month(loc_time), (year(loc_time) - 2000));
// p5_display.printf( "%02u/%02u", day(loc_time), month(loc_time) );
// display waktu sholat
p5_display.setTextSize(1); // size 1 == 8 pixels high 6 pixels wide
p5_display.setTextColor(p5_DMMAGENTA);
p5_display.fillRect(4, 20, 17, 5, p5_BLACK);
p5_display.setCursor(4, 25); // start at x=4 y=25, with 8 pixel of spacing
p5_display.print(b_subuh);
p5_display.fillRect(26, 20, 17, 5, p5_BLACK);
p5_display.setCursor(26, 25); // start at x=26 y=25, with 8 pixel of spacing
p5_display.print(b_terbit);
p5_display.fillRect(48, 20, 17, 5, p5_BLACK);
p5_display.setCursor(48, 25); // start at x=48 y=25, with 8 pixel of spacing
p5_display.print(b_dzuhur);
p5_display.fillRect(5, 26, 17, 5, p5_BLACK);
p5_display.setCursor(5, 31); // start at x=5 y=31, with 8 pixel of spacing
p5_display.print(b_ashar);
p5_display.fillRect(27, 26, 17, 5, p5_BLACK);
p5_display.setCursor(27, 31); // start at x=27 y=31, with 8 pixel of spacing
p5_display.print(b_maghrib);
p5_display.fillRect(48, 26, 17, 5, p5_BLACK);
p5_display.setCursor(48, 31); // start at x=48 y=31, with 8 pixel of spacing
p5_display.print(b_isya);
}
}
// SCROLL_TEXT FUNCTION (y, delay, text, red color, green color, blue color)
void scroll_text(uint8_t y_pos, unsigned long scroll_delay, String text, uint8_t R_color, uint8_t G_color, uint8_t B_color)
{
uint16_t text_length = text.length() + 12;
p5_display.setTextWrap(false); // we don't wrap text so it scrolls nicely
p5_display.setFont(NULL);
p5_display.setTextSize(1);
p5_display.setRotation(0);
p5_display.setTextColor(p5_display.color565(R_color, G_color, B_color));
// Asuming 5 pixel average character width
for (int x_pos = p5_width; x_pos > -(p5_width + text_length * 5); x_pos--)
{
p5_display.setTextColor(p5_display.color565(R_color, G_color, B_color));
// p5_display.clearDisplay();
p5_display.fillRect(0, y_pos, p5_width, 8, p5_BLACK);
p5_display.setCursor(x_pos, y_pos);
p5_display.println(text);
delay(scroll_delay);
yield();
}
}
// JADWAL_SHOLAT FUNCTION
void jadwal_sholat()
{
WiFiClientSecure client;
client.setInsecure(); // use with caution
client.connect("api.myquran.com", 80);
// url request construct
HTTPClient https;
String url = "https://api.myquran.com/v2/sholat/jadwal/";
url = url + id_kota + "/" + year(loc_time) + "/" + month(loc_time) + "/" + day(loc_time);
// requesting the table
https.begin(client, url);
int httpCode = https.GET();
String payload = https.getString();
// Serial.println(url);
// Serial.print(payload);
// Serial.print("\r\n\r\n");
// deserialize JSON payload
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, payload);
JsonObject results = doc["data"]["jadwal"];
String imsak = results["imsak"];
String subuh = results["subuh"];
String terbit = results["terbit"];
String dhuha = results["dhuha"];
String dzuhur = results["dzuhur"];
String ashar = results["ashar"];
String maghrib = results["maghrib"];
String isya = results["isya"];
// convert string to character
imsak.toCharArray(b_imsak, 10);
subuh.toCharArray(b_subuh, 10);
terbit.toCharArray(b_terbit, 10);
dhuha.toCharArray(b_dhuha, 10);
dzuhur.toCharArray(b_dzuhur, 10);
ashar.toCharArray(b_ashar, 10);
maghrib.toCharArray(b_maghrib, 10);
isya.toCharArray(b_isya, 10);
// on JSON deserialization error
if (error)
{
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
return;
}
}
// NTP_STATUS FUNCTION - inspired by W8BH - Bruce E. Hall - https://github.com/bhall66/NTP-clock
void ntp_status()
{
if (second() % 30) return; // update every 30 seconds
sync_age = now() - lastNtpUpdateTime(); // how long since last sync?
if (sync_age < SYNC_MARGINAL) // time is good & in sync
sync_result = p5_DMGREEN;
else if (sync_age < SYNC_LOST) // sync is 1-24 hours old
sync_result = p5_DMYELLOW;
else sync_result = p5_DMRED; // time is stale!
}
// SETUP
void setup()
{
// initializing Serial Port
Serial.begin(115200); // set serial port speed
delay(1000); // 3 seconds delay
Serial.println();
p5_display.begin(16); // Matrix Panel scan ratio (our p5 is a 1/16)
// Define multiplex implemention here {BINARY, STRAIGHT} (default is BINARY)
// p5_display.setMuxPattern(BINARY);
// Set the multiplex pattern {LINE, ZIGZAG,ZZAGG, ZAGGIZ, WZAGZIG, VZAG, ZAGZIG} (default is LINE)
// p5_display.setScanPattern(LINE);
// Rotate display
// p5_display.setRotate(true);
// Flip display
// p5_display.setFlip(true);
// Control the minimum color values that result in an active pixel
// p5_display.setColorOffset(5, 5, 5);
// Set the multiplex implemention {BINARY, STRAIGHT} (default is BINARY)
// p5_display.setMuxPattern(BINARY);
// Set the color order {RRGGBB, RRBBGG, GGRRBB, GGBBRR, BBRRGG, BBGGRR} (default is RRGGBB)
// p5_display.setColorOrder(GGRRBB);
// Set the time in microseconds that we pause after selecting each mux channel
// (May help if some rows are missing / the mux chip is too slow)
p5_display.setMuxDelay(1, 1, 1, 1, 1);
// Set the number of panels that make up the display area width (default is 1)
// p5_display.setPanelsWidth(2);
// Set the brightness of the panels (default is 255)
p5_display.setBrightness(brightness);
// Set driver chip type (default is FM6124)
// p5_display.setDriverChip(FM6124);
p5_display.clearDisplay();
p5_display.showBuffer();
display_update_enable(true);
// WiFiManager, Local initialization.
// Once its business is done, there is no need to keep it around
WiFiManager wfm;
// reset settings - wipe stored credentials for testing
// these are stored by the esp library
// wfm.resetSettings();
Serial.println("WiFi connecting");
if (!wfm.autoConnect("P5-NTP-JS")) {
// Did not connect, print error message
Serial.println("failed to connect and hit timeout");
// Reset and try again
ESP.restart();
delay(1000);
}
// Connected!
Serial.println("WiFi Connected");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
Serial.println(sketchName);
p5_display.setFont(&TomThumb);
p5_display.setTextColor(p5_GREY);
p5_display.println("WiFi Connected");
p5_display.println("IP Address:");
p5_display.println(WiFi.localIP());
p5_display.println(sketchName);
delay(5000);
p5_display.clearDisplay();
// set hostname
WiFi.setHostname(new_hostname.c_str());
// priming eztime library
setServer(ntp_pool); // set NTP server
while (timeStatus() != timeSet) // wait until ntp synced
{
events(); // allow ezTime to sync
delay(100);
}
my_tz.setLocation(t_zone);
// display scrolling text
scroll_text(12, 60, "This is NTP based Prayer/Salat Time on P5 Display Module", 32, 128, 128);
// call static_display function
static_display();
}
// MAIN LOOP
void loop()
{
if (secondChanged()) ntp_clock();
events(); // update NTP
delay(100);
}
// PROGRAM END