Skip to content

Commit 094f5d5

Browse files
author
MOK
committed
feat:Add finnhub api
1 parent 117c65b commit 094f5d5

File tree

4 files changed

+108
-5
lines changed

4 files changed

+108
-5
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
.piolibdeps
44
.clang_complete
55
.gcc-flags.json
6+
API_TOKENS.h
67

78
.vscode/.browse.c_cpp.db*
89
.vscode/c_cpp_properties.json

README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# ESP32-S3 LVGL Yet Another Stock Price Tracker
2-
3-
A demo project for ESP32-S3 using [LVGL](https://lvgl.io/) to display real-time stock prices with WiFi configuration and persistent storage.
2+
A demo project for ESP32-S3 using [LVGL](https://lvgl.io/) to display stock prices with WiFi configuration and persistent storage.
43

54
Most other ESP32 stock price tracker projects require registering for an API account to fetch stock prices.
65

@@ -19,6 +18,13 @@ Around 80% of the code is generated by AI. The most time-consuming task was find
1918

2019
If you need a simple and straightforward API, please check `get_stock_price_all_yahoo()` in `appController.cpp`.
2120

21+
### 14-Jul-2025 updated
22+
After serveral test, the above simple API is not very stable, so inevitable to find a stabel API which need to register an account.
23+
24+
Finally, [FINNHUB](https://finnhub.io/) is a good choice which have 60 API call per 1min. That is very good for testing purpose.
25+
26+
Others have very little api call per min.
27+
2228

2329
## Screenshots & Demo
2430

@@ -60,6 +66,8 @@ Don't know why github can't show the gif. You can check the demo in below link:h
6066

6167
2. Open the project in PlatformIO.
6268

69+
3. Rename the `API_TOKENS.h.example` to `API_TOKENS.h` and fill your own FINNHUB api tokens
70+
6371
3. Build and upload to your ESP32-S3 board.
6472

6573
### Usage
@@ -74,7 +82,7 @@ Don't know why github can't show the gif. You can check the demo in below link:h
7482
```
7583
lib/
7684
appController/ # Main application logic
77-
stockPrice/ # GUI and stock price logic
85+
stockPrice/ # GUI code
7886
storage/ # Persistent storage (NVS)
7987
src/
8088
main.cpp # Entry point
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#ifndef MY_API_TOKENS_H
2+
#define MY_API_TOKENS_H
3+
4+
#define FINN_HUB_API_TOKENS "YOUR_API_TOKEN_HERE"
5+
6+
#endif

lib/appController/appController.cpp

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "freertos/FreeRTOS.h"
1313
#include "freertos/timers.h"
1414
#include <WiFiClientSecure.h>
15+
#include "API_TOKENS.h"
1516

1617
const char *rootCACertificate =
1718
"-----BEGIN CERTIFICATE-----\n"
@@ -38,6 +39,21 @@ const char *rootCACertificate =
3839
"+OkuE6N36B9K\n"
3940
"-----END CERTIFICATE-----\n";
4041

42+
const char *FINN_HUB_ROOT_CA =
43+
"-----BEGIN CERTIFICATE-----\n"
44+
"MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD\n"
45+
"VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG\n"
46+
"A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw\n"
47+
"WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz\n"
48+
"IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi\n"
49+
"AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi\n"
50+
"QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR\n"
51+
"HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW\n"
52+
"BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D\n"
53+
"9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8\n"
54+
"p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD\n"
55+
"-----END CERTIFICATE-----\n";
56+
4157
TaskHandle_t httpTaskHandle = NULL;
4258
// Add your includes here
4359
// UI event
@@ -53,6 +69,7 @@ static TimerHandle_t http_timer = NULL;
5369
String get_stock_price_yahoo(const char *symbol);
5470
void get_stock_price_all_yahoo(void);
5571
void connect_to_wifi_async(const char *ssid, const char *password);
72+
void http_get_all_stock_prices_finnhub(void);
5673

5774
static uint8_t _gui_hide_loading = 0;
5875
static uint8_t _gui_show_loading = 0;
@@ -235,12 +252,84 @@ void http_get_all_stock_prices(void)
235252
{
236253
LV_LOG_USER("HTTP GET all stock prices");
237254
_gui_show_loading = 1;
238-
get_stock_price_all_yahoo();
255+
// get_stock_price_all_yahoo();
256+
http_get_all_stock_prices_finnhub();
239257
_gui_hide_loading = 1;
240258
_gui_update_price = 1;
241259

242260
}
243261

262+
void http_get_all_stock_prices_finnhub(void)
263+
{
264+
String sprice = "N/A"; // Default value if fetching fails
265+
char (*symbols)[5] = gui_get_symbol_list();
266+
char (*prices)[10] = gui_get_price_list();
267+
if (WiFi.status() == WL_CONNECTED)
268+
{
269+
httpsClient->setCACert(FINN_HUB_ROOT_CA); // Set the root CA certificate
270+
httpsClient->setHandshakeTimeout(8000); // Set handshake timeout
271+
// httpsClient->setInsecure(); // Disable certificate validation for testing purposes (not recommended for production)
272+
for (int i = 0; i < 4; ++i)
273+
{
274+
275+
String symbol = String(symbols[i]); // Adjust based on your actual data structure
276+
Serial.printf("Fetching price for symbol: %s\n", symbol.c_str());
277+
_http_status = "Fetching " + symbol + "... ";
278+
_gui_update_http_status = 1;
279+
280+
String url = String("https://finnhub.io/api/v1/quote?symbol=") + symbol + "&token=" + String(FINN_HUB_API_TOKENS);
281+
Serial.println(url.c_str());
282+
s_http.begin(*httpsClient, url);
283+
s_http.setUserAgent("EchoapiRuntime/1.1.0");
284+
s_http.setTimeout(5000);
285+
// Start external timeout timer
286+
// start_http_timeout_timer(10000);
287+
288+
int httpCode = s_http.GET();
289+
stop_http_timeout_timer();
290+
if (httpCode == 200)
291+
{
292+
293+
String payload = s_http.getString();
294+
// Serial.println("Response: " + payload);
295+
296+
// Parse JSON
297+
JsonDocument doc;
298+
DeserializationError error = deserializeJson(doc, payload);
299+
if (!error)
300+
{
301+
float price = doc["c"];
302+
sprice = "$" + String(price, 2); // Format price to 2 decimal places
303+
strncpy(prices[i], sprice.c_str(), 10); // Store in prices array
304+
}
305+
else
306+
{
307+
Serial.println("Failed to parse JSON.");
308+
}
309+
}
310+
else
311+
{
312+
_http_status = "HTTP GET failed, error:" + httpCode;
313+
_gui_update_http_status = 1;
314+
// gui_update_loading_status(status.c_str());
315+
Serial.printf("HTTP GET failed, error: %d\n", httpCode);
316+
}
317+
}
318+
s_http.end();
319+
Serial.println("Updated stock prices:");
320+
for (int i = 0; i < 4; ++i)
321+
{
322+
Serial.printf("Symbol: %s, Price: %s\n", symbols[i], prices[i]);
323+
}
324+
}
325+
else
326+
{
327+
Serial.println("WiFi not connected");
328+
}
329+
}
330+
331+
332+
244333
void https_get_all_stock_prices(void)
245334
{
246335
String sprice = "N/A"; // Default value if fetching fails
@@ -429,7 +518,6 @@ void http_request_task(void *parameter)
429518
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
430519
LV_LOG_USER("Starting HTTP request task");
431520
// Perform HTTP request
432-
// get_stock_price_yahoo("AAPL");
433521
http_get_all_stock_prices();
434522

435523
}

0 commit comments

Comments
 (0)