Compare commits
22
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07f5be6fe7 | ||
|
|
bc488d444f | ||
|
|
37b7001099 | ||
|
|
fdb214ec55 | ||
|
|
c4adc10a35 | ||
|
|
b63a139901 | ||
|
|
613970b146 | ||
|
|
2745a145ce | ||
|
|
e11aa92692 | ||
|
|
536b076f39 | ||
|
|
6c202faac5 | ||
|
|
d3b81d5793 | ||
|
|
c6360b0fb2 | ||
|
|
ae5fa17cf0 | ||
|
|
0f0c451e14 | ||
|
|
65cd974ec9 | ||
|
|
91fbcb1c8f | ||
|
|
dfd8fbb976 | ||
|
|
26e166c8dc | ||
|
|
2c8a4664a4 | ||
|
|
0bf2880d36 | ||
|
|
745445edeb |
No files matched your search
@@ -0,0 +1,3 @@
|
|||||||
|
.env
|
||||||
|
secrets.h
|
||||||
|
local_secrets.py
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
# CTA for ESP32
|
# CTA for ESP32
|
||||||
## Notes
|
## Notes
|
||||||
### CTA API interface
|
### CTA API interface
|
||||||
The CTA API can be fairly trivially queries to get a JSON response with the required metadata.
|
The CTA API can be fairly trivially queried to get a JSON response with the required metadata.
|
||||||
- Docs are available here: https://www.transitchicago.com/developers/ttdocs/
|
- Docs are available here: https://www.transitchicago.com/developers/ttdocs/
|
||||||
- API consists of two main queries
|
- API consists of two main queries
|
||||||
- 'Arrivals' - which lets you query all arrivals for a station available at https://lapi.transitchicago.com/api/1.0/ttarrivals.aspx
|
- 'Arrivals' - which lets you query all arrivals for a station available at https://lapi.transitchicago.com/api/1.0/ttarrivals.aspx
|
||||||
@@ -13,7 +13,7 @@ The CTA API can be fairly trivially queries to get a JSON response with the requ
|
|||||||
To query XML: https://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key=<KEYID>&mapid=<mapID>
|
To query XML: https://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key=<KEYID>&mapid=<mapID>
|
||||||
To query JSON: https://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key=<KEYID>&mapid=40380&outputType=JSON
|
To query JSON: https://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key=<KEYID>&mapid=40380&outputType=JSON
|
||||||
|
|
||||||
Simple HTTP POST queries use the '?' to define start of parameters, and each parameter is seperated by an '&'
|
Simple HTTP queries use the '?' to define start of parameters, and each parameter is seperated by an '&'
|
||||||
In the above, we are querying the 'ttarrivals' endpoint, used for the Arrivals API
|
In the above, we are querying the 'ttarrivals' endpoint, used for the Arrivals API
|
||||||
KEYID is your API key
|
KEYID is your API key
|
||||||
MAPID is the ID of a station on the CTA, such as "40380". These station numbers are available on the ttdocs website.
|
MAPID is the ID of a station on the CTA, such as "40380". These station numbers are available on the ttdocs website.
|
||||||
@@ -31,7 +31,7 @@ The CTA API can be fairly trivially queries to get a JSON response with the requ
|
|||||||
- `output->ctatt->eta` gives us a list of folders for all the next upcoming trains.
|
- `output->ctatt->eta` gives us a list of folders for all the next upcoming trains.
|
||||||
- `output->ctatt->eta->0` gives us the next train.
|
- `output->ctatt->eta->0` gives us the next train.
|
||||||
- `output->ctatt->eta->1` gives us the second to next train.
|
- `output->ctatt->eta->1` gives us the second to next train.
|
||||||
- `output->ctatt->eta->0-arrT` gives us the time the next train will arrive in an ISO date format, i.e. "2026-07-12T00:50:16"
|
- `output->ctatt->eta->0->arrT` gives us the time the next train will arrive in an ISO date format, i.e. "2026-07-12T00:50:16"
|
||||||
- The problem with the Arrivals API, is you then need to query every station one by one, save the next arrival time of a train and then do something with the result (say, turn on an LED if it's less than 2 minutes away).
|
- The problem with the Arrivals API, is you then need to query every station one by one, save the next arrival time of a train and then do something with the result (say, turn on an LED if it's less than 2 minutes away).
|
||||||
- That's a lot of queries to check for the entire network. Especially for a little ESP32.
|
- That's a lot of queries to check for the entire network. Especially for a little ESP32.
|
||||||
- Very wasteful and abusive of the API for just your usage.
|
- Very wasteful and abusive of the API for just your usage.
|
||||||
@@ -48,7 +48,7 @@ The CTA API can be fairly trivially queries to get a JSON response with the requ
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
- The Locations API install returns all trains along a route.
|
- The Locations API instead returns all trains along a route.
|
||||||
- In the above example, we have an array of all trains, starting at the top of the tree, we can pick each like you would in a folder. Some pseudocode:
|
- In the above example, we have an array of all trains, starting at the top of the tree, we can pick each like you would in a folder. Some pseudocode:
|
||||||
- Say return json is output.json which = https://lapi.transitchicago.com/api/1.0/ttpositions.aspx?key=<KEYID>&rt=Blue&outputType=JSON
|
- Say return json is output.json which = https://lapi.transitchicago.com/api/1.0/ttpositions.aspx?key=<KEYID>&rt=Blue&outputType=JSON
|
||||||
- `output->tmst` gives us the time we made this query, this is handy to find the current time.
|
- `output->tmst` gives us the time we made this query, this is handy to find the current time.
|
||||||
@@ -64,11 +64,11 @@ The CTA API can be fairly trivially queries to get a JSON response with the requ
|
|||||||
|
|
||||||
So example pseudocode:
|
So example pseudocode:
|
||||||
```
|
```
|
||||||
# Create a simple 2D array of all stations (imagine table with two columns) and when the next train arrives. Let's set arrival time to 999 for now (i.e. not any time soon).
|
# Create a simple 2D array of all stations (imagine table with two columns) and when the next train arrives. Let's set arrival time to 2199-01-01 for now (i.e. not any time soon).
|
||||||
# We can use the station number instead of the name to keep code simpler (don't have to deal with spaces or symbols)
|
# We can use the station number instead of the name to keep code simpler (don't have to deal with spaces or symbols)
|
||||||
stations_eta = <array>
|
stations_eta = <array>
|
||||||
stations_eta[40380] = 999
|
stations_eta[40380] = 2199-01-01
|
||||||
stations_eta[40390] = 999
|
stations_eta[40390] = 2199-01-01
|
||||||
.... etc ....
|
.... etc ....
|
||||||
|
|
||||||
# Get route data in JSON format
|
# Get route data in JSON format
|
||||||
@@ -85,30 +85,27 @@ for train in output->ctatt->route->0->train:
|
|||||||
# 'train' will now refer to the first train in the folder, aka 0.
|
# 'train' will now refer to the first train in the folder, aka 0.
|
||||||
# So we can save the next stop of the train
|
# So we can save the next stop of the train
|
||||||
next_stop = train->nextStaId
|
next_stop = train->nextStaId
|
||||||
# The time of the next stop
|
|
||||||
time_to_stop = train->arrT
|
|
||||||
# Get the time difference.
|
|
||||||
time_eta = time_to_stop - time_now
|
|
||||||
# In our made up language, this is going to be in seconds.
|
|
||||||
time_eta_mins = time_eta / 60
|
|
||||||
|
|
||||||
# Now we can update the station array from earlier
|
# The time of the next stop
|
||||||
stations_eta[next_stop] = time_eta_mins
|
station_eta[next_stop] = train->arrT
|
||||||
|
|
||||||
# The loop will now run again, but next time it will refer to the second train (aka 1)
|
# The loop will now run again, but next time it will refer to the second train (aka 1)
|
||||||
|
|
||||||
# We now have an array of all stations and the next train to arrive at them. For the ones with none any time soon, they'll still be 999 minutes away.
|
# We now have an array of all stations and the next train to arrive at them. For the ones with none any time soon, they'll still be 999 minutes away.
|
||||||
print(stations_eta[40380])
|
print(stations_eta[40380])
|
||||||
---> 6
|
---> 2026-06-06 12:11:14
|
||||||
|
|
||||||
print(stations_eta[40390])
|
print(stations_eta[40390])
|
||||||
---> 11
|
---> 2026-06-06 12:13:14
|
||||||
|
|
||||||
|
# This data can now be used to toggle LEDs based on the desired behavior.
|
||||||
```
|
```
|
||||||
|
|
||||||
### ESP32 Implementation
|
### ESP32 Implementation
|
||||||
- Micropython appears to still be poorly documented for ESP32s (especially the aliexpress clone boards).
|
- Micropython, Arduino IDE and PlatformIO are the three best options
|
||||||
- Recommendation is to use either the Arduino IDE (for quickly getting going) or using PlatformIO with VS Code.
|
- Easier programming - go with MicroPython
|
||||||
|
- Simpler setup, use either the Arduino IDE (for quickly getting going) or using PlatformIO with VS Code.
|
||||||
- Both of these are just fancy wrappers around C++ language, so plenty of documentation to google.
|
- Both of these are just fancy wrappers around C++ language, so plenty of documentation to google.
|
||||||
- The latter is harder to initially get going (mostly cause of VS Code), but it's a much nicer environment to code in than Arduino IDE.
|
- The latter is harder to initially get going (mostly cause of VS Code weirdness), but it's a much nicer environment to code in than Arduino IDE.
|
||||||
- PlatformIO is completely compatable with Arduino code, so can always start in Arduino IDE and move from there.
|
- PlatformIO is completely compatable with Arduino code, so can always start in Arduino IDE and move from there.
|
||||||
- Example PlatformIO code for the API is available in example/src/
|
- Example Arduino IDE code for the API is available in /example/src/
|
||||||
@@ -0,0 +1,243 @@
|
|||||||
|
#include "secrets.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <ArduinoJson.h> // Include ArduinoJson library
|
||||||
|
#include <HTTPClient.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
// Use HTTP instead of HTTPS for a bit more simplicity
|
||||||
|
String serverName = "http://lapi.transitchicago.com/api/1.0/ttpositions.aspx";
|
||||||
|
|
||||||
|
// Last run time for the loop, don't need to query too often, stored in milliseconds
|
||||||
|
unsigned long lastTime = 0;
|
||||||
|
// How often to query API server for updates (every 60 seconds)
|
||||||
|
unsigned long queryTime = 60*1000;
|
||||||
|
// How far away the train (in seconds) should be from the station to trigger
|
||||||
|
unsigned int time_to_led = 120;
|
||||||
|
// Current time (last API refresh time)
|
||||||
|
time_t last_api_time;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
WiFi.begin(SECRET_SSID, SECRET_PASS);
|
||||||
|
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
delay(1000);
|
||||||
|
Serial.print("Connecting to WiFi...");
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("Connected to WiFi!");
|
||||||
|
Serial.print("IP Address: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
|
||||||
|
// Setup array of stations and set a starting ETA
|
||||||
|
// This is really horrible in C/C++
|
||||||
|
struct tm def_tm;
|
||||||
|
const char* def_dt = "2199-01-01T01:01:01";
|
||||||
|
strptime(def_dt, "%Y-%m-%dT%H:%M:%S", &def_tm);
|
||||||
|
time_t def_time = mktime(&def_tm);
|
||||||
|
std::unordered_map<int, time_t> stations;
|
||||||
|
stations.insert(std::make_pair(41090, def_time)); //Monroe (Red Line)
|
||||||
|
stations.insert(std::make_pair(40820, def_time)); //Rosemont (Blue Line)
|
||||||
|
stations.insert(std::make_pair(41010, def_time)); //Rockwell (Brown Line)
|
||||||
|
stations.insert(std::make_pair(40470, def_time)); //Racine (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40190, def_time)); //Sox-35th (Red Line)
|
||||||
|
stations.insert(std::make_pair(40020, def_time)); //Harlem/Lake (Green Line)
|
||||||
|
stations.insert(std::make_pair(40900, def_time)); //Howard (Red, Purple & Yellow lines)
|
||||||
|
stations.insert(std::make_pair(41160, def_time)); //Clinton (Green & Pink lines)
|
||||||
|
stations.insert(std::make_pair(40230, def_time)); //Cumberland (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40560, def_time)); //Jackson (Red Line)
|
||||||
|
stations.insert(std::make_pair(41150, def_time)); //Kedzie (Orange Line)
|
||||||
|
stations.insert(std::make_pair(40780, def_time)); //Central Park (Pink Line)
|
||||||
|
stations.insert(std::make_pair(41080, def_time)); //47th (Green Line)
|
||||||
|
stations.insert(std::make_pair(40510, def_time)); //Garfield (Green Line)
|
||||||
|
stations.insert(std::make_pair(41050, def_time)); //Linden (Purple Line)
|
||||||
|
stations.insert(std::make_pair(40120, def_time)); //35th/Archer (Orange Line)
|
||||||
|
stations.insert(std::make_pair(40570, def_time)); //California (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40260, def_time)); //State/Lake (Brown, Green, Orange, Pink & Purple lines)
|
||||||
|
stations.insert(std::make_pair(40130, def_time)); //51st (Green Line)
|
||||||
|
stations.insert(std::make_pair(41700, def_time)); //Washington/Wabash (Brown, Green, Orange, Purple & Pink lines)
|
||||||
|
stations.insert(std::make_pair(41000, def_time)); //Cermak-Chinatown (Red Line)
|
||||||
|
stations.insert(std::make_pair(40340, def_time)); //Berwyn (Red Line)
|
||||||
|
stations.insert(std::make_pair(41690, def_time)); //Cermak-McCormick Place (Green Line)
|
||||||
|
stations.insert(std::make_pair(40490, def_time)); //Grand (Blue Line)
|
||||||
|
stations.insert(std::make_pair(41060, def_time)); //Ashland (Orange Line)
|
||||||
|
stations.insert(std::make_pair(40090, def_time)); //Damen (Brown Line)
|
||||||
|
stations.insert(std::make_pair(41280, def_time)); //Jefferson Park (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40520, def_time)); //Foster (Purple Line)
|
||||||
|
stations.insert(std::make_pair(40330, def_time)); //Grand (Red Line)
|
||||||
|
stations.insert(std::make_pair(40280, def_time)); //Central (Green Line)
|
||||||
|
stations.insert(std::make_pair(40250, def_time)); //Kedzie-Homan (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40870, def_time)); //Francisco (Brown Line)
|
||||||
|
stations.insert(std::make_pair(41240, def_time)); //Addison (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40740, def_time)); //Western (Pink Line)
|
||||||
|
stations.insert(std::make_pair(41360, def_time)); //California (Green Line)
|
||||||
|
stations.insert(std::make_pair(41400, def_time)); //Roosevelt (Red, Orange & Green lines)
|
||||||
|
stations.insert(std::make_pair(41410, def_time)); //Chicago (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40680, def_time)); //Adams/Wabash (Brown, Green, Orange, Pink & Purple lines)
|
||||||
|
stations.insert(std::make_pair(40920, def_time)); //Pulaski (Blue Line)
|
||||||
|
stations.insert(std::make_pair(41210, def_time)); //Wellington (Brown & Purple lines)
|
||||||
|
stations.insert(std::make_pair(41340, def_time)); //LaSalle (Blue Line)
|
||||||
|
stations.insert(std::make_pair(41490, def_time)); //Harrison (Red Line)
|
||||||
|
stations.insert(std::make_pair(41350, def_time)); //Oak Park (Green Line)
|
||||||
|
stations.insert(std::make_pair(40040, def_time)); //Quincy/Wells (Brown, Orange, Purple & Pink lines)
|
||||||
|
stations.insert(std::make_pair(40390, def_time)); //Forest Park (Blue Line)
|
||||||
|
stations.insert(std::make_pair(41130, def_time)); //Halsted (Orange Line)
|
||||||
|
stations.insert(std::make_pair(40960, def_time)); //Pulaski (Orange Line)
|
||||||
|
stations.insert(std::make_pair(40830, def_time)); //18th (Pink Line)
|
||||||
|
stations.insert(std::make_pair(40140, def_time)); //Dempster-Skokie (Yellow Line)
|
||||||
|
stations.insert(std::make_pair(41320, def_time)); //Belmont (Red, Brown & Purple lines)
|
||||||
|
stations.insert(std::make_pair(41660, def_time)); //Lake (Red Line)
|
||||||
|
stations.insert(std::make_pair(40910, def_time)); //63rd (Red Line)
|
||||||
|
stations.insert(std::make_pair(40690, def_time)); //Dempster (Purple Line)
|
||||||
|
stations.insert(std::make_pair(40460, def_time)); //Merchandise Mart (Brown & Purple lines)
|
||||||
|
stations.insert(std::make_pair(40710, def_time)); //Chicago (Brown & Purple lines)
|
||||||
|
stations.insert(std::make_pair(40530, def_time)); //Diversey (Brown & Purple lines)
|
||||||
|
stations.insert(std::make_pair(40850, def_time)); //Harold Washington Library-State/Van Buren (Brown, Orange, Purple & Pink lines)
|
||||||
|
stations.insert(std::make_pair(41020, def_time)); //Logan Square (Blue Line)
|
||||||
|
stations.insert(std::make_pair(41030, def_time)); //Polk (Pink Line)
|
||||||
|
stations.insert(std::make_pair(41300, def_time)); //Loyola (Red Line)
|
||||||
|
stations.insert(std::make_pair(40310, def_time)); //Western (Orange Line)
|
||||||
|
stations.insert(std::make_pair(40430, def_time)); //Clinton (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40320, def_time)); //Division (Blue Line)
|
||||||
|
stations.insert(std::make_pair(41510, def_time)); //Morgan (Green & Pink lines)
|
||||||
|
stations.insert(std::make_pair(40270, def_time)); //Main (Purple Line)
|
||||||
|
stations.insert(std::make_pair(41330, def_time)); //Montrose (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40350, def_time)); //UIC-Halsted (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40940, def_time)); //Halsted (Green Line)
|
||||||
|
stations.insert(std::make_pair(41480, def_time)); //Western (Brown Line)
|
||||||
|
stations.insert(std::make_pair(40030, def_time)); //Pulaski (Green Line)
|
||||||
|
stations.insert(std::make_pair(41190, def_time)); //Jarvis (Red Line)
|
||||||
|
stations.insert(std::make_pair(41170, def_time)); //Garfield (Red Line)
|
||||||
|
stations.insert(std::make_pair(40050, def_time)); //Davis (Purple Line)
|
||||||
|
stations.insert(std::make_pair(40750, def_time)); //Harlem (Blue Line - O'Hare Branch)
|
||||||
|
stations.insert(std::make_pair(41200, def_time)); //Argyle (Red Line)
|
||||||
|
stations.insert(std::make_pair(40440, def_time)); //California (Pink Line)
|
||||||
|
stations.insert(std::make_pair(40360, def_time)); //Southport (Brown Line)
|
||||||
|
stations.insert(std::make_pair(40760, def_time)); //Granville (Red Line)
|
||||||
|
stations.insert(std::make_pair(40480, def_time)); //Cicero (Green Line)
|
||||||
|
stations.insert(std::make_pair(40730, def_time)); //Washington/Wells (Brown, Orange, Purple & Pink lines)
|
||||||
|
stations.insert(std::make_pair(40580, def_time)); //54th/Cermak (Pink Line)
|
||||||
|
stations.insert(std::make_pair(40650, def_time)); //North/Clybourn (Red Line)
|
||||||
|
stations.insert(std::make_pair(40220, def_time)); //Western (Blue Line - Forest Park Branch)
|
||||||
|
stations.insert(std::make_pair(40070, def_time)); //Jackson (Blue Line)
|
||||||
|
stations.insert(std::make_pair(41440, def_time)); //Addison (Brown Line)
|
||||||
|
stations.insert(std::make_pair(41670, def_time)); //Conservatory (Green Line)
|
||||||
|
stations.insert(std::make_pair(40790, def_time)); //Monroe (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40180, def_time)); //Oak Park (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40400, def_time)); //Noyes (Purple Line)
|
||||||
|
stations.insert(std::make_pair(41260, def_time)); //Austin (Green Line)
|
||||||
|
stations.insert(std::make_pair(40600, def_time)); //Kostner (Pink Line)
|
||||||
|
stations.insert(std::make_pair(40670, def_time)); //Western (Blue Line - O'Hare Branch)
|
||||||
|
stations.insert(std::make_pair(40100, def_time)); //Morse (Red Line)
|
||||||
|
stations.insert(std::make_pair(40770, def_time)); //Lawrence (Red Line)
|
||||||
|
stations.insert(std::make_pair(40150, def_time)); //Pulaski (Pink Line)
|
||||||
|
stations.insert(std::make_pair(40660, def_time)); //Armitage (Brown & Purple lines)
|
||||||
|
stations.insert(std::make_pair(40540, def_time)); //Wilson (Red & Purple lines)
|
||||||
|
stations.insert(std::make_pair(40380, def_time)); //Clark/Lake (Blue, Brown, Green, Orange, Purple & Pink lines)
|
||||||
|
stations.insert(std::make_pair(40160, def_time)); //LaSalle/Van Buren (Brown, Orange, Purple & Pink lines)
|
||||||
|
stations.insert(std::make_pair(40700, def_time)); //Laramie (Green Line)
|
||||||
|
stations.insert(std::make_pair(40240, def_time)); //79th (Red Line)
|
||||||
|
stations.insert(std::make_pair(40290, def_time)); //Ashland/63rd (Green Line)
|
||||||
|
stations.insert(std::make_pair(40450, def_time)); //95th/Dan Ryan (Red Line)
|
||||||
|
stations.insert(std::make_pair(40210, def_time)); //Damen (Pink Line)
|
||||||
|
stations.insert(std::make_pair(41140, def_time)); //King Drive (Green Line)
|
||||||
|
stations.insert(std::make_pair(41710, def_time)); //Damen (Green Line)
|
||||||
|
stations.insert(std::make_pair(40980, def_time)); //Harlem (Blue Line - Forest Park Branch)
|
||||||
|
stations.insert(std::make_pair(41270, def_time)); //43rd (Green Line)
|
||||||
|
stations.insert(std::make_pair(40080, def_time)); //Sheridan (Red Line)
|
||||||
|
stations.insert(std::make_pair(40610, def_time)); //Ridgeland (Green Line)
|
||||||
|
stations.insert(std::make_pair(41070, def_time)); //Kedzie (Green Line)
|
||||||
|
stations.insert(std::make_pair(41430, def_time)); //87th (Red Line)
|
||||||
|
stations.insert(std::make_pair(41250, def_time)); //Central (Purple Line)
|
||||||
|
stations.insert(std::make_pair(40880, def_time)); //Thorndale (Red Line)
|
||||||
|
stations.insert(std::make_pair(41680, def_time)); //Oakton-Skokie (Yellow Line)
|
||||||
|
stations.insert(std::make_pair(41120, def_time)); //35th-Bronzeville-IIT (Green Line)
|
||||||
|
stations.insert(std::make_pair(41460, def_time)); //Irving Park (Brown Line)
|
||||||
|
stations.insert(std::make_pair(41220, def_time)); //Fullerton (Red, Brown & Purple lines)
|
||||||
|
stations.insert(std::make_pair(40990, def_time)); //69th (Red Line)
|
||||||
|
stations.insert(std::make_pair(41040, def_time)); //Kedzie (Pink Line)
|
||||||
|
stations.insert(std::make_pair(40800, def_time)); //Sedgwick (Brown & Purple lines)
|
||||||
|
stations.insert(std::make_pair(40060, def_time)); //Belmont (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40840, def_time)); //South Boulevard (Purple Line)
|
||||||
|
stations.insert(std::make_pair(40170, def_time)); //Ashland (Green & Pink lines)
|
||||||
|
stations.insert(std::make_pair(40810, def_time)); //Illinois Medical District (Blue Line)
|
||||||
|
stations.insert(std::make_pair(41230, def_time)); //47th (Red Line)
|
||||||
|
stations.insert(std::make_pair(41500, def_time)); //Montrose (Brown Line)
|
||||||
|
stations.insert(std::make_pair(40930, def_time)); //Midway (Orange Line)
|
||||||
|
stations.insert(std::make_pair(40550, def_time)); //Irving Park (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40370, def_time)); //Washington (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40890, def_time)); //O'Hare (Blue Line)
|
||||||
|
stations.insert(std::make_pair(40630, def_time)); //Clark/Division (Red Line)
|
||||||
|
stations.insert(std::make_pair(41420, def_time)); //Addison (Red Line)
|
||||||
|
stations.insert(std::make_pair(41290, def_time)); //Kimball (Brown Line)
|
||||||
|
stations.insert(std::make_pair(40300, def_time)); //Indiana (Green Line)
|
||||||
|
stations.insert(std::make_pair(40420, def_time)); //Cicero (Pink Line)
|
||||||
|
stations.insert(std::make_pair(40720, def_time)); //Cottage Grove (Green Line)
|
||||||
|
stations.insert(std::make_pair(41380, def_time)); //Bryn Mawr (Red Line)
|
||||||
|
stations.insert(std::make_pair(41450, def_time)); //Chicago (Red Line)
|
||||||
|
stations.insert(std::make_pair(40590, def_time)); //Damen (Blue Line)
|
||||||
|
stations.insert(std::make_pair(41180, def_time)); //Kedzie (Brown Line)
|
||||||
|
stations.insert(std::make_pair(40010, def_time)); //Austin (Blue Line)
|
||||||
|
stations.insert(std::make_pair(41310, def_time)); //Paulina (Brown Line)
|
||||||
|
stations.insert(std::make_pair(40970, def_time)); //Cicero (Blue Line)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// It's been at least 'queryTime' seconds since we last checked the API. Update the arrival times.
|
||||||
|
if ((millis() - lastTime) > queryTime) {
|
||||||
|
// Query the HTTP endpoint with a POST request and parameters, only interested in Blue route for now
|
||||||
|
const char* route = "Blue";
|
||||||
|
|
||||||
|
// http object let's us query a webserver
|
||||||
|
HTTPClient http;
|
||||||
|
|
||||||
|
String serverPath = serverName + "?key=" + SECRET_APIKEY + "&rt=" + route + "&outputType=JSON";
|
||||||
|
http.useHTTP10(true);
|
||||||
|
http.begin(serverPath.c_str());
|
||||||
|
int httpResponse = http.GET();
|
||||||
|
|
||||||
|
// Minimum size acquired from pasting raw JSON into here: https://arduinojson.org/v5/assistant/
|
||||||
|
DynamicJsonDocument location_json(9128);
|
||||||
|
deserializeJson(location_json, http.getStream());
|
||||||
|
|
||||||
|
// Store time we queried server
|
||||||
|
const char* time_c = location_json["ctatt"]["tmst"];
|
||||||
|
struct tm time_tm;
|
||||||
|
strptime(time_c, "%Y-%m-%dT%H:%M:%S", &time_tm);
|
||||||
|
last_api_time = mktime(&time_tm);
|
||||||
|
|
||||||
|
const char* nextStaID = location_json["ctatt"]["route"][0]["train"][0]["nextStaID"];
|
||||||
|
Serial.println(nextStaID);
|
||||||
|
|
||||||
|
// Move through the array to find
|
||||||
|
for (JsonObject train : location_json["ctatt"]["route"][0]["train"].as<JsonArray>()) {
|
||||||
|
// Save station ID
|
||||||
|
unsigned int station = train["nextStaId"];
|
||||||
|
const char* arrTime = train["arrT"];
|
||||||
|
// Annoying multistep process to get ISO time into time_t format
|
||||||
|
struct tm eta_tm;
|
||||||
|
strptime(arrTime, "%Y-%m-%dT%H:%M:%S", &eta_tm);
|
||||||
|
|
||||||
|
// Update next ETA for this station
|
||||||
|
stations[station] = mktime(&eta_tm);
|
||||||
|
|
||||||
|
Serial.println(stations[station])
|
||||||
|
}
|
||||||
|
|
||||||
|
lastTime = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
double difference = difftime(stations[station], last_api_time);
|
||||||
|
|
||||||
|
if(difference < time_to_led) {
|
||||||
|
String output = String("Train arriving soon at ") + stationName + " in " + difference + " seconds.";
|
||||||
|
Serial.println(output);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
delay(5000)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#define SECRET_SSID "WIFINAME"
|
||||||
|
#define SECRET_PASS "WIFIPASS"
|
||||||
|
#define SECRET_APIKEY "abcdef1234567890abcdef"
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
# Not currently used
|
||||||
|
stations = {}
|
||||||
|
stations[41090] = { 'name':' Monroe (Red Line)', 'eta':[], 'led_index':1, 'state':0 }
|
||||||
|
stations[40820] = { 'name':' Rosemont (Blue Line)', 'eta':[], 'led_index': machine.Pin(15, machine.Pin.OUT), 'state':0 }
|
||||||
|
stations[41010] = { 'name':' Rockwell (Brown Line)', 'eta':[], 'led_index':3, 'state':0 }
|
||||||
|
stations[40470] = { 'name':' Racine (Blue Line)', 'eta':[], 'led_index':4, 'state':0 }
|
||||||
|
stations[40190] = { 'name':' Sox-35th (Red Line)', 'eta':[], 'led_index':5, 'state':0 }
|
||||||
|
stations[40020] = { 'name':' Harlem/Lake (Green Line)', 'eta':[], 'led_index':6, 'state':0 }
|
||||||
|
stations[40900] = { 'name':' Howard (Red Purple & Yellow lines)', 'eta':[], 'led_index':7, 'state':0 }
|
||||||
|
stations[41160] = { 'name':' Clinton (Green & Pink lines)', 'eta':[], 'led_index':8, 'state':0 }
|
||||||
|
stations[40230] = { 'name':' Cumberland (Blue Line)', 'eta':[], 'led_index':9, 'state':0 }
|
||||||
|
stations[40560] = { 'name':' Jackson (Red Line)', 'eta':[], 'led_index':10, 'state':0 }
|
||||||
|
stations[41150] = { 'name':' Kedzie (Orange Line)', 'eta':[], 'led_index':11, 'state':0 }
|
||||||
|
stations[40780] = { 'name':' Central Park (Pink Line)', 'eta':[], 'led_index':12, 'state':0 }
|
||||||
|
stations[41080] = { 'name':' 47th (Green Line)', 'eta':[], 'led_index':13, 'state':0 }
|
||||||
|
stations[40510] = { 'name':' Garfield (Green Line)', 'eta':[], 'led_index':14, 'state':0 }
|
||||||
|
stations[41050] = { 'name':' Linden (Purple Line)', 'eta':[], 'led_index':2, 'state':0 }
|
||||||
|
stations[40120] = { 'name':' 35th/Archer (Orange Line)', 'eta':[], 'led_index':16, 'state':0 }
|
||||||
|
stations[40570] = { 'name':' California (Blue Line)', 'eta':[], 'led_index':17, 'state':0 }
|
||||||
|
stations[40260] = { 'name':' State/Lake (Brown Green Orange Pink & Purple lines)', 'eta':[], 'led_index':18, 'state':0 }
|
||||||
|
stations[40130] = { 'name':' 51st (Green Line)', 'eta':[], 'led_index':19, 'state':0 }
|
||||||
|
stations[41700] = { 'name':' Washington/Wabash (Brown Green Orange Purple & Pink lines)', 'eta':[], 'led_index':20, 'state':0 }
|
||||||
|
stations[41000] = { 'name':' Cermak-Chinatown (Red Line)', 'eta':[], 'led_index':21, 'state':0 }
|
||||||
|
stations[40340] = { 'name':' Berwyn (Red Line)', 'eta':[], 'led_index':22, 'state':0 }
|
||||||
|
stations[41690] = { 'name':' Cermak-McCormick Place (Green Line)', 'eta':[], 'led_index':23, 'state':0 }
|
||||||
|
stations[40490] = { 'name':' Grand (Blue Line)', 'eta':[], 'led_index':24, 'state':0 }
|
||||||
|
stations[41060] = { 'name':' Ashland (Orange Line)', 'eta':[], 'led_index':25, 'state':0 }
|
||||||
|
stations[40090] = { 'name':' Damen (Brown Line)', 'eta':[], 'led_index':26, 'state':0 }
|
||||||
|
stations[41280] = { 'name':' Jefferson Park (Blue Line)', 'eta':[], 'led_index':27, 'state':0 }
|
||||||
|
stations[40520] = { 'name':' Foster (Purple Line)', 'eta':[], 'led_index':28, 'state':0 }
|
||||||
|
stations[40330] = { 'name':' Grand (Red Line)', 'eta':[], 'led_index':29, 'state':0 }
|
||||||
|
stations[40280] = { 'name':' Central (Green Line)', 'eta':[], 'led_index':30, 'state':0 }
|
||||||
|
stations[40250] = { 'name':' Kedzie-Homan (Blue Line)', 'eta':[], 'led_index':31, 'state':0 }
|
||||||
|
stations[40870] = { 'name':' Francisco (Brown Line)', 'eta':[], 'led_index':32, 'state':0 }
|
||||||
|
stations[41240] = { 'name':' Addison (Blue Line)', 'eta':[], 'led_index':33, 'state':0 }
|
||||||
|
stations[40740] = { 'name':' Western (Pink Line)', 'eta':[], 'led_index':34, 'state':0 }
|
||||||
|
stations[41360] = { 'name':' California (Green Line)', 'eta':[], 'led_index':35, 'state':0 }
|
||||||
|
stations[41400] = { 'name':' Roosevelt (Red Orange & Green lines)', 'eta':[], 'led_index':36, 'state':0 }
|
||||||
|
stations[41410] = { 'name':' Chicago (Blue Line)', 'eta':[], 'led_index':37, 'state':0 }
|
||||||
|
stations[40680] = { 'name':' Adams/Wabash (Brown Green Orange Pink & Purple lines)', 'eta':[], 'led_index':38, 'state':0 }
|
||||||
|
stations[40920] = { 'name':' Pulaski (Blue Line)', 'eta':[], 'led_index':39, 'state':0 }
|
||||||
|
stations[41210] = { 'name':' Wellington (Brown & Purple lines)', 'eta':[], 'led_index':40, 'state':0 }
|
||||||
|
stations[41340] = { 'name':' LaSalle (Blue Line)', 'eta':[], 'led_index':41, 'state':0 }
|
||||||
|
stations[41490] = { 'name':' Harrison (Red Line)', 'eta':[], 'led_index':42, 'state':0 }
|
||||||
|
stations[41350] = { 'name':' Oak Park (Green Line)', 'eta':[], 'led_index':43, 'state':0 }
|
||||||
|
stations[40040] = { 'name':' Quincy/Wells (Brown Orange Purple & Pink lines)', 'eta':[], 'led_index':44, 'state':0 }
|
||||||
|
stations[40390] = { 'name':' Forest Park (Blue Line)', 'eta':[], 'led_index':45, 'state':0 }
|
||||||
|
stations[41130] = { 'name':' Halsted (Orange Line)', 'eta':[], 'led_index':46, 'state':0 }
|
||||||
|
stations[40960] = { 'name':' Pulaski (Orange Line)', 'eta':[], 'led_index':47, 'state':0 }
|
||||||
|
stations[40830] = { 'name':' 18th (Pink Line)', 'eta':[], 'led_index':48, 'state':0 }
|
||||||
|
stations[40140] = { 'name':' Dempster-Skokie (Yellow Line)', 'eta':[], 'led_index':49, 'state':0 }
|
||||||
|
stations[41320] = { 'name':' Belmont (Red Brown & Purple lines)', 'eta':[], 'led_index':50, 'state':0 }
|
||||||
|
stations[41660] = { 'name':' Lake (Red Line)', 'eta':[], 'led_index':51, 'state':0 }
|
||||||
|
stations[40910] = { 'name':' 63rd (Red Line)', 'eta':[], 'led_index':52, 'state':0 }
|
||||||
|
stations[40690] = { 'name':' Dempster (Purple Line)', 'eta':[], 'led_index':53, 'state':0 }
|
||||||
|
stations[40460] = { 'name':' Merchandise Mart (Brown & Purple lines)', 'eta':[], 'led_index':54, 'state':0 }
|
||||||
|
stations[40710] = { 'name':' Chicago (Brown & Purple lines)', 'eta':[], 'led_index':55, 'state':0 }
|
||||||
|
stations[40530] = { 'name':' Diversey (Brown & Purple lines)', 'eta':[], 'led_index':56, 'state':0 }
|
||||||
|
stations[40850] = { 'name':' Harold Washington Library-State/Van Buren (Brown Orange Purple & Pink lines)', 'eta':[], 'led_index':57, 'state':0 }
|
||||||
|
stations[41020] = { 'name':' Logan Square (Blue Line)', 'eta':[], 'led_index':58, 'state':0 }
|
||||||
|
stations[41030] = { 'name':' Polk (Pink Line)', 'eta':[], 'led_index':59, 'state':0 }
|
||||||
|
stations[41300] = { 'name':' Loyola (Red Line)', 'eta':[], 'led_index':60, 'state':0 }
|
||||||
|
stations[40310] = { 'name':' Western (Orange Line)', 'eta':[], 'led_index':61, 'state':0 }
|
||||||
|
stations[40430] = { 'name':' Clinton (Blue Line)', 'eta':[], 'led_index':62, 'state':0 }
|
||||||
|
stations[40320] = { 'name':' Division (Blue Line)', 'eta':[], 'led_index':63, 'state':0 }
|
||||||
|
stations[41510] = { 'name':' Morgan (Green & Pink lines)', 'eta':[], 'led_index':64, 'state':0 }
|
||||||
|
stations[40270] = { 'name':' Main (Purple Line)', 'eta':[], 'led_index':65, 'state':0 }
|
||||||
|
stations[41330] = { 'name':' Montrose (Blue Line)', 'eta':[], 'led_index':66, 'state':0 }
|
||||||
|
stations[40350] = { 'name':' UIC-Halsted (Blue Line)', 'eta':[], 'led_index':67, 'state':0 }
|
||||||
|
stations[40940] = { 'name':' Halsted (Green Line)', 'eta':[], 'led_index':68, 'state':0 }
|
||||||
|
stations[41480] = { 'name':' Western (Brown Line)', 'eta':[], 'led_index':69, 'state':0 }
|
||||||
|
stations[40030] = { 'name':' Pulaski (Green Line)', 'eta':[], 'led_index':70, 'state':0 }
|
||||||
|
stations[41190] = { 'name':' Jarvis (Red Line)', 'eta':[], 'led_index':71, 'state':0 }
|
||||||
|
stations[41170] = { 'name':' Garfield (Red Line)', 'eta':[], 'led_index':72, 'state':0 }
|
||||||
|
stations[40050] = { 'name':' Davis (Purple Line)', 'eta':[], 'led_index':73, 'state':0 }
|
||||||
|
stations[40750] = { 'name':' Harlem (Blue Line - OHare Branch)', 'eta':[], 'led_index':74, 'state':0 }
|
||||||
|
stations[41200] = { 'name':' Argyle (Red Line)', 'eta':[], 'led_index':75, 'state':0 }
|
||||||
|
stations[40440] = { 'name':' California (Pink Line)', 'eta':[], 'led_index':76, 'state':0 }
|
||||||
|
stations[40360] = { 'name':' Southport (Brown Line)', 'eta':[], 'led_index':77, 'state':0 }
|
||||||
|
stations[40760] = { 'name':' Granville (Red Line)', 'eta':[], 'led_index':78, 'state':0 }
|
||||||
|
stations[40480] = { 'name':' Cicero (Green Line)', 'eta':[], 'led_index':79, 'state':0 }
|
||||||
|
stations[40730] = { 'name':' Washington/Wells (Brown Orange Purple & Pink lines)', 'eta':[], 'led_index':80, 'state':0 }
|
||||||
|
stations[40580] = { 'name':' 54th/Cermak (Pink Line)', 'eta':[], 'led_index':81, 'state':0 }
|
||||||
|
stations[40650] = { 'name':' North/Clybourn (Red Line)', 'eta':[], 'led_index':82, 'state':0 }
|
||||||
|
stations[40220] = { 'name':' Western (Blue Line - Forest Park Branch)', 'eta':[], 'led_index':83, 'state':0 }
|
||||||
|
stations[40070] = { 'name':' Jackson (Blue Line)', 'eta':[], 'led_index':84, 'state':0 }
|
||||||
|
stations[41440] = { 'name':' Addison (Brown Line)', 'eta':[], 'led_index':85, 'state':0 }
|
||||||
|
stations[41670] = { 'name':' Conservatory (Green Line)', 'eta':[], 'led_index':86, 'state':0 }
|
||||||
|
stations[40790] = { 'name':' Monroe (Blue Line)', 'eta':[], 'led_index':87, 'state':0 }
|
||||||
|
stations[40180] = { 'name':' Oak Park (Blue Line)', 'eta':[], 'led_index':88, 'state':0 }
|
||||||
|
stations[40400] = { 'name':' Noyes (Purple Line)', 'eta':[], 'led_index':89, 'state':0 }
|
||||||
|
stations[41260] = { 'name':' Austin (Green Line)', 'eta':[], 'led_index':90, 'state':0 }
|
||||||
|
stations[40600] = { 'name':' Kostner (Pink Line)', 'eta':[], 'led_index':91, 'state':0 }
|
||||||
|
stations[40670] = { 'name':' Western (Blue Line - OHare Branch)', 'eta':[], 'led_index':92, 'state':0 }
|
||||||
|
stations[40100] = { 'name':' Morse (Red Line)', 'eta':[], 'led_index':93, 'state':0 }
|
||||||
|
stations[40770] = { 'name':' Lawrence (Red Line)', 'eta':[], 'led_index':94, 'state':0 }
|
||||||
|
stations[40150] = { 'name':' Pulaski (Pink Line)', 'eta':[], 'led_index':95, 'state':0 }
|
||||||
|
stations[40660] = { 'name':' Armitage (Brown & Purple lines)', 'eta':[], 'led_index':96, 'state':0 }
|
||||||
|
stations[40540] = { 'name':' Wilson (Red & Purple lines)', 'eta':[], 'led_index':97, 'state':0 }
|
||||||
|
stations[40380] = { 'name':' Clark/Lake (Blue Brown Green Orange Purple & Pink lines)', 'eta':[], 'led_index':98, 'state':0 }
|
||||||
|
stations[40160] = { 'name':' LaSalle/Van Buren (Brown Orange Purple & Pink lines)', 'eta':[], 'led_index':99, 'state':0 }
|
||||||
|
stations[40700] = { 'name':' Laramie (Green Line)', 'eta':[], 'led_index':100, 'state':0 }
|
||||||
|
stations[40240] = { 'name':' 79th (Red Line)', 'eta':[], 'led_index':101, 'state':0 }
|
||||||
|
stations[40290] = { 'name':' Ashland/63rd (Green Line)', 'eta':[], 'led_index':102, 'state':0 }
|
||||||
|
stations[40450] = { 'name':' 95th/Dan Ryan (Red Line)', 'eta':[], 'led_index':103, 'state':0 }
|
||||||
|
stations[40210] = { 'name':' Damen (Pink Line)', 'eta':[], 'led_index':104, 'state':0 }
|
||||||
|
stations[41140] = { 'name':' King Drive (Green Line)', 'eta':[], 'led_index':105, 'state':0 }
|
||||||
|
stations[41710] = { 'name':' Damen (Green Line)', 'eta':[], 'led_index':106, 'state':0 }
|
||||||
|
stations[40980] = { 'name':' Harlem (Blue Line - Forest Park Branch)', 'eta':[], 'led_index':107, 'state':0 }
|
||||||
|
stations[41270] = { 'name':' 43rd (Green Line)', 'eta':[], 'led_index':108, 'state':0 }
|
||||||
|
stations[40080] = { 'name':' Sheridan (Red Line)', 'eta':[], 'led_index':109, 'state':0 }
|
||||||
|
stations[40610] = { 'name':' Ridgeland (Green Line)', 'eta':[], 'led_index':110, 'state':0 }
|
||||||
|
stations[41070] = { 'name':' Kedzie (Green Line)', 'eta':[], 'led_index':111, 'state':0 }
|
||||||
|
stations[41430] = { 'name':' 87th (Red Line)', 'eta':[], 'led_index':112, 'state':0 }
|
||||||
|
stations[41250] = { 'name':' Central (Purple Line)', 'eta':[], 'led_index':113, 'state':0 }
|
||||||
|
stations[40880] = { 'name':' Thorndale (Red Line)', 'eta':[], 'led_index':114, 'state':0 }
|
||||||
|
stations[41680] = { 'name':' Oakton-Skokie (Yellow Line)', 'eta':[], 'led_index':115, 'state':0 }
|
||||||
|
stations[41120] = { 'name':' 35th-Bronzeville-IIT (Green Line)', 'eta':[], 'led_index':116, 'state':0 }
|
||||||
|
stations[41460] = { 'name':' Irving Park (Brown Line)', 'eta':[], 'led_index':117, 'state':0 }
|
||||||
|
stations[41220] = { 'name':' Fullerton (Red Brown & Purple lines)', 'eta':[], 'led_index':118, 'state':0 }
|
||||||
|
stations[40990] = { 'name':' 69th (Red Line)', 'eta':[], 'led_index':119, 'state':0 }
|
||||||
|
stations[41040] = { 'name':' Kedzie (Pink Line)', 'eta':[], 'led_index':120, 'state':0 }
|
||||||
|
stations[40800] = { 'name':' Sedgwick (Brown & Purple lines)', 'eta':[], 'led_index':121, 'state':0 }
|
||||||
|
stations[40060] = { 'name':' Belmont (Blue Line)', 'eta':[], 'led_index':122, 'state':0 }
|
||||||
|
stations[40840] = { 'name':' South Boulevard (Purple Line)', 'eta':[], 'led_index':123, 'state':0 }
|
||||||
|
stations[40170] = { 'name':' Ashland (Green & Pink lines)', 'eta':[], 'led_index':124, 'state':0 }
|
||||||
|
stations[40810] = { 'name':' Illinois Medical District (Blue Line)', 'eta':[], 'led_index':125, 'state':0 }
|
||||||
|
stations[41230] = { 'name':' 47th (Red Line)', 'eta':[], 'led_index':126, 'state':0 }
|
||||||
|
stations[41500] = { 'name':' Montrose (Brown Line)', 'eta':[], 'led_index':127, 'state':0 }
|
||||||
|
stations[40930] = { 'name':' Midway (Orange Line)', 'eta':[], 'led_index':128, 'state':0 }
|
||||||
|
stations[40550] = { 'name':' Irving Park (Blue Line)', 'eta':[], 'led_index':129, 'state':0 }
|
||||||
|
stations[40370] = { 'name':' Washington (Blue Line)', 'eta':[], 'led_index':130, 'state':0 }
|
||||||
|
stations[40890] = { 'name':' OHare (Blue Line)', 'eta':[], 'led_index':131, 'state':0 }
|
||||||
|
stations[40630] = { 'name':' Clark/Division (Red Line)', 'eta':[], 'led_index':132, 'state':0 }
|
||||||
|
stations[41420] = { 'name':' Addison (Red Line)', 'eta':[], 'led_index':133, 'state':0 }
|
||||||
|
stations[41290] = { 'name':' Kimball (Brown Line)', 'eta':[], 'led_index':134, 'state':0 }
|
||||||
|
stations[40300] = { 'name':' Indiana (Green Line)', 'eta':[], 'led_index':135, 'state':0 }
|
||||||
|
stations[40420] = { 'name':' Cicero (Pink Line)', 'eta':[], 'led_index':136, 'state':0 }
|
||||||
|
stations[40720] = { 'name':' Cottage Grove (Green Line)', 'eta':[], 'led_index':137, 'state':0 }
|
||||||
|
stations[41380] = { 'name':' Bryn Mawr (Red Line)', 'eta':[], 'led_index':138, 'state':0 }
|
||||||
|
stations[41450] = { 'name':' Chicago (Red Line)', 'eta':[], 'led_index':139, 'state':0 }
|
||||||
|
stations[40590] = { 'name':' Damen (Blue Line)', 'eta':[], 'led_index':140, 'state':0 }
|
||||||
|
stations[41180] = { 'name':' Kedzie (Brown Line)', 'eta':[], 'led_index':141, 'state':0 }
|
||||||
|
stations[40010] = { 'name':' Austin (Blue Line)', 'eta':[], 'led_index':142, 'state':0 }
|
||||||
|
stations[41310] = { 'name':' Paulina (Brown Line)', 'eta':[], 'led_index':143, 'state':0 }
|
||||||
|
stations[40970] = { 'name':' Cicero (Blue Line)', 'eta':[], 'led_index':144, 'state':0 }
|
||||||
@@ -0,0 +1,239 @@
|
|||||||
|
from time import time, gmtime, mktime,sleep
|
||||||
|
import network, machine, ntptime, socket, json, requests,neopixel
|
||||||
|
|
||||||
|
def time_from_iso(datetime_str):
|
||||||
|
[yyyy, mm, dd] = [int(i) for i in datetime_str.split('T')[0].split('-')]
|
||||||
|
[h,m,s] = [int(i) for i in datetime_str.split('T')[1].split(':')]
|
||||||
|
time_u = mktime((yyyy, mm, dd, h, m, s, 0, 0))
|
||||||
|
return time_u
|
||||||
|
|
||||||
|
def start_ap():
|
||||||
|
# Sets up initial captive portal for configuring wifi and basic options
|
||||||
|
ap = network.WLAN(network.AP_IF)
|
||||||
|
ap.active(True)
|
||||||
|
|
||||||
|
ap.config(
|
||||||
|
essid="CTA-Setup",
|
||||||
|
authmode=network.AUTH_OPEN
|
||||||
|
)
|
||||||
|
|
||||||
|
print("AP active for initial setup: ", ap.active())
|
||||||
|
print("AP IP address:", ap.ifconfig()[0])
|
||||||
|
|
||||||
|
return ap
|
||||||
|
|
||||||
|
def parse_form_data(body):
|
||||||
|
"""Parse URL-encoded form data"""
|
||||||
|
data = {}
|
||||||
|
pairs = body.split("&")
|
||||||
|
for pair in pairs:
|
||||||
|
if "=" in pair:
|
||||||
|
key, value = pair.split("=", 1)
|
||||||
|
# URL decode
|
||||||
|
data[key] = value.replace("+", " ").replace("%40", "@")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def save_config(data):
|
||||||
|
"""Save Wi-Fi credentials to config.json"""
|
||||||
|
if not data.get("SSID"):
|
||||||
|
raise ValueError("SSID is required")
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"SSID": data.get("SSID"),
|
||||||
|
"PASS": data.get("PASS", ""),
|
||||||
|
"APIKEY": data.get("APIKEY", ""),
|
||||||
|
"LStation": data.get("LStation", ""),
|
||||||
|
"RStation": data.get("RStation", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
with open("config.json", "w") as f:
|
||||||
|
json.dump(config, f)
|
||||||
|
|
||||||
|
print("Configuration saved:", config)
|
||||||
|
|
||||||
|
def start_http_server():
|
||||||
|
addr = socket.getaddrinfo("0.0.0.0", 80)[0][-1]
|
||||||
|
s = socket.socket()
|
||||||
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
s.bind(addr)
|
||||||
|
s.listen(1)
|
||||||
|
|
||||||
|
print("HTTP server listening on port 80")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
conn, addr = s.accept()
|
||||||
|
request = conn.recv(2048).decode()
|
||||||
|
|
||||||
|
if request.startswith("POST /save"):
|
||||||
|
# Handle form submission
|
||||||
|
body = request.split("\r\n\r\n", 1)[1]
|
||||||
|
form_data = parse_form_data(body)
|
||||||
|
save_config(form_data)
|
||||||
|
|
||||||
|
response_body = """<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Setup Complete</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: sans-serif; padding: 16px; text-align: center; }
|
||||||
|
h2 { color: #28a745; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Configuration saved</h2>
|
||||||
|
<p>Device will reboot and connect to Wi-Fi.</p>
|
||||||
|
<p><small>You can close this window.</small></p>
|
||||||
|
</body>
|
||||||
|
</html>"""
|
||||||
|
else:
|
||||||
|
# Serve the setup page for any other request
|
||||||
|
try:
|
||||||
|
with open("portal.html") as f:
|
||||||
|
response_body = f.read()
|
||||||
|
except:
|
||||||
|
response_body = "<h1>Setup Page Not Found</h1><p>Please upload portal.html</p>"
|
||||||
|
|
||||||
|
response = (
|
||||||
|
"HTTP/1.1 200 OK\r\n"
|
||||||
|
"Content-Type: text/html\r\n"
|
||||||
|
"Connection: close\r\n\r\n"
|
||||||
|
+ response_body
|
||||||
|
)
|
||||||
|
|
||||||
|
conn.send(response.encode())
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("HTTP error:", e)
|
||||||
|
try:
|
||||||
|
error = f"<h2>Error</h2><p>{e}</p>"
|
||||||
|
conn.send(
|
||||||
|
"HTTP/1.1 500 Internal Server Error\r\n"
|
||||||
|
"Content-Type: text/html\r\n"
|
||||||
|
"Connection: close\r\n\r\n"
|
||||||
|
.encode() + error.encode()
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
conn.close()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def reconnect_wifi():
|
||||||
|
while not wlan.isconnected():
|
||||||
|
try:
|
||||||
|
wlan.connect(SSID, PASS)
|
||||||
|
max_wait = 10
|
||||||
|
while max_wait > 0:
|
||||||
|
if wlan.isconnected():
|
||||||
|
break
|
||||||
|
max_wait -= 1
|
||||||
|
print('Waiting for connection...')
|
||||||
|
sleep(1)
|
||||||
|
if wlan.isconnected():
|
||||||
|
print('Connected to Wi-Fi')
|
||||||
|
print('Network config:', wlan.ifconfig())
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print('Connection error:', e)
|
||||||
|
print('Retrying connection...')
|
||||||
|
sleep(2)
|
||||||
|
|
||||||
|
# Synchronize time of RTC with NTP
|
||||||
|
last_ntp_sync = -3700 # Init as more than an hour ago
|
||||||
|
last_api_query = mktime([2000,1,1,0,0,0,0,0]) # Set last query default (will run on first run)
|
||||||
|
query_period = 120 # Query the API at most every 2 minutes
|
||||||
|
distance_on = 10 # Time from station before turning on LED
|
||||||
|
distance_half = 30 # Time from station before going 'half' on
|
||||||
|
|
||||||
|
stations = {}
|
||||||
|
|
||||||
|
# Setup Neopixel
|
||||||
|
p = machine.Pin(20) # connected on pin 20
|
||||||
|
wled = neopixel.NeoPixel(p,2)
|
||||||
|
wled[0] = (0,0,0)
|
||||||
|
wled[1] = (0,0,0)
|
||||||
|
wled.write()
|
||||||
|
|
||||||
|
# Check if already configured and load config for Wifi, API Key etc.
|
||||||
|
try:
|
||||||
|
with open("config.json", "r") as f:
|
||||||
|
config = json.load(f)
|
||||||
|
APIKEY = config["APIKEY"]
|
||||||
|
SSID = config["SSID"]
|
||||||
|
PASS = config["PASS"]
|
||||||
|
# Allocate first and second station in demo only
|
||||||
|
stations[0] = { 'id':config["LStation"], 'eta':[] }
|
||||||
|
stations[1] = { 'id':config["RStation"], 'eta':[] }
|
||||||
|
wlan = network.WLAN(network.STA_IF)
|
||||||
|
wlan.active(True)
|
||||||
|
reconnect_wifi()
|
||||||
|
|
||||||
|
# need to make below multithreaded....
|
||||||
|
#start_http_server() # Still launch server to allow changing SSID and config
|
||||||
|
demo = False
|
||||||
|
except:
|
||||||
|
# Failed to open file, launch AP mode
|
||||||
|
start_ap()
|
||||||
|
start_http_server()
|
||||||
|
|
||||||
|
# Halt waiting for config
|
||||||
|
while(True):
|
||||||
|
sleep(5)
|
||||||
|
|
||||||
|
while(True):
|
||||||
|
# Synchronise NTP time if hasn't been done in 1 hour
|
||||||
|
if (time() - last_ntp_sync) > 3600:
|
||||||
|
reconnect_wifi()
|
||||||
|
try:
|
||||||
|
ntptime.settime()
|
||||||
|
print("Time synchronized successfully")
|
||||||
|
last_ntp_sync = time()
|
||||||
|
except Exception as e:
|
||||||
|
print("Error synchronizing time:", e)
|
||||||
|
|
||||||
|
# Have we queried API in the query_period seconds?
|
||||||
|
if (time() - last_api_query) > query_period:
|
||||||
|
# Query updated API
|
||||||
|
#trains = (requests.get("https://lapi.transitchicago.com/api/1.0/ttpositions.aspx?key="+APIKEY+"&rt=Blue&outputType=JSON")).json()['ctatt']
|
||||||
|
# Query all stations
|
||||||
|
for station,dict in stations.items():
|
||||||
|
trains_s = (requests.get(f"https://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key={APIKEY}&mapid={dict['id']}&outputType=JSON")).json()['ctatt']
|
||||||
|
|
||||||
|
# Timestamps are served in local Chicago time, convert to GMT for simplicity on this side.
|
||||||
|
#print(f"Time of poll is: "+str(gmtime(time_from_iso(trains_s['tmst'])+(5*60*60))))
|
||||||
|
|
||||||
|
# Loop through all trains and update matching stations
|
||||||
|
for train in trains_s['eta']:
|
||||||
|
eta_time = time_from_iso(train['arrT'])+(5*60*60)
|
||||||
|
|
||||||
|
# Append the ETA, we rely on the station loop to remove old trains
|
||||||
|
stations[station]['eta'].append(eta_time)
|
||||||
|
|
||||||
|
|
||||||
|
last_api_query = time() # uptime polling window
|
||||||
|
|
||||||
|
# Process the ETA for each station
|
||||||
|
for station, value in stations.items(): # loop through all stations
|
||||||
|
for index, eta in enumerate(value['eta']): # multiple trains. Find old trains
|
||||||
|
if (eta - time()) < -distance_on: # Remove old trains
|
||||||
|
stations[station]['eta'].pop(index)
|
||||||
|
|
||||||
|
# Set LED state tracker to 0, if no trains, it'll stay 0.
|
||||||
|
eta = min(value['eta'])
|
||||||
|
time_from_now = eta - time()
|
||||||
|
print(f"Next train will arrive at {value['id']} in {str(time_from_now)} seconds")
|
||||||
|
if time_from_now < distance_on:
|
||||||
|
wled[station] = (255,0,0)
|
||||||
|
elif time_from_now < distance_half:
|
||||||
|
wled[station] = (255,100,0)
|
||||||
|
else:
|
||||||
|
wled[station] = (0,0,0)
|
||||||
|
|
||||||
|
# Once all LEDs updated
|
||||||
|
wled.write()
|
||||||
|
|
||||||
|
sleep(1)
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Device Setup</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
padding: 16px;
|
||||||
|
max-width: 400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-top: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
input, button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 6px;
|
||||||
|
font-size: 16px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
margin-top: 20px;
|
||||||
|
background: #007bff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
button:hover {
|
||||||
|
background: #0056b3;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Device Setup</h2>
|
||||||
|
|
||||||
|
<form method="POST" action="/save">
|
||||||
|
<label>
|
||||||
|
Wi-Fi SSID
|
||||||
|
<input name="SSID" required>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
Password
|
||||||
|
<input name="PASS" type="password">
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
CTA API Key
|
||||||
|
<input name="APIKEY">
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
Left LED Station:
|
||||||
|
<select name="LStation"><option value=41090>Monroe (Red Line)</option><option value=41010>Rockwell (Brown Line)</option><option value=40470>Racine (Blue Line)</option><option value=40190>Sox-35th (Red Line)</option><option value=40020>Harlem/Lake (Green Line)</option><option value=40900>Howard (Red Purple & Yellow lines)</option><option value=41160>Clinton (Green & Pink lines)</option><option value=40230>Cumberland (Blue Line)</option><option value=40560>Jackson (Red Line)</option><option value=41150>Kedzie (Orange Line)</option><option value=40780>Central Park (Pink Line)</option><option value=41080>47th (Green Line)</option><option value=40510>Garfield (Green Line)</option><option value=41050>Linden (Purple Line)</option><option value=40120>35th/Archer (Orange Line)</option><option value=40570>California (Blue Line)</option><option value=40260>State/Lake (Brown Green Orange Pink & Purple lines)</option><option value=40130>51st (Green Line)</option><option value=41700>Washington/Wabash (Brown Green Orange Purple & Pink lines)</option><option value=41000>Cermak-Chinatown (Red Line)</option><option value=40340>Berwyn (Red Line)</option><option value=41690>Cermak-McCormick Place (Green Line)</option><option value=40490>Grand (Blue Line)</option><option value=41060>Ashland (Orange Line)</option><option value=40090>Damen (Brown Line)</option><option value=41280>Jefferson Park (Blue Line)</option><option value=40520>Foster (Purple Line)</option><option value=40330>Grand (Red Line)</option><option value=40280>Central (Green Line)</option><option value=40250>Kedzie-Homan (Blue Line)</option><option value=40870>Francisco (Brown Line)</option><option value=41240>Addison (Blue Line)</option><option value=40740>Western (Pink Line)</option><option value=41360>California (Green Line)</option><option value=41400>Roosevelt (Red Orange & Green lines)</option><option value=41410>Chicago (Blue Line)</option><option value=40680>Adams/Wabash (Brown Green Orange Pink & Purple lines)</option><option value=40920>Pulaski (Blue Line)</option><option value=41210>Wellington (Brown & Purple lines)</option><option value=41340>LaSalle (Blue Line)</option><option value=41490>Harrison (Red Line)</option><option value=41350>Oak Park (Green Line)</option><option value=40040>Quincy/Wells (Brown Orange Purple & Pink lines)</option><option value=40390>Forest Park (Blue Line)</option><option value=41130>Halsted (Orange Line)</option><option value=40960>Pulaski (Orange Line)</option><option value=40830>18th (Pink Line)</option><option value=40140>Dempster-Skokie \xa0(Yellow Line)</option><option value=41320>Belmont (Red Brown & Purple lines)</option><option value=41660>Lake (Red Line)</option><option value=40910>63rd (Red Line)</option><option value=40690>Dempster (Purple Line)</option><option value=40460>Merchandise Mart (Brown & Purple lines)</option><option value=40710>Chicago (Brown & Purple lines)</option><option value=40530>Diversey (Brown & Purple lines)</option><option value=40850>Harold Washington Library-State/Van Buren (Brown Orange Purple & Pink lines)</option><option value=41020>Logan Square (Blue Line)</option><option value=41030>Polk (Pink Line)</option><option value=41300>Loyola (Red Line)</option><option value=40310>Western (Orange Line)</option><option value=40430>Clinton (Blue Line)</option><option value=40320>Division (Blue Line)</option><option value=41510>Morgan (Green & Pink lines)</option><option value=40270>Main (Purple Line)</option><option value=41330>Montrose (Blue Line)</option><option value=40350>UIC-Halsted (Blue Line)</option><option value=40940>Halsted (Green Line)</option><option value=41480>Western (Brown Line)</option><option value=40030>Pulaski (Green Line)</option><option value=41190>Jarvis (Red Line)</option><option value=41170>Garfield (Red Line)</option><option value=40050>Davis (Purple Line)</option><option value=40750>Harlem (Blue Line - OHare Branch)</option><option value=41200>Argyle (Red Line)</option><option value=40440>California (Pink Line)</option><option value=40360>Southport (Brown Line)</option><option value=40760>Granville (Red Line)</option><option value=40480>Cicero (Green Line)</option><option value=40730>Washington/Wells (Brown Orange Purple & Pink lines)</option><option value=40580>54th/Cermak (Pink Line)</option><option value=40650>North/Clybourn (Red Line)</option><option value=40220>Western (Blue Line - Forest Park Branch)</option><option value=40070>Jackson (Blue Line)</option><option value=41440>Addison (Brown Line)</option><option value=41670>Conservatory (Green Line)</option><option value=40790>Monroe (Blue Line)</option><option value=40180>Oak Park (Blue Line)</option><option value=40400>Noyes (Purple Line)</option><option value=41260>Austin (Green Line)</option><option value=40600>Kostner (Pink Line)</option><option value=40670>Western (Blue Line - OHare Branch)</option><option value=40100>Morse (Red Line)</option><option value=40770>Lawrence (Red Line)</option><optiLine truncated
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
Right LED Station:
|
||||||
|
<select name="RStation"><option value=41090>Monroe (Red Line)</option><option value=41010>Rockwell (Brown Line)</option><option value=40470>Racine (Blue Line)</option><option value=40190>Sox-35th (Red Line)</option><option value=40020>Harlem/Lake (Green Line)</option><option value=40900>Howard (Red Purple & Yellow lines)</option><option value=41160>Clinton (Green & Pink lines)</option><option value=40230>Cumberland (Blue Line)</option><option value=40560>Jackson (Red Line)</option><option value=41150>Kedzie (Orange Line)</option><option value=40780>Central Park (Pink Line)</option><option value=41080>47th (Green Line)</option><option value=40510>Garfield (Green Line)</option><option value=41050>Linden (Purple Line)</option><option value=40120>35th/Archer (Orange Line)</option><option value=40570>California (Blue Line)</option><option value=40260>State/Lake (Brown Green Orange Pink & Purple lines)</option><option value=40130>51st (Green Line)</option><option value=41700>Washington/Wabash (Brown Green Orange Purple & Pink lines)</option><option value=41000>Cermak-Chinatown (Red Line)</option><option value=40340>Berwyn (Red Line)</option><option value=41690>Cermak-McCormick Place (Green Line)</option><option value=40490>Grand (Blue Line)</option><option value=41060>Ashland (Orange Line)</option><option value=40090>Damen (Brown Line)</option><option value=41280>Jefferson Park (Blue Line)</option><option value=40520>Foster (Purple Line)</option><option value=40330>Grand (Red Line)</option><option value=40280>Central (Green Line)</option><option value=40250>Kedzie-Homan (Blue Line)</option><option value=40870>Francisco (Brown Line)</option><option value=41240>Addison (Blue Line)</option><option value=40740>Western (Pink Line)</option><option value=41360>California (Green Line)</option><option value=41400>Roosevelt (Red Orange & Green lines)</option><option value=41410>Chicago (Blue Line)</option><option value=40680>Adams/Wabash (Brown Green Orange Pink & Purple lines)</option><option value=40920>Pulaski (Blue Line)</option><option value=41210>Wellington (Brown & Purple lines)</option><option value=41340>LaSalle (Blue Line)</option><option value=41490>Harrison (Red Line)</option><option value=41350>Oak Park (Green Line)</option><option value=40040>Quincy/Wells (Brown Orange Purple & Pink lines)</option><option value=40390>Forest Park (Blue Line)</option><option value=41130>Halsted (Orange Line)</option><option value=40960>Pulaski (Orange Line)</option><option value=40830>18th (Pink Line)</option><option value=40140>Dempster-Skokie \xa0(Yellow Line)</option><option value=41320>Belmont (Red Brown & Purple lines)</option><option value=41660>Lake (Red Line)</option><option value=40910>63rd (Red Line)</option><option value=40690>Dempster (Purple Line)</option><option value=40460>Merchandise Mart (Brown & Purple lines)</option><option value=40710>Chicago (Brown & Purple lines)</option><option value=40530>Diversey (Brown & Purple lines)</option><option value=40850>Harold Washington Library-State/Van Buren (Brown Orange Purple & Pink lines)</option><option value=41020>Logan Square (Blue Line)</option><option value=41030>Polk (Pink Line)</option><option value=41300>Loyola (Red Line)</option><option value=40310>Western (Orange Line)</option><option value=40430>Clinton (Blue Line)</option><option value=40320>Division (Blue Line)</option><option value=41510>Morgan (Green & Pink lines)</option><option value=40270>Main (Purple Line)</option><option value=41330>Montrose (Blue Line)</option><option value=40350>UIC-Halsted (Blue Line)</option><option value=40940>Halsted (Green Line)</option><option value=41480>Western (Brown Line)</option><option value=40030>Pulaski (Green Line)</option><option value=41190>Jarvis (Red Line)</option><option value=41170>Garfield (Red Line)</option><option value=40050>Davis (Purple Line)</option><option value=40750>Harlem (Blue Line - OHare Branch)</option><option value=41200>Argyle (Red Line)</option><option value=40440>California (Pink Line)</option><option value=40360>Southport (Brown Line)</option><option value=40760>Granville (Red Line)</option><option value=40480>Cicero (Green Line)</option><option value=40730>Washington/Wells (Brown Orange Purple & Pink lines)</option><option value=40580>54th/Cermak (Pink Line)</option><option value=40650>North/Clybourn (Red Line)</option><option value=40220>Western (Blue Line - Forest Park Branch)</option><option value=40070>Jackson (Blue Line)</option><option value=41440>Addison (Brown Line)</option><option value=41670>Conservatory (Green Line)</option><option value=40790>Monroe (Blue Line)</option><option value=40180>Oak Park (Blue Line)</option><option value=40400>Noyes (Purple Line)</option><option value=41260>Austin (Green Line)</option><option value=40600>Kostner (Pink Line)</option><option value=40670>Western (Blue Line - OHare Branch)</option><option value=40100>Morse (Red Line)</option><option value=40770>Lawrence (Red Line)</option><optiLine truncated
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<button type="submit">Save & Connect</button>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"author": "Isaac",
|
||||||
|
"editor": "wokwi",
|
||||||
|
"parts": [
|
||||||
|
{ "type": "board-esp32-devkit-c-v4", "id": "esp", "top": -37.58, "left": -96.37, "attrs": {} },
|
||||||
|
{ "type": "wokwi-led", "id": "led1", "top": -61.2, "left": 61.4, "attrs": { "color": "red" } }
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
[ "esp:TX", "$serialMonitor:RX", "", [] ],
|
||||||
|
[ "esp:RX", "$serialMonitor:TX", "", [] ],
|
||||||
|
[ "led1:C", "esp:GND.2", "green", [ "v0" ] ],
|
||||||
|
[ "led1:A", "esp:15", "green", [ "v0" ] ]
|
||||||
|
],
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
SSID = "Wokwi-GUEST"
|
||||||
|
PASS = ""
|
||||||
|
APIKEY = "abcdef1234567890abcdef"
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
import requests
|
||||||
|
from time import time, gmtime, mktime,sleep
|
||||||
|
import network
|
||||||
|
import local_secrets
|
||||||
|
import machine
|
||||||
|
import ntptime
|
||||||
|
|
||||||
|
APIKEY = local_secrets.APIKEY
|
||||||
|
SSID = local_secrets.SSID
|
||||||
|
PASS = local_secrets.PASS
|
||||||
|
|
||||||
|
def time_from_iso(datetime_str):
|
||||||
|
[yyyy, mm, dd] = [int(i) for i in datetime_str.split('T')[0].split('-')]
|
||||||
|
[h,m,s] = [int(i) for i in datetime_str.split('T')[1].split(':')]
|
||||||
|
time_u = mktime((yyyy, mm, dd, h, m, s, 0, 0))
|
||||||
|
return time_u
|
||||||
|
|
||||||
|
def reconnect_wifi():
|
||||||
|
while not wlan.isconnected():
|
||||||
|
try:
|
||||||
|
wlan.connect(SSID, PASS)
|
||||||
|
max_wait = 10
|
||||||
|
while max_wait > 0:
|
||||||
|
if wlan.isconnected():
|
||||||
|
break
|
||||||
|
max_wait -= 1
|
||||||
|
print('Waiting for connection...')
|
||||||
|
sleep(1)
|
||||||
|
if wlan.isconnected():
|
||||||
|
print('Connected to Wi-Fi')
|
||||||
|
print('Network config:', wlan.ifconfig())
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print('Connection error:', e)
|
||||||
|
print('Retrying connection...')
|
||||||
|
sleep(2)
|
||||||
|
|
||||||
|
def init_LEDs():
|
||||||
|
# Sets up LEDs and their ports.
|
||||||
|
led = machine.Pin(15, machine.Pin.OUT)
|
||||||
|
led.off()
|
||||||
|
|
||||||
|
# Connect Wifi
|
||||||
|
# Create network in station mode, activate it and connect
|
||||||
|
wlan = network.WLAN(network.STA_IF)
|
||||||
|
|
||||||
|
wlan.active(True)
|
||||||
|
reconnect_wifi()
|
||||||
|
|
||||||
|
# Synchronize time of RTC with NTP
|
||||||
|
last_ntp_sync = -3700 # Init as more than an hour ago
|
||||||
|
last_api_query = mktime([2000,1,1,0,0,0,0,0]) # Set last query default (will run on first run)
|
||||||
|
query_period = 120 # Query the API at most every 2 minutes
|
||||||
|
distance_on = 10 # Time from station before turning on LED
|
||||||
|
|
||||||
|
# Stations dictionary contains name, the ETA of all trains as an array, the LED index of the light and the LED state
|
||||||
|
stations = {}
|
||||||
|
stations[41090] = { 'name':' Monroe (Red Line)', 'eta':[], 'led_index':1, 'state':0 }
|
||||||
|
stations[40820] = { 'name':' Rosemont (Blue Line)', 'eta':[], 'led_index': machine.Pin(15, machine.Pin.OUT), 'state':0 }
|
||||||
|
stations[41010] = { 'name':' Rockwell (Brown Line)', 'eta':[], 'led_index':3, 'state':0 }
|
||||||
|
stations[40470] = { 'name':' Racine (Blue Line)', 'eta':[], 'led_index':4, 'state':0 }
|
||||||
|
stations[40190] = { 'name':' Sox-35th (Red Line)', 'eta':[], 'led_index':5, 'state':0 }
|
||||||
|
stations[40020] = { 'name':' Harlem/Lake (Green Line)', 'eta':[], 'led_index':6, 'state':0 }
|
||||||
|
stations[40900] = { 'name':' Howard (Red Purple & Yellow lines)', 'eta':[], 'led_index':7, 'state':0 }
|
||||||
|
stations[41160] = { 'name':' Clinton (Green & Pink lines)', 'eta':[], 'led_index':8, 'state':0 }
|
||||||
|
stations[40230] = { 'name':' Cumberland (Blue Line)', 'eta':[], 'led_index':9, 'state':0 }
|
||||||
|
stations[40560] = { 'name':' Jackson (Red Line)', 'eta':[], 'led_index':10, 'state':0 }
|
||||||
|
stations[41150] = { 'name':' Kedzie (Orange Line)', 'eta':[], 'led_index':11, 'state':0 }
|
||||||
|
stations[40780] = { 'name':' Central Park (Pink Line)', 'eta':[], 'led_index':12, 'state':0 }
|
||||||
|
stations[41080] = { 'name':' 47th (Green Line)', 'eta':[], 'led_index':13, 'state':0 }
|
||||||
|
stations[40510] = { 'name':' Garfield (Green Line)', 'eta':[], 'led_index':14, 'state':0 }
|
||||||
|
stations[41050] = { 'name':' Linden (Purple Line)', 'eta':[], 'led_index':2, 'state':0 }
|
||||||
|
stations[40120] = { 'name':' 35th/Archer (Orange Line)', 'eta':[], 'led_index':16, 'state':0 }
|
||||||
|
stations[40570] = { 'name':' California (Blue Line)', 'eta':[], 'led_index':17, 'state':0 }
|
||||||
|
stations[40260] = { 'name':' State/Lake (Brown Green Orange Pink & Purple lines)', 'eta':[], 'led_index':18, 'state':0 }
|
||||||
|
stations[40130] = { 'name':' 51st (Green Line)', 'eta':[], 'led_index':19, 'state':0 }
|
||||||
|
stations[41700] = { 'name':' Washington/Wabash (Brown Green Orange Purple & Pink lines)', 'eta':[], 'led_index':20, 'state':0 }
|
||||||
|
stations[41000] = { 'name':' Cermak-Chinatown (Red Line)', 'eta':[], 'led_index':21, 'state':0 }
|
||||||
|
stations[40340] = { 'name':' Berwyn (Red Line)', 'eta':[], 'led_index':22, 'state':0 }
|
||||||
|
stations[41690] = { 'name':' Cermak-McCormick Place (Green Line)', 'eta':[], 'led_index':23, 'state':0 }
|
||||||
|
stations[40490] = { 'name':' Grand (Blue Line)', 'eta':[], 'led_index':24, 'state':0 }
|
||||||
|
stations[41060] = { 'name':' Ashland (Orange Line)', 'eta':[], 'led_index':25, 'state':0 }
|
||||||
|
stations[40090] = { 'name':' Damen (Brown Line)', 'eta':[], 'led_index':26, 'state':0 }
|
||||||
|
stations[41280] = { 'name':' Jefferson Park (Blue Line)', 'eta':[], 'led_index':27, 'state':0 }
|
||||||
|
stations[40520] = { 'name':' Foster (Purple Line)', 'eta':[], 'led_index':28, 'state':0 }
|
||||||
|
stations[40330] = { 'name':' Grand (Red Line)', 'eta':[], 'led_index':29, 'state':0 }
|
||||||
|
stations[40280] = { 'name':' Central (Green Line)', 'eta':[], 'led_index':30, 'state':0 }
|
||||||
|
stations[40250] = { 'name':' Kedzie-Homan (Blue Line)', 'eta':[], 'led_index':31, 'state':0 }
|
||||||
|
stations[40870] = { 'name':' Francisco (Brown Line)', 'eta':[], 'led_index':32, 'state':0 }
|
||||||
|
stations[41240] = { 'name':' Addison (Blue Line)', 'eta':[], 'led_index':33, 'state':0 }
|
||||||
|
stations[40740] = { 'name':' Western (Pink Line)', 'eta':[], 'led_index':34, 'state':0 }
|
||||||
|
stations[41360] = { 'name':' California (Green Line)', 'eta':[], 'led_index':35, 'state':0 }
|
||||||
|
stations[41400] = { 'name':' Roosevelt (Red Orange & Green lines)', 'eta':[], 'led_index':36, 'state':0 }
|
||||||
|
stations[41410] = { 'name':' Chicago (Blue Line)', 'eta':[], 'led_index':37, 'state':0 }
|
||||||
|
stations[40680] = { 'name':' Adams/Wabash (Brown Green Orange Pink & Purple lines)', 'eta':[], 'led_index':38, 'state':0 }
|
||||||
|
stations[40920] = { 'name':' Pulaski (Blue Line)', 'eta':[], 'led_index':39, 'state':0 }
|
||||||
|
stations[41210] = { 'name':' Wellington (Brown & Purple lines)', 'eta':[], 'led_index':40, 'state':0 }
|
||||||
|
stations[41340] = { 'name':' LaSalle (Blue Line)', 'eta':[], 'led_index':41, 'state':0 }
|
||||||
|
stations[41490] = { 'name':' Harrison (Red Line)', 'eta':[], 'led_index':42, 'state':0 }
|
||||||
|
stations[41350] = { 'name':' Oak Park (Green Line)', 'eta':[], 'led_index':43, 'state':0 }
|
||||||
|
stations[40040] = { 'name':' Quincy/Wells (Brown Orange Purple & Pink lines)', 'eta':[], 'led_index':44, 'state':0 }
|
||||||
|
stations[40390] = { 'name':' Forest Park (Blue Line)', 'eta':[], 'led_index':45, 'state':0 }
|
||||||
|
stations[41130] = { 'name':' Halsted (Orange Line)', 'eta':[], 'led_index':46, 'state':0 }
|
||||||
|
stations[40960] = { 'name':' Pulaski (Orange Line)', 'eta':[], 'led_index':47, 'state':0 }
|
||||||
|
stations[40830] = { 'name':' 18th (Pink Line)', 'eta':[], 'led_index':48, 'state':0 }
|
||||||
|
stations[40140] = { 'name':' Dempster-Skokie (Yellow Line)', 'eta':[], 'led_index':49, 'state':0 }
|
||||||
|
stations[41320] = { 'name':' Belmont (Red Brown & Purple lines)', 'eta':[], 'led_index':50, 'state':0 }
|
||||||
|
stations[41660] = { 'name':' Lake (Red Line)', 'eta':[], 'led_index':51, 'state':0 }
|
||||||
|
stations[40910] = { 'name':' 63rd (Red Line)', 'eta':[], 'led_index':52, 'state':0 }
|
||||||
|
stations[40690] = { 'name':' Dempster (Purple Line)', 'eta':[], 'led_index':53, 'state':0 }
|
||||||
|
stations[40460] = { 'name':' Merchandise Mart (Brown & Purple lines)', 'eta':[], 'led_index':54, 'state':0 }
|
||||||
|
stations[40710] = { 'name':' Chicago (Brown & Purple lines)', 'eta':[], 'led_index':55, 'state':0 }
|
||||||
|
stations[40530] = { 'name':' Diversey (Brown & Purple lines)', 'eta':[], 'led_index':56, 'state':0 }
|
||||||
|
stations[40850] = { 'name':' Harold Washington Library-State/Van Buren (Brown Orange Purple & Pink lines)', 'eta':[], 'led_index':57, 'state':0 }
|
||||||
|
stations[41020] = { 'name':' Logan Square (Blue Line)', 'eta':[], 'led_index':58, 'state':0 }
|
||||||
|
stations[41030] = { 'name':' Polk (Pink Line)', 'eta':[], 'led_index':59, 'state':0 }
|
||||||
|
stations[41300] = { 'name':' Loyola (Red Line)', 'eta':[], 'led_index':60, 'state':0 }
|
||||||
|
stations[40310] = { 'name':' Western (Orange Line)', 'eta':[], 'led_index':61, 'state':0 }
|
||||||
|
stations[40430] = { 'name':' Clinton (Blue Line)', 'eta':[], 'led_index':62, 'state':0 }
|
||||||
|
stations[40320] = { 'name':' Division (Blue Line)', 'eta':[], 'led_index':63, 'state':0 }
|
||||||
|
stations[41510] = { 'name':' Morgan (Green & Pink lines)', 'eta':[], 'led_index':64, 'state':0 }
|
||||||
|
stations[40270] = { 'name':' Main (Purple Line)', 'eta':[], 'led_index':65, 'state':0 }
|
||||||
|
stations[41330] = { 'name':' Montrose (Blue Line)', 'eta':[], 'led_index':66, 'state':0 }
|
||||||
|
stations[40350] = { 'name':' UIC-Halsted (Blue Line)', 'eta':[], 'led_index':67, 'state':0 }
|
||||||
|
stations[40940] = { 'name':' Halsted (Green Line)', 'eta':[], 'led_index':68, 'state':0 }
|
||||||
|
stations[41480] = { 'name':' Western (Brown Line)', 'eta':[], 'led_index':69, 'state':0 }
|
||||||
|
stations[40030] = { 'name':' Pulaski (Green Line)', 'eta':[], 'led_index':70, 'state':0 }
|
||||||
|
stations[41190] = { 'name':' Jarvis (Red Line)', 'eta':[], 'led_index':71, 'state':0 }
|
||||||
|
stations[41170] = { 'name':' Garfield (Red Line)', 'eta':[], 'led_index':72, 'state':0 }
|
||||||
|
stations[40050] = { 'name':' Davis (Purple Line)', 'eta':[], 'led_index':73, 'state':0 }
|
||||||
|
stations[40750] = { 'name':' Harlem (Blue Line - OHare Branch)', 'eta':[], 'led_index':74, 'state':0 }
|
||||||
|
stations[41200] = { 'name':' Argyle (Red Line)', 'eta':[], 'led_index':75, 'state':0 }
|
||||||
|
stations[40440] = { 'name':' California (Pink Line)', 'eta':[], 'led_index':76, 'state':0 }
|
||||||
|
stations[40360] = { 'name':' Southport (Brown Line)', 'eta':[], 'led_index':77, 'state':0 }
|
||||||
|
stations[40760] = { 'name':' Granville (Red Line)', 'eta':[], 'led_index':78, 'state':0 }
|
||||||
|
stations[40480] = { 'name':' Cicero (Green Line)', 'eta':[], 'led_index':79, 'state':0 }
|
||||||
|
stations[40730] = { 'name':' Washington/Wells (Brown Orange Purple & Pink lines)', 'eta':[], 'led_index':80, 'state':0 }
|
||||||
|
stations[40580] = { 'name':' 54th/Cermak (Pink Line)', 'eta':[], 'led_index':81, 'state':0 }
|
||||||
|
stations[40650] = { 'name':' North/Clybourn (Red Line)', 'eta':[], 'led_index':82, 'state':0 }
|
||||||
|
stations[40220] = { 'name':' Western (Blue Line - Forest Park Branch)', 'eta':[], 'led_index':83, 'state':0 }
|
||||||
|
stations[40070] = { 'name':' Jackson (Blue Line)', 'eta':[], 'led_index':84, 'state':0 }
|
||||||
|
stations[41440] = { 'name':' Addison (Brown Line)', 'eta':[], 'led_index':85, 'state':0 }
|
||||||
|
stations[41670] = { 'name':' Conservatory (Green Line)', 'eta':[], 'led_index':86, 'state':0 }
|
||||||
|
stations[40790] = { 'name':' Monroe (Blue Line)', 'eta':[], 'led_index':87, 'state':0 }
|
||||||
|
stations[40180] = { 'name':' Oak Park (Blue Line)', 'eta':[], 'led_index':88, 'state':0 }
|
||||||
|
stations[40400] = { 'name':' Noyes (Purple Line)', 'eta':[], 'led_index':89, 'state':0 }
|
||||||
|
stations[41260] = { 'name':' Austin (Green Line)', 'eta':[], 'led_index':90, 'state':0 }
|
||||||
|
stations[40600] = { 'name':' Kostner (Pink Line)', 'eta':[], 'led_index':91, 'state':0 }
|
||||||
|
stations[40670] = { 'name':' Western (Blue Line - OHare Branch)', 'eta':[], 'led_index':92, 'state':0 }
|
||||||
|
stations[40100] = { 'name':' Morse (Red Line)', 'eta':[], 'led_index':93, 'state':0 }
|
||||||
|
stations[40770] = { 'name':' Lawrence (Red Line)', 'eta':[], 'led_index':94, 'state':0 }
|
||||||
|
stations[40150] = { 'name':' Pulaski (Pink Line)', 'eta':[], 'led_index':95, 'state':0 }
|
||||||
|
stations[40660] = { 'name':' Armitage (Brown & Purple lines)', 'eta':[], 'led_index':96, 'state':0 }
|
||||||
|
stations[40540] = { 'name':' Wilson (Red & Purple lines)', 'eta':[], 'led_index':97, 'state':0 }
|
||||||
|
stations[40380] = { 'name':' Clark/Lake (Blue Brown Green Orange Purple & Pink lines)', 'eta':[], 'led_index':98, 'state':0 }
|
||||||
|
stations[40160] = { 'name':' LaSalle/Van Buren (Brown Orange Purple & Pink lines)', 'eta':[], 'led_index':99, 'state':0 }
|
||||||
|
stations[40700] = { 'name':' Laramie (Green Line)', 'eta':[], 'led_index':100, 'state':0 }
|
||||||
|
stations[40240] = { 'name':' 79th (Red Line)', 'eta':[], 'led_index':101, 'state':0 }
|
||||||
|
stations[40290] = { 'name':' Ashland/63rd (Green Line)', 'eta':[], 'led_index':102, 'state':0 }
|
||||||
|
stations[40450] = { 'name':' 95th/Dan Ryan (Red Line)', 'eta':[], 'led_index':103, 'state':0 }
|
||||||
|
stations[40210] = { 'name':' Damen (Pink Line)', 'eta':[], 'led_index':104, 'state':0 }
|
||||||
|
stations[41140] = { 'name':' King Drive (Green Line)', 'eta':[], 'led_index':105, 'state':0 }
|
||||||
|
stations[41710] = { 'name':' Damen (Green Line)', 'eta':[], 'led_index':106, 'state':0 }
|
||||||
|
stations[40980] = { 'name':' Harlem (Blue Line - Forest Park Branch)', 'eta':[], 'led_index':107, 'state':0 }
|
||||||
|
stations[41270] = { 'name':' 43rd (Green Line)', 'eta':[], 'led_index':108, 'state':0 }
|
||||||
|
stations[40080] = { 'name':' Sheridan (Red Line)', 'eta':[], 'led_index':109, 'state':0 }
|
||||||
|
stations[40610] = { 'name':' Ridgeland (Green Line)', 'eta':[], 'led_index':110, 'state':0 }
|
||||||
|
stations[41070] = { 'name':' Kedzie (Green Line)', 'eta':[], 'led_index':111, 'state':0 }
|
||||||
|
stations[41430] = { 'name':' 87th (Red Line)', 'eta':[], 'led_index':112, 'state':0 }
|
||||||
|
stations[41250] = { 'name':' Central (Purple Line)', 'eta':[], 'led_index':113, 'state':0 }
|
||||||
|
stations[40880] = { 'name':' Thorndale (Red Line)', 'eta':[], 'led_index':114, 'state':0 }
|
||||||
|
stations[41680] = { 'name':' Oakton-Skokie (Yellow Line)', 'eta':[], 'led_index':115, 'state':0 }
|
||||||
|
stations[41120] = { 'name':' 35th-Bronzeville-IIT (Green Line)', 'eta':[], 'led_index':116, 'state':0 }
|
||||||
|
stations[41460] = { 'name':' Irving Park (Brown Line)', 'eta':[], 'led_index':117, 'state':0 }
|
||||||
|
stations[41220] = { 'name':' Fullerton (Red Brown & Purple lines)', 'eta':[], 'led_index':118, 'state':0 }
|
||||||
|
stations[40990] = { 'name':' 69th (Red Line)', 'eta':[], 'led_index':119, 'state':0 }
|
||||||
|
stations[41040] = { 'name':' Kedzie (Pink Line)', 'eta':[], 'led_index':120, 'state':0 }
|
||||||
|
stations[40800] = { 'name':' Sedgwick (Brown & Purple lines)', 'eta':[], 'led_index':121, 'state':0 }
|
||||||
|
stations[40060] = { 'name':' Belmont (Blue Line)', 'eta':[], 'led_index':122, 'state':0 }
|
||||||
|
stations[40840] = { 'name':' South Boulevard (Purple Line)', 'eta':[], 'led_index':123, 'state':0 }
|
||||||
|
stations[40170] = { 'name':' Ashland (Green & Pink lines)', 'eta':[], 'led_index':124, 'state':0 }
|
||||||
|
stations[40810] = { 'name':' Illinois Medical District (Blue Line)', 'eta':[], 'led_index':125, 'state':0 }
|
||||||
|
stations[41230] = { 'name':' 47th (Red Line)', 'eta':[], 'led_index':126, 'state':0 }
|
||||||
|
stations[41500] = { 'name':' Montrose (Brown Line)', 'eta':[], 'led_index':127, 'state':0 }
|
||||||
|
stations[40930] = { 'name':' Midway (Orange Line)', 'eta':[], 'led_index':128, 'state':0 }
|
||||||
|
stations[40550] = { 'name':' Irving Park (Blue Line)', 'eta':[], 'led_index':129, 'state':0 }
|
||||||
|
stations[40370] = { 'name':' Washington (Blue Line)', 'eta':[], 'led_index':130, 'state':0 }
|
||||||
|
stations[40890] = { 'name':' OHare (Blue Line)', 'eta':[], 'led_index':131, 'state':0 }
|
||||||
|
stations[40630] = { 'name':' Clark/Division (Red Line)', 'eta':[], 'led_index':132, 'state':0 }
|
||||||
|
stations[41420] = { 'name':' Addison (Red Line)', 'eta':[], 'led_index':133, 'state':0 }
|
||||||
|
stations[41290] = { 'name':' Kimball (Brown Line)', 'eta':[], 'led_index':134, 'state':0 }
|
||||||
|
stations[40300] = { 'name':' Indiana (Green Line)', 'eta':[], 'led_index':135, 'state':0 }
|
||||||
|
stations[40420] = { 'name':' Cicero (Pink Line)', 'eta':[], 'led_index':136, 'state':0 }
|
||||||
|
stations[40720] = { 'name':' Cottage Grove (Green Line)', 'eta':[], 'led_index':137, 'state':0 }
|
||||||
|
stations[41380] = { 'name':' Bryn Mawr (Red Line)', 'eta':[], 'led_index':138, 'state':0 }
|
||||||
|
stations[41450] = { 'name':' Chicago (Red Line)', 'eta':[], 'led_index':139, 'state':0 }
|
||||||
|
stations[40590] = { 'name':' Damen (Blue Line)', 'eta':[], 'led_index':140, 'state':0 }
|
||||||
|
stations[41180] = { 'name':' Kedzie (Brown Line)', 'eta':[], 'led_index':141, 'state':0 }
|
||||||
|
stations[40010] = { 'name':' Austin (Blue Line)', 'eta':[], 'led_index':142, 'state':0 }
|
||||||
|
stations[41310] = { 'name':' Paulina (Brown Line)', 'eta':[], 'led_index':143, 'state':0 }
|
||||||
|
stations[40970] = { 'name':' Cicero (Blue Line)', 'eta':[], 'led_index':144, 'state':0 }
|
||||||
|
|
||||||
|
# Function sets up all LEDs.
|
||||||
|
init_LEDs()
|
||||||
|
|
||||||
|
|
||||||
|
while(True):
|
||||||
|
# Synchronise NTP time if hasn't been done in 1 hour
|
||||||
|
if (time() - last_ntp_sync) > 3600:
|
||||||
|
reconnect_wifi()
|
||||||
|
try:
|
||||||
|
ntptime.settime()
|
||||||
|
print("Time synchronized successfully")
|
||||||
|
last_ntp_sync = time()
|
||||||
|
except Exception as e:
|
||||||
|
print("Error synchronizing time:", e)
|
||||||
|
|
||||||
|
# Have we queried API in the query_period seconds?
|
||||||
|
if (time() - last_api_query) > query_period:
|
||||||
|
# Query updated API
|
||||||
|
trains = (requests.get("https://lapi.transitchicago.com/api/1.0/ttpositions.aspx?key="+APIKEY+"&rt=Blue&outputType=JSON")).json()['ctatt']
|
||||||
|
|
||||||
|
# Timestamps are served in local Chicago time, convert to GMT for simplicity on this side.
|
||||||
|
print(f"Time of poll is: "+str(gmtime(time_from_iso(trains['tmst'])+(5*60*60))))
|
||||||
|
|
||||||
|
# Loop through all trains and update matching stations
|
||||||
|
for train in trains['route'][0]['train']:
|
||||||
|
nextStation = int(train['nextStaId'])
|
||||||
|
eta_time = time_from_iso(train['arrT'])+(5*60*60)
|
||||||
|
|
||||||
|
# Append the ETA, we rely on the station loop to remove old trains
|
||||||
|
stations[nextStation]['eta'].append(eta_time)
|
||||||
|
|
||||||
|
|
||||||
|
last_api_query = time() # uptime polling window
|
||||||
|
|
||||||
|
|
||||||
|
# Process the ETA for each station
|
||||||
|
for station, dict in stations.items(): # loop through all stations
|
||||||
|
if station == 40820: # Our test station for onboard LED
|
||||||
|
|
||||||
|
# Set LED state tracker to 0, if no trains, it'll stay 0.
|
||||||
|
stations[station]['state'] = 0
|
||||||
|
for index, eta in enumerate(dict['eta']): # multiple trains. Enumerate is used so we have the index to update the dict itself.
|
||||||
|
time_from_now = eta - time()
|
||||||
|
|
||||||
|
print('Train will arrive at'+dict['name']+' in '+ str(time_from_now) + ' seconds')
|
||||||
|
if time_from_now < distance_on:
|
||||||
|
stations[station]['state'] = 1
|
||||||
|
|
||||||
|
if time_from_now < -distance_on: # Remove old trains
|
||||||
|
stations[station]['eta'].pop(index)
|
||||||
|
|
||||||
|
# Set Station LED state
|
||||||
|
stations[station]['led_index'].value(stations[station]['state'])
|
||||||
|
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
Reference in new issue
Block a user