11/*
2- InkPlate_News for Soldered Inkplate 10
2+ Inkplate10_News_API example for Soldered Inkplate 10
3+ For this example you will need only USB cable and Inkplate 10.
4+ Select "e-radionica Inkplate10" or "Soldered Inkplate10" from Tools -> Board menu.
5+ Don't have "e-radionica Inkplate10" or "Soldered Inkplate10" option? Follow our tutorial and add it:
6+ https://soldered.com/learn/add-inkplate-6-board-definition-to-arduino-ide/
37
4- This project fetches and displays news headlines using a news API.
8+ This example will show you how you can use Inkplate 10 to display API data.
9+ Here we use News API to get headline news and short description and display
10+ them on the Inkplate screen. For this you will need an API key which you can obtain
11+ here: https://newsapi.org/
512
6- Setup:
7- 1. Enter your WiFi credentials.
8- 2. Get an API key from https://newsapi.org/ or another news provider.
13+ IMPORTANT:
14+ Make sure to change your timezone and wifi credentials below
15+ Also have ArduinoJSON installed in your Arduino libraries, download here: https://arduinojson.org/
16+
17+ Want to learn more about Inkplate? Visit www.inkplate.io
18+ Looking to get support? Write on our forums: https://forum.soldered.com/
19+ 28 July 2020 by Soldered
920*/
1021
11- #include " src/includes.h" // Include necessary libraries and dependencies
22+ // Next 3 lines are a precaution, you can ignore those, and the example would also work without them
23+ #if !defined(ARDUINO_INKPLATE10) && !defined(ARDUINO_INKPLATE10V2)
24+ #error "Wrong board selection for this example, please select e-radionica Inkplate10 or Soldered Inkplate10 in the boards menu."
25+ #endif
26+
27+ // ---------- CHANGE HERE -------------:
28+
29+ // Adjust your time zone, 2 means UTC+2
30+ int timeZone = 2 ;
31+
32+ // Put in your ssid and password
33+ char ssid[] = " Soldered-testingPurposes" ;
34+ char pass[] = " Testing443" ;
35+ char api_key_news[] = " 10fb57f24c784ee7be7a9cc419b775cc" ; // You can obtain one here: https://newsapi.org/
36+ // Also, declare the function to check if the API key is valid
37+ bool checkIfAPIKeyIsValid (char *APIKEY);
38+
39+ // ----------------------------------
40+
41+ // Include Inkplate library to the sketch
42+ #include " Inkplate.h"
1243
13- // --- WiFi Configuration ---
14- const char *ssid = " Soldered-testingPurposes" ;
15- const char *password = " Testing443" ;
44+ // Our networking functions, declared in Network.cpp
45+ #include " Network.h"
46+ #include " Inter12pt7b.h"
47+ #include " GT_Pressura16pt7b.h"
1648
17- // --- News API Configuration ---
18- String apiKey = " 10fb57f24c784ee7be7a9cc419b775cc" ;
19- String newsEndpoint = " https://newsapi.org/v2/top-headlines?country=us&apiKey=" + apiKey;
2049
21- // --- Device and Data Objects ---
22- Inkplate inkplate (INKPLATE_3BIT);
50+ // create object with all networking functions
2351Network network;
24- Gui gui (inkplate);
2552
26- // --- Deep Sleep Configuration ---
27- #define uS_TO_S_FACTOR 1000000
28- #define TIME_TO_SLEEP 600 // Sleep for 10 minutes
53+ // create display object
54+ Inkplate display (INKPLATE_1BIT);
55+
56+ // Delay between API calls in miliseconds (first 60 represents minutes so you can change to your need)
57+ #define DELAY_MS (uint32_t )60 * 60 * 1000
58+ #define DELAY_WIFI_RETRY_SECONDS 10
59+ #define DELAY_API_RETRY_SECONDS 10
60+
61+ // Variable for counting partial refreshes
62+ RTC_DATA_ATTR unsigned refreshes = 0 ;
63+
64+ // Constant to determine when to full update
65+ const int fullRefresh = 20 ;
2966
3067void setup ()
3168{
69+ // Begin serial communitcation, sed for debugging
3270 Serial.begin (115200 );
33- inkplate.begin ();
34- inkplate.clearDisplay ();
35- inkplate.setRotation (1 );
71+ // Initial display settings
72+ display.begin ();
73+ display.setTextWrap (false );
74+
75+ // Connect Inkplate to the WiFi network
76+ // Try connecting to a WiFi network.
77+ // Parameters are network SSID, password, timeout in seconds and whether to print to serial.
78+ // If the Inkplate isn't able to connect to a network stop further code execution and print an error message.
79+ if (!display.connectWiFi (ssid, pass, WIFI_TIMEOUT, true ))
80+ {
81+ // Can't connect to netowrk
82+ // Clear display for the error message
83+ display.clearDisplay ();
84+ // Set the font size;
85+ display.setTextSize (3 );
86+ // Set the cursor positions and print the text.
87+ display.setCursor ((display.width () / 2 ) - 200 , display.height () / 2 );
88+ display.print (F (" Unable to connect to " ));
89+ display.println (F (ssid));
90+ display.setCursor ((display.width () / 2 ) - 200 , (display.height () / 2 ) + 30 );
91+ display.println (F (" Please check SSID and PASS!" ));
92+ // Display the error message on the Inkplate and go to deep sleep
93+ display.display ();
94+ esp_sleep_enable_timer_wakeup (1000L * DELAY_WIFI_RETRY_SECONDS);
95+ (void )esp_deep_sleep_start ();
96+ }
97+
98+ if (!checkIfAPIKeyIsValid (api_key_news))
99+ {
100+ display.clearDisplay ();
101+ display.setTextSize (3 );
102+ display.setCursor ((display.width () / 2 ) - 200 , display.height () / 2 );
103+ display.print (F (" Your API key is invalid or incorrect." ));
104+ display.setCursor ((display.width () / 2 ) - 200 , (display.height () / 2 ) + 30 );
105+ display.println (F (" Please check your API key." ));
106+ display.display ();
107+ esp_sleep_enable_timer_wakeup (1000L * DELAY_API_RETRY_SECONDS);
108+ (void )esp_deep_sleep_start ();
109+ }
110+
111+ setTime ();
112+
113+ struct news *entities;
114+
115+ entities = network.getData ();
116+ drawNews (entities);
117+
118+ display.display ();
119+
120+ ++refreshes;
121+
122+ // Go to sleep before checking again
123+ esp_sleep_enable_timer_wakeup (1000 * DELAY_MS);
124+ (void )esp_deep_sleep_start ();
125+ }
126+
127+ void drawNews (struct news *entities)
128+ {
129+ display.setRotation (3 );
130+
131+ // Add title "World News"
132+ display.setFont (>_Pressura16pt7b); // Use a bold font for the title
133+ display.setTextSize (2 ); // Set text size for the title
134+ int textWidth = strlen (" World News" ) * 12 ; // Approximate width (12 pixels per character for GT_Pressura16pt7b)
135+ int centerX = (display.width () - textWidth) / 2 ; // Center the title horizontally
136+ display.setCursor (centerX-100 , 55 ); // Set the cursor to the calculated position
137+ display.print (" World News" );
138+
139+ // Add a dividing line below the title
140+ for (int lineY = 60 ; lineY < 65 ; lineY++) { // 5-pixel thick line
141+ display.drawLine (0 , lineY, display.width (), lineY, BLACK);
142+ }
143+
144+ display.setTextSize (1 ); // Set text size for the news items
145+ // Start rendering news items below the title
146+
147+ // Start rendering news items below the title
148+ int startY = 100 ; // Starting Y position below the title
149+ int boxHeight = 135 ; // Height of each news box
150+ int boxSpacing = 20 ; // Spacing between boxes
151+ int leftMargin = 20 ; // Left margin for the text
152+ int rightMargin = 20 ; // Right margin for the text
153+ int maxBoxes = (display.height () - startY) / (boxHeight + boxSpacing); // Calculate how many boxes fit on the screen
36154
37- // Attempt to connect to WiFi
38- const unsigned long timeout = 30000 ;
39- unsigned long startTime = millis ();
40- bool connected = false ;
155+ const int MAX_NEWS_ITEMS = 7 ;
41156
42- while (!connected && (millis () - startTime) < timeout)
157+ // Loop through the news items and display each in a box
158+ for (int i = 0 ; i < maxBoxes && i < MAX_NEWS_ITEMS && entities[i].title != NULL && entities[i].description != NULL ; i++)
43159 {
44- connected = inkplate.connectWiFi (ssid, password, 10 , true );
160+ // Calculate the position of the current box
161+ int y0 = startY + i * (boxHeight + boxSpacing);
162+ int y1 = y0 + boxHeight;
163+
164+ // Draw the title in the box
165+ display.drawTextBox (leftMargin, y0, display.width () - rightMargin, y0 + 80 , entities[i].title , 1 , >_Pressura16pt7b, 30 , false , 18 );
166+
167+ // Draw the description in the box
168+ display.drawTextBox (leftMargin, y0 + 57 , display.width () - rightMargin, y1+100 , entities[i].description , 1 , &Inter12pt7b, 30 , false , 16 );
45169 }
170+ }
46171
47- // If WiFi failed, display error message
48- if (!connected)
172+ // Function for getting time from NTP server
173+ void setTime ()
174+ {
175+ // Structure used to hold time information
176+ struct tm timeInfo;
177+ time_t nowSec;
178+ // Fetch current time in epoch format and store it
179+ display.getNTPEpoch (&nowSec);
180+ // This loop ensures that the NTP time fetched is valid and beyond a certain threshold
181+ while (nowSec < 8 * 3600 * 2 )
49182 {
50- gui.wifiError ();
183+ delay (500 );
184+ yield ();
185+ nowSec = time (nullptr );
186+ }
187+ gmtime_r (&nowSec, &timeInfo);
188+ Serial.print (F (" Current time: " ));
189+ Serial.print (asctime (&timeInfo));
190+ }
191+
192+ bool checkIfAPIKeyIsValid (char *APIKEY)
193+ {
194+ bool failed = false ;
195+ // Create the buffer for holding the API response, make it large enough just in case
196+ char *data;
197+ data = (char *)ps_malloc (50000LL );
198+
199+ // Http object used to make GET request
200+ HTTPClient http;
201+ http.getStream ().setTimeout (10 );
202+ http.getStream ().flush ();
203+ http.getStream ().setNoDelay (true );
204+
205+ // Combine the base URL and the API key to do a test call
206+ char *baseURL = " https://newsapi.org/v2/top-headlines?country=us&apiKey=" ;
207+ char apiTestURL[200 ];
208+ sprintf (apiTestURL, " %s%s" , baseURL, APIKEY);
209+
210+ http.begin (apiTestURL);
211+ delay (300 );
212+
213+ int httpCode = http.GET ();
214+
215+ if (httpCode != 200 )
216+ {
217+ Serial.println (" Your API key is invalid or incorrect." );
218+ failed = true ;
51219 }
52220 else
53221 {
54- // Fetch and display news
55- String newsData = network.fetchData (newsEndpoint);
56- if (newsData.length () > 0 )
57- {
58- gui.showNews (newsData); // Custom function to display news
59- }
60- else
61- {
62- gui.showError (" Failed to fetch news." );
63- }
222+ Serial.println (" API key OK." );
64223 }
224+ http.end ();
225+ free (data);
65226
66- // Enter deep sleep
67- esp_sleep_enable_timer_wakeup (TIME_TO_SLEEP * uS_TO_S_FACTOR);
68- esp_deep_sleep_start ();
227+ return !failed;
69228}
70229
71230void loop ()
72231{
73- // Empty, main logic is in setup
74- }
232+ // Never here
233+ }
0 commit comments