-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathESPStockTicker.h
367 lines (295 loc) · 14 KB
/
ESPStockTicker.h
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
#define VERSION 2.48
//This supports an ST7735 with a custom
//PCB or an ILI9341 screen using the
//Adafruit Featherwing and Huzzah boards
//NodeMCU ARDUINO_ESP8266_NODEMCU_ESP12E -- this assumes an ST7735 display
//Huzzah ARDUINO_ESP8266_ADAFRUIT_HUZZAH -- this assumes an ILI9341 on a Featherwing
//these get set by the IDE at build time when you pick the board
#ifdef ARDUINO_ESP8266_NODEMCU_ESP12E
#include "ST7735_REV.h"
#define SCREEN_WIDTH ST7735_TFTHEIGHT_160
#define SCREEN_HEIGHT ST7735_TFTHEIGHT_128
#include "fonts/Monospaced_plain_11.h"
#define MONOSPACED_FONT_11 Monospaced_plain_11
#define TICKER_FONT &MONOSPACED_FONT_11
#define TICKER_FONT_SIZE 1
#define HISTORICAL_TITLE_FONT &MONOSPACED_FONT_11
#define HISTORICAL_TITLE_FONT_SIZE 1
#define HISTORICAL_LABEL_FONT
#define HISTORICAL_LABEL_FONT_SIZE 1
#define HISTORICAL_LABEL_VERTICAL_OFFSET_X_AXIS 6
#define HISTORICAL_LABEL_VERTICAL_OFFSET_Y_AXIS -3
#define HISTORICAL_TITLE_POS_X 0
#define HISTORICAL_TITLE_POS_Y 10
#define HISTORICAL_CHART_VERTICAL_OFFSET 15
//#define HISTORICAL_CHART_Y_HEIGHT 80
#define TICKER_CHART_TITLE_FONT &MONOSPACED_FONT_11
#define TICKER_CHART_TITLE_FONT_SIZE 1
#define TICKER_CHART_LABEL_FONT
#define TICKER_CHART_LABEL_FONT_SIZE 1
#define TICKER_CHART_LABEL_VERTICAL_OFFSET_X_AXIS 5
#define TICKER_CHART_LABEL_VERTICAL_OFFSET_Y_AXIS -2
#define TICKER_CHART_LABEL_HORIZONTAL_OFFSET_X_AXIS -3
#define STATUS_FONT
#define STATUS_FONT_SIZE 1
#define STATUS_MSG_HEIGHT 10
#define STATUS_MSG_VERTICAL_OFFSET 2
#define MSG_LINE_SPACING 1.75
#define TICKER_ROW_HEIGHT 14
#define TICKER_TRIANGLE_BASE_ADJ -2
#define TICKER_TRIANGLE_TOP_ADJ -6
#define TICKER_TRIANGLE_WIDTH 4
//default triangle color - doubt we need it
#define ST7735_GREY 0xB5F6
#define ST7735_DIMYELLOW 0xFF36
//TFT pins
#define TFT_CS D8
#define TFT_RST D4
#define TFT_DC D3 /A0
#define TFT_BLACK ST7735_BLACK
#define TFT_WHITE ST7735_WHITE
#define TFT_GREEN ST7735_GREEN
#define TFT_RED ST7735_RED
#define TFT_YELLOW ST7735_DIMYELLOW
#define TFT_GREY ST7735_GREY
//list of mac addresses for ESPs soldered trotao screwed up Ebay screen that print backwards.
//i call them YELLOWTABS because of they had yellow tabs on the screen protectors
const int YELLOW_TAB_SIZE = 2;
const char YELLOW_TABS[YELLOW_TAB_SIZE][18] PROGMEM = { "60:01:94:74:4A:42", "68:C6:3A:9F:B6:61" };
const int YELLOW_TAB_NON_REVERSED_SIZE = 1;
const char YELLOW_TABS_NON_REVERSED[YELLOW_TAB_NON_REVERSED_SIZE][18] PROGMEM = { "BC:DD:C2:16:CA:4F" };
const int ROTATION_SIZE = 3;
//These are the bright ones. We can probably just make this the default
const char ROTATION_OVERRIDES[ROTATION_SIZE][18] PROGMEM = { "DC:4F:22:1C:2A:98", "B4:E6:2D:69:D5:0D", "BC:DD:C2:16:CA:4F" };
//calculate the number of rows we can fit in usable area
const int DISPLAY_ROWS = (SCREEN_HEIGHT - STATUS_MSG_HEIGHT) / TICKER_ROW_HEIGHT;
//screen is 160 x 128
//column value is left hand side or start of column
const int COLUMN_0 = 0; // 0 - 40 (40 px wide) SYMBOL - FIXED
const int COLUMN_1 = 40; // 40 - 105 (65 px wide) PRICE - SCALED
const int COLUMN_2 = SCREEN_WIDTH - 60; // 105 - 155 (50 px wide) % CHANGE - FIXED
const int COLUMN_3 = SCREEN_WIDTH - 48;
const int COLUMN_4 = SCREEN_WIDTH - 6; // 155 - 160 ( 5 px wide) % SYMBOL - SLIDES
//left side of chart in pixels
const int CHART_X_ORIGIN = 35;
//how many pixels between horizontal bars
const float CHART_X_SPACING = 19;
//not 7.5, because of the leading 9:30 we draw separately
const float CHART_X_WIDTH = CHART_X_SPACING * 6.5;
//top border of chart - distance from origin
const int CHART_Y_ORIGIN = 3;
//total height of chart
const int CHART_Y_HEIGHT = 100;
//how many pixels between vertical bars
const int CHART_Y_SPACING = 20;
//vertical position of chart labels - hour
const int CHART_Y_TICKER_POS = 118;
const char* TBILL_LABEL PROGMEM = "10 Year";
const char* OIL_LABEL PROGMEM = "WTI";
const char* COIN_LABEL PROGMEM = "Bitcoin";
#endif
#ifdef ARDUINO_ESP8266_ADAFRUIT_HUZZAH
#include "Generic_SPI_TFT.h"
#include "Adafruit_ILI9341.h"
#include "Adafruit_HX8357.h"
bool LARGE_SCREEN = false; //this will get set at runtime
//these are set at runtime, once we figure out
//kind of screen is connected
int SCREEN_HEIGHT = 0;
int SCREEN_WIDTH = 0;
int DISPLAY_ROWS = 0;
int CHART_Y_ORIGIN = 0;
int CHART_Y_HEIGHT = 0;
int CHART_Y_SPACING = 0;
int CHART_Y_TICKER_POS = 0;
//screen is 320 x 256
//column value is left hand side or start of column
const int COLUMN_0 = 0; // SYMBOL - FIXED
const int COLUMN_1 = 75; // PRICE - FIXED
//the rest are set at runtime
int COLUMN_1_5 = 0; // COMPANY NAME
int COLUMN_2 = 0; // ARROW - FXED
int COLUMN_3 = 0; // % CHANGE - FIXED
int COLUMN_4 = 0; // SYMBOL - SLIDES
float CHART_X_WIDTH = 0.0;
float CHART_X_SPACING = 0.0;
#include "fonts/Monospaced_plain_12.h"
#define MONOSPACED_FONT_12 Monospaced_plain_12
#include "fonts/Monospaced_plain_15.h"
#define MONOSPACED_FONT_15 Monospaced_plain_15
#include "fonts/Monospaced_plain_18.h"
#define MONOSPACED_FONT_18 Monospaced_plain_18
#define TICKER_FONT &MONOSPACED_FONT_18
#define TICKER_FONT_SIZE 1
#define HISTORICAL_TITLE_FONT &MONOSPACED_FONT_18
#define HISTORICAL_TITLE_FONT_SIZE 1
#define HISTORICAL_LABEL_FONT &MONOSPACED_FONT_15
#define HISTORICAL_LABEL_FONT_SIZE 1
#define HISTORICAL_LABEL_VERTICAL_OFFSET_X_AXIS 20
#define HISTORICAL_LABEL_VERTICAL_OFFSET_Y_AXIS 8
#define HISTORICAL_TITLE_POS_X 0
#define HISTORICAL_TITLE_POS_Y 20
#define HISTORICAL_CHART_VERTICAL_OFFSET 30
#define TICKER_CHART_TITLE_FONT &MONOSPACED_FONT_18
#define TICKER_CHART_TITLE_FONT_SIZE 1
#define TICKER_CHART_LABEL_FONT &MONOSPACED_FONT_15
#define TICKER_CHART_LABEL_FONT_SIZE 1
#define TICKER_CHART_LABEL_VERTICAL_OFFSET_X_AXIS 18
#define TICKER_CHART_LABEL_VERTICAL_OFFSET_Y_AXIS 9
#define TICKER_CHART_LABEL_HORIZONTAL_OFFSET_X_AXIS -5
#define STATUS_FONT &MONOSPACED_FONT_12
#define STATUS_FONT_SIZE 1
#define STATUS_MSG_HEIGHT 16
#define STATUS_MSG_VERTICAL_OFFSET 12
#define MSG_LINE_SPACING 1.50
//Pricing screen Settings
#define TICKER_ROW_HEIGHT 27
#define TICKER_TRIANGLE_BASE_ADJ -2
#define TICKER_TRIANGLE_TOP_ADJ -10
#define TICKER_TRIANGLE_WIDTH 8
#define TFT_CS 0
#define TFT_DC 15
#define TFT_BLACK ILI9341_BLACK
#define TFT_WHITE ILI9341_WHITE
#define TFT_GREEN ILI9341_GREEN
#define TFT_RED ILI9341_RED
#define TFT_YELLOW ILI9341_YELLOW
#define TFT_GREY ILI9341_LIGHTGREY
//Chart Settings
//left side of chart in pixels
const int CHART_X_ORIGIN = 55;
const char* TBILL_LABEL PROGMEM = "10 Year TBill";
const char* OIL_LABEL PROGMEM = "WTI";
const char* COIN_LABEL PROGMEM = "Bitcoin Price";
#endif
//SCL -> SCK -> D5
//SDA -> MOSI -> D7
//VCC +3.3V
//LED- GND
//LED+ VIN +5V
//GND GND
#define ARDUINOJSON_USE_DOUBLE 0
const int MAX_WIFI_NETWORKS = 5;
const char *WIFI_FILE PROGMEM = "/wifi.txt";
//number of 500 ms increments to wait for a connection
const int MAX_WIFI_TIMEOUT = 20;
const int HTTP_PORT = 80;
const int HTTPS_PORT = 443;
const int OTA_PORT = 8080;
char hostName [20] = "esp";
const char* SOFT_AP_NAME PROGMEM = "ESPSoftAP";
//stock ticker api and SSL fingerprint
//const char* SSL_FINGERPRINT = "D1 34 42 D6 30 58 2F 09 A0 8C 48 B6 25 B4 6C 05 69 A4 2E 4E";
const char* SETTINGS_FILE PROGMEM = "/settings.txt";
const char* IEX_KEY_FILE PROGMEM = "/iexkey.txt";
const char* OCTOPI_KEY_FILE PROGMEM = "/octopikey.txt";
const char* TICKER_FILE PROGMEM = "/tickers.txt";
const char* CHART_FILE PROGMEM = "/chart.json";
const char* PRICING_FILE PROGMEM = "/prices.json";
const char* KEY_STATS_FILE PROGMEM = "/keystats.json";
const char* TBILL_HIST_FILE PROGMEM = "/tbill.csv";
const char* COIN_HIST_FILE PROGMEM = "/coinhist.json";
const char* OIL_HIST_FILE PROGMEM = "/oilhist.csv";
const char* OCTOPI_PRINTER_FILE PROGMEM = "/octopi_printer.json";
const char* OCTOPI_JOB_FILE PROGMEM = "/octopi_job.json";
const char* FW_REMOTE_VERSION_FILE PROGMEM = "/version.remote";
const char* IEX_HOST PROGMEM = "cloud.iexapis.com";
const char* PRICING_LIST_URL PROGMEM = "GET /stable/stock/market/batch?token=%s&filter=latestPrice,companyName,changePercent&types=quote&displayPercent=true&symbols=%s HTTP/1.0\r\nHost: cloud.iexapis.com\r\nUser-Agent: ESP8266\r\nConnection: close\r\n\r\n";
//interval is number of minutes between prices
const char* BASE_CHART_URL PROGMEM = "GET /stable/stock/%s/intraday-prices?token=%s&filter=average&chartInterval=%d HTTP/1.0\r\nHost: cloud.iexapis.com\r\nUser-Agent: ESP8266\r\nConnection: close\r\n\r\n";
const char* KEY_STATS_URL PROGMEM = "GET /stable/stock/%s/stats?token=%s&filter=week52low,week52high,day200MovingAvg HTTP/1.0\r\nHost: cloud.iexapis.com\r\nUser-Agent: ESP8266\r\nConnection: close\r\n\r\n";
const char* TIME_HOST PROGMEM = "worldtimeapi.org";
const char* TIME_URL PROGMEM = "GET /api/timezone/America/Chicago HTTP/1.0\r\nHost: worldtimeapi.org\r\nUser-Agent: ESP8266\r\nConnection: close\r\n\r\n";
const char* OCTOPI_HOST PROGMEM = "octopi.local";
const char* OCTOPI_JOB_URL PROGMEM = "GET /api/job HTTP/1.0\r\nHost: octopi.local\r\nUser-Agent: ESP8266\r\nX-Api-Key: %s\r\nContent-Type': 'application/json\r\nConnection: close\r\n\r\n";
const char* OCTOPI_PRINTER_URL PROGMEM = "GET /api/printer HTTP/1.0\r\nHost: octopi.local\r\nUser-Agent: ESP8266\r\nX-Api-Key: %s\r\nContent-Type': 'application/json\r\nConnection: close\r\n\r\n";
//https://www.federalreserve.gov/datadownload/Output.aspx?rel=H15&series=bcb44e369321bfb3f&lastobs=180&from=&to=&filetype=csv&label=omit&layout=seriescolumn
const char* COIN_HOST PROGMEM = "api.coindesk.com";
const char* COIN_HIST_URL PROGMEM = "GET /v1/bpi/historical/close.json HTTP/1.0\r\nHost: api.coindesk.com\r\nUser-Agent: ESP8266\r\nConnection: close\r\n\r\n";
const char* COIN_CURR_URL PROGMEM = "GET /v1/bpi/currentprice/USD.json HTTP/1.0\r\nHost: api.coindesk.com\r\nUser-Agent: ESP8266\r\nConnection: close\r\n\r\n";
const char* FED_HOST PROGMEM = "fred.stlouisfed.org";
const char* OIL_URL PROGMEM = "GET /graph/fredgraph.csv?cosd=%s&mode=fred&id=DCOILWTICO&fq=Daily HTTP/1.0\r\nHost: fred.stlouisfed.org\r\nUser-Agent: ESP8266\r\nConnection: close\r\n\r\n";
const char* TBILL_URL PROGMEM = "GET /graph/fredgraph.csv?cosd=%s&mode=fred&id=DGS10&fq=Daily HTTP/1.0\r\nHost: fred.stlouisfed.org\r\nUser-Agent: ESP8266\r\nConnection: close\r\n\r\n";
//used to process stock selection form submission
//also used to create API GET request
const int GET_REQUEST_BUFFER_SIZE = 1000;
//https client connection timeout for API calls
const int CLIENT_TIMEOUT = 5000; //http read in ms
//where to check for firmware version
const char* FIRMWARE_HOST PROGMEM = "raw.githubusercontent.com";
const char* FW_VERSION_URL PROGMEM = "GET /brownjd/ESPStockTicker/master/data/version.txt";
const char* FW_GET_SUFFIX PROGMEM = " HTTP/1.0\r\nHost: raw.githubusercontent.com\r\nUser-Agent: ESP8266\r\nConnection: close\r\n\r\n";
//OTA update does not support HTTPS, so had to use amazon for firmware hosting
#ifdef ARDUINO_ESP8266_NODEMCU_ESP12E
const char* FW_BIN_URL PROGMEM = "http://espstockticker.s3-website-us-east-1.amazonaws.com/ESPStockTicker.ino.nodemcu.bin";
#endif
#ifdef ARDUINO_ESP8266_ADAFRUIT_HUZZAH
const char* FW_BIN_URL PROGMEM = "http://espstockticker.s3-website-us-east-1.amazonaws.com/ESPStockTicker.ino.adafruit.bin";
#endif
const int KEY_LEN = 36;
const int MAX_STRINGS = 365;
const int MAX_STRING_LEN = 11;
//this gets reused to hold temp data for the page being rendered
//pay careful attention to the data lengths.
//it needs to be cleared out before use.
char string_list[MAX_STRINGS][MAX_STRING_LEN];
float price_list[MAX_STRINGS][2]; //can hold to a set of two floats
const int MAX_TICKER_SIZE = 8;
const int TICKER_COUNT = 33;
const int TICKER_CO_SIZE = 16;
//to hold company names
char ticker_name_list[TICKER_COUNT][TICKER_CO_SIZE];
const int MAX_TBILLS = 365;
const int MAX_DATE_LEN = 11;
const int MAX_OIL_PRICES = 365;
const int MAX_COINS = 32;
//how many minutes between data points to request
const int CHART_INTERVAL = 5;
//9:30 - 4 pm = 390 minutes / increment
const int MAX_CHART_POINTS = 390 / CHART_INTERVAL;
//200 day moving average
float movingAvg = 0.0f;
float yearlow = 0.0f;
float yearhigh = 0.0f;
const int SETTINGS_NUM = 6;
const int SETTINGS_SHARES = 0;
const int SETTINGS_BITCOIN = 1;
const int SETTINGS_TBILLS = 2;
const int SETTINGS_OIL = 3;
const int SETTINGS_PRINT = 4;
const int SETTINGS_BIG_SCREEN = 5;
bool SETTINGS[SETTINGS_NUM] = {true};
//no need to keep these in a temp file since they're small
float coinprice = 0.0;
char coindate[MAX_DATE_LEN];
//re-used and cleared to make API calls for prices and chart info
char requestBuffer [GET_REQUEST_BUFFER_SIZE] = {""};
//for serving configuration pages
ESP8266WebServer httpServer(HTTP_PORT);
//how often to get new data in ms
const int MAX_STOCK_API_INTERVAL = 300000;
const int MAX_FED_API_INTERVAL = 3600000;
const int MAX_COIN_API_INTERVAL = 60000;
const int MAX_OCTOPI_API_INTERVAL = 60000;
//how often to check for new firmware in ms
const int MAX_FW_INTERVAL = 600000;
//how often to switch display pages in ms
const int MAX_PAGE_INTERVAL = 9500;
//how long to remain in AP mode before rebooting
const int MAX_AP_INTERVAL = 120000;
//how long between hour interval checks
const int MAX_TIME_INTERVAL = 900000; // every 15
//keep track of when to switch pages
elapsedMillis sincePrint;
//keep track of when to refresh data
elapsedMillis sinceStockAPIUpdate = MAX_STOCK_API_INTERVAL;
elapsedMillis sinceFedAPIUpdate = MAX_FED_API_INTERVAL;
elapsedMillis sinceCoinAPIUpdate = MAX_COIN_API_INTERVAL;
elapsedMillis sinceTimeUpdate = MAX_TIME_INTERVAL;
elapsedMillis sinceOctoPiUpdate = MAX_OCTOPI_API_INTERVAL;
//keep track of when to check for updates
elapsedMillis sinceFWUpdate = MAX_FW_INTERVAL;
ESP8266WiFiMulti wifiMulti;
int page = 0;
bool soft_AP_started = false;
static const char ERROR_MSG_INDENT[] PROGMEM = "\t\t\t\t\t\t";