Hardware components | ||||||
![]() |
| × | 1 |
Built an IoT project with Arduino, integrating Alpha Vantage API for stock data. Efficiently parsing JSON for real-time data useI recently completed my first IoT project with Arduino, focusing on web APIs. I used the Alpha Vantage API to pull stock data and learned to handle JSON responses. This involved connecting an Arduino R4 WiFi to my home network, sending HTTPS requests, and parsing JSON data to extract specific stock information. Despite initial challenges, I achieved seamless integration and effective data handling, setting the stage for more advanced projects
Here is the link to the tutorial:
https://youtu.be/--GR1fDXxak
- Reading stock quotes for three Stocks and parsing the results using tools from ArduinoJson library
- Requesting quotes for three stocks and displaying parsed result on the smal TFT 240x240 display
- Requesting 3 quotes but this time ChatGPT helped me format the parsed response on the TFT screen
- Reading stock quote for Apple and displaying received unparsed information in the serial monitor
Reading stock quotes for three Stocks and parsing the results using tools from ArduinoJson library
Arduino#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
const char* ssid = "xxxxxxx";
const char* password = "xxxxxxx";
const char* apiKey = "xxxxxxxxxx";
const char* serverName = "www.alphavantage.co";
// Define the WiFi client
WiFiClientSecure client;
void setup() {
Serial.begin(9600);
delay(10);
// Connect to Wi-Fi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println(fetchStockData("IBM"));
Serial.println(fetchStockData("AAPL"));
Serial.println(fetchStockData("TSLA"));
}
void loop() {
// Add your logic here if you need to repeat fetching data periodically
}
String roundStringToTwoDecimal(const char* valueStr) {
// Convert string to float
float value = atof(valueStr);
// Round the float to two decimal places
float roundedValue = roundf(value * 100) / 100;
// Convert rounded float back to string
return String(roundedValue, 2);
}
String fetchStockData(String stockSymbol) {
client.setInsecure(); // Use this line if you don't have the SSL fingerprint and want to ignore SSL verification
if (client.connect(serverName, 443)) { // Port 443 for HTTPS
String url = "/query?function=GLOBAL_QUOTE&symbol=" + stockSymbol + "&apikey=" + apiKey;
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + serverName + "\r\n" +
"Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return "";
}
}
//Skip HTTP headers
while (client.available()) {
String line = client.readStringUntil('\r');
if (line == "\n" || line == "\r\n") {
break;
}
}
// Read the JSON response
String payload = "";
while (client.available()) {
payload += client.readStringUntil('\r');
}
//Serial.println("Received payload:");
//Serial.println(payload);
// Parse JSON
DynamicJsonDocument doc(1024);
deserializeJson(doc, payload);
// Extract and print the desired information
const char* symbol = doc["Global Quote"]["01. symbol"];
const char* price = doc["Global Quote"]["05. price"];
const char* change = doc["Global Quote"]["10. change percent"];
// Combine the strings
return String(symbol) + " " + roundStringToTwoDecimal(price) + " " + roundStringToTwoDecimal(change) + "%" ;
client.stop();
} else {
Serial.println("Connection to server failed");
return "";
}
}
Requesting quotes for three stocks and displaying parsed result on the smal TFT 240x240 display
Arduino#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include <SPI.h>
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
// ST7789 TFT module connections
#define TFT_DC D1 // TFT DC pin is connected to NodeMCU pin D1 (GPIO5)
#define TFT_RST D2 // TFT RST pin is connected to NodeMCU pin D2 (GPIO4)
#define TFT_CS D8 // TFT CS pin is connected to NodeMCU pin D8 (GPIO15)
// Initialize ST7789 TFT library with hardware SPI module
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
// Define color constants
#define BLACK 0x0000
#define WHITE 0xFFFF
#define RED 0xF800
#define GREEN 0x07E0
#define BLUE 0x001F
// Previous state buffers
String prevPrice[3] = {"", "", ""};
String prevPercentage[3] = {"", "", ""};
const char* ssid = "xxxxxx";
const char* password = "xxxxxxx";
const char* apiKey = "xxxxxx";
//const char* stockSymbol = "VOD.LON";
const char* serverName = "www.alphavantage.co";
// Define the WiFi client
WiFiClientSecure client;
void setup() {
Serial.begin(9600);
delay(10000 );
// Connect to Wi-Fi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
//Serial.println(fetchStockData("IBM"));
//Serial.println(fetchStockData("AAPL"));
//Serial.println(fetchStockData("TSLA"));
// Initialize the display
tft.init(240, 240, SPI_MODE2); // Init ST7789 display 240x240 pixels
// Set the rotation (adjust as needed)
tft.setRotation(3);
Serial.println(F("Initialized"));
// Clear the screen
tft.fillScreen(BLACK);
String META = fetchStockData("META");
String GOOG = fetchStockData("AMZN");
String AAPL = fetchStockData("AAPL");
displayStockInfo(META, 0);
displayStockInfo(GOOG, 1);
displayStockInfo(AAPL, 2);
}
void loop(){
}
String roundStringToTwoDecimal(const char* valueStr) {
// Convert string to float
float value = atof(valueStr);
// Round the float to two decimal places
float roundedValue = roundf(value * 100) / 100;
// Convert rounded float back to string
return String(roundedValue, 2);
}
String fetchStockData(String stockSymbol) {
client.setInsecure(); // Use this line if you don't have the SSL fingerprint and want to ignore SSL verification
if (client.connect(serverName, 443)) { // Port 443 for HTTPS
String url = "/query?function=GLOBAL_QUOTE&symbol=" + stockSymbol + "&apikey=" + apiKey;
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + serverName + "\r\n" +
"Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return "";
}
}
//Skip HTTP headers
while (client.available()) {
String line = client.readStringUntil('\r');
if (line == "\n" || line == "\r\n") {
break;
}
}
// Read the JSON response
String payload = "";
while (client.available()) {
payload += client.readStringUntil('\r');
}
//Serial.println("Received payload:");
Serial.println(payload);
// Parse JSON
DynamicJsonDocument doc(1024);
deserializeJson(doc, payload);
// Extract and print the desired information
const char* symbol = doc["Global Quote"]["01. symbol"];
const char* price = doc["Global Quote"]["05. price"];
const char* change = doc["Global Quote"]["10. change percent"];
// Combine the strings
return String(symbol) + ";" + roundStringToTwoDecimal(price) + ";" + roundStringToTwoDecimal(change) + "%" ;
client.stop();
} else {
Serial.println("Connection to server failed");
return "";
}
}
void displayStockInfo(String stockInfo, int lineNumber) {
// Set the font size
tft.setTextSize(2);
if (stockInfo.indexOf("-")>0) tft.setTextColor(RED, BLACK); else tft.setTextColor(GREEN, BLACK);
// Calculate the Y position based on line number
int yPos = lineNumber * 20;
// Set the cursor to the start of the line
tft.setCursor(0, yPos);
// Print the stock info to the display
tft.print(stockInfo);
}
Requesting 3 quotes but this time ChatGPT helped me format the parsed response on the TFT screen
Arduino#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include <SPI.h>
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
// ST7789 TFT module connections
#define TFT_DC D1 // TFT DC pin is connected to NodeMCU pin D1 (GPIO5)
#define TFT_RST D2 // TFT RST pin is connected to NodeMCU pin D2 (GPIO4)
#define TFT_CS D8 // TFT CS pin is connected to NodeMCU pin D8 (GPIO15)
// Initialize ST7789 TFT library with hardware SPI module
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
// Define color constants
#define BLACK 0x0000
#define WHITE 0xFFFF
#define RED 0xF800
#define GREEN 0x07E0
#define BLUE 0x001F
// Previous state buffers
String prevPrice[3] = {"", "", ""};
String prevPercentage[3] = {"", "", ""};
const char* ssid = "xxxxxx";
const char* password = "xxxxx";
const char* apiKey = "xxxxxx";
//const char* stockSymbol = "VOD.LON";
const char* serverName = "www.alphavantage.co";
// Define the WiFi client
WiFiClientSecure client;
void setup() {
Serial.begin(9600);
delay(30000);
// Connect to Wi-Fi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// Initialize the display
tft.init(240, 240, SPI_MODE2); // Init ST7789 display 240x240 pixels
// Set the rotation (adjust as needed)
tft.setRotation(3);
Serial.println(F("Initialized"));
// Clear the screen
tft.fillScreen(BLACK);
// Draw static elements
drawStockNames();
}
void loop() {
// Add your logic here if you need to repeat fetching data periodically
String AAPL = fetchStockData("AAPL");
String AMZN = fetchStockData("AMZN");
String META = fetchStockData("META");
updateStockInfo(AAPL, 0);
updateStockInfo(AMZN, 1);
updateStockInfo(META, 2);
// for the ticker to work you have to have access to real time stock exchange data:(. If you do not have it you will be displayed one value each day
delay(60000);
}
String roundStringToTwoDecimal(const char* valueStr) {
// Convert string to float
float value = atof(valueStr);
// Round the float to two decimal places
float roundedValue = roundf(value * 100) / 100;
// Convert rounded float back to string
return String(roundedValue, 2);
}
String fetchStockData(String stockSymbol) {
client.setInsecure(); // Use this line if you don't have the SSL fingerprint and want to ignore SSL verification
if (client.connect(serverName, 443)) { // Port 443 for HTTPS
String url = "/query?function=GLOBAL_QUOTE&symbol=" + stockSymbol + "&apikey=" + apiKey;
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + serverName + "\r\n" +
"Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return "";
}
}
//Skip HTTP headers
while (client.available()) {
String line = client.readStringUntil('\r');
if (line == "\n" || line == "\r\n") {
break;
}
}
// Read the JSON response
String payload = "";
while (client.available()) {
payload += client.readStringUntil('\r');
}
//Serial.println("Received payload:");
Serial.println(payload);
// Parse JSON
DynamicJsonDocument doc(1024);
deserializeJson(doc, payload);
// Extract and print the desired information
const char* symbol = doc["Global Quote"]["01. symbol"];
const char* price = doc["Global Quote"]["05. price"];
const char* change = doc["Global Quote"]["10. change percent"];
// Combine the strings
return String(symbol) + ";" + roundStringToTwoDecimal(price) + ";" + roundStringToTwoDecimal(change) + "%" ;
client.stop();
} else {
Serial.println("Connection to server failed");
return "";
}
}
void drawStockNames() {
// Draw static stock names
drawStockName("AAPL", 0);
drawStockName("AMZN", 1);
drawStockName("META", 2);
}
void drawStockName(String stockName, int position) {
int yOffset = position * 80; // Calculate vertical offset based on position
// Define rectangle sizes and spacing
int stockRectWidth = 70;
int rectHeight = 30;
// Draw stock name rectangle
tft.fillRect(5, yOffset, stockRectWidth, rectHeight, WHITE);
tft.setCursor(10, yOffset + 8);
tft.setTextColor(BLACK);
tft.setTextSize(2);
tft.print(stockName);
}
void updateStockInfo(String stockInfo, int position) {
int yOffset = position * 80; // Calculate vertical offset based on position
// Split the stockInfo string into stockName, price, and percentage
int firstSemi = stockInfo.indexOf(';');
int secondSemi = stockInfo.indexOf(';', firstSemi + 1);
String stockName = stockInfo.substring(0, firstSemi);
String price = stockInfo.substring(firstSemi + 1, secondSemi);
String percentage = stockInfo.substring(secondSemi + 1);
// Define rectangle sizes and spacing
int rectWidth = 110;
int rectHeight = 30;
int rectSpacing = 3;
// Define colors based on percentage sign
uint16_t color = (percentage[0] == '-') ? RED : GREEN;
// Update only if there are changes
if (prevPrice[position] != price) {
// Clear the previous price
tft.fillRect(5, yOffset + rectHeight + rectSpacing, rectWidth, rectHeight, BLACK);
// Draw price rectangle
tft.fillRect(5, yOffset + rectHeight + rectSpacing, rectWidth, rectHeight, color);
tft.setCursor(10, yOffset + rectHeight + rectSpacing + 8);
tft.setTextColor((color == GREEN) ? BLACK : WHITE); // Set text color based on box color
tft.setTextSize(2);
tft.print(price);
prevPrice[position] = price;
}
if (prevPercentage[position] != percentage) {
// Clear the previous percentage
tft.fillRect(5 + rectWidth + rectSpacing, yOffset + rectHeight + rectSpacing, rectWidth, rectHeight, BLACK);
// Draw percentage rectangle
tft.fillRect(5 + rectWidth + rectSpacing, yOffset + rectHeight + rectSpacing, rectWidth, rectHeight, color);
tft.setCursor(10 + rectWidth + rectSpacing, yOffset + rectHeight + rectSpacing + 8);
tft.setTextColor((color == GREEN) ? BLACK : WHITE); // Set text color based on box color
tft.setTextSize(2);
tft.print(percentage);
prevPercentage[position] = percentage;
}
}
Reading stock quote for Apple and displaying received unparsed information in the serial monitor
ArduinoWe are reading received response ignoring control data and displaying ony Json part of the response
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
const char* ssid = "Dziubym";
const char* password = "Mikigosia1";
const char* apiKey = "C38RBEPO37T9RG1D";
const char* stockSymbol = "AAPL";
const char* serverName = "www.alphavantage.co";
// Define the WiFi client
WiFiClientSecure client;
void setup() {
Serial.begin(9600);
delay(10);
// Connect to Wi-Fi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
fetchStockData();
}
void loop() {
// Add your logic here if you need to repeat fetching data periodically
}
void fetchStockData() {
client.setInsecure(); // Use this line if you don't have the SSL fingerprint and want to ignore SSL verification
if (client.connect(serverName, 443)) { // Port 443 for HTTPS
String url = "/query?function=GLOBAL_QUOTE&symbol=" + String(stockSymbol) + "&apikey=" + apiKey;
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + serverName + "\r\n" +
"Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}
// Skip HTTP headers
while (client.available()) {
String line = client.readStringUntil('\r');
if (line == "\n" || line == "\r\n") {
break;
}
}
// Read the JSON response
String payload = "";
while (client.available()) {
payload += client.readStringUntil('\r');
}
Serial.println("Received payload:");
Serial.println(payload);
client.stop();
} else {
Serial.println("Connection to server failed");
}
}
Comments
Please log in or sign up to comment.