SL Real Time Information 4
Arduino sketch written for NodeMCU to fetch information from Stockholm Lokaltrafiks API about departures from any given stop.
Components and supplies
1
NodeMCU ESP8266 Breakout Board
Apps and platforms
1
SL Realtidsinformation 4
1
SL Platsuppslag
Project description
Code
SL_Real_Time_Information_4.ino
arduino
Just add API keys and your wifi credentials
1/* 2 This sketch makes use of the SL Realtidsinformation 4 API 3 to fetch and present the json data in the serial monitor. 4 It's written to be easily remixable to fit your project. 5 6 Read about the APIs here: 7 https://www.trafiklab.se/api/sl-realtidsinformation-4 8 https://www.trafiklab.se/api/sl-platsuppslag 9*/ 10 11 12#include <WiFiClient.h> 13#include <ESP8266WiFi.h> 14#include <ArduinoJson.h> 15 16// Enter your WiFi credentials here: 17const char* wifiName = "your-wifi"; 18const char* wifiPass = "your-pass"; 19 20// Enter your API key for SL Platsuppslag here (if you don't need SL Platsuppslag just set fetchStopInfo to false): 21const char* PUAPIKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; 22 23// Enter your API key for SL Realtidsinformation 4 here: 24const char* RTD4APIKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; 25// Enter site ID (e.g. 9001 for T-centralen, 9192 for Slussen): 26const char* RTD4siteID = "9001"; 27// Enter time window (60 minutes is max): 28const char* RTD4timeWindow = "60"; 29 30const bool fetchStopInfo = true;// Set to false if not using the SL Platsuppslag API. 31 32const bool lookForMetros = true; 33const bool lookForBuses = true; 34const bool lookForTrains = true; 35const bool lookForTrams = true; 36const bool lookForShips = true; 37 38const bool lookForStopPointDeviations = true; 39 40WiFiClient client; 41 42DynamicJsonDocument doc(16 * 1024); 43 44void setup() { 45 46 Serial.begin(115200); 47 delay(10); 48 Serial.println(); 49 50 Serial.print("Connecting to "); 51 Serial.println(wifiName); 52 53 WiFi.begin(wifiName, wifiPass); 54 55 while (WiFi.status() != WL_CONNECTED) { 56 delay(500); 57 Serial.print("."); 58 } 59 60 61 Serial.println(); 62 Serial.println("WiFi connected."); 63 Serial.print("IP address: "); 64 Serial.println(WiFi.localIP()); //You can get IP address assigned to ESP 65 66 67 if (fetchStopInfo) { 68 stopInfoFetcher(PUAPIKey, RTD4siteID); 69 } 70 71 72} 73void loop() { 74 75 client.connect("api.sl.se", 80); 76 77 client.print("GET /api2/realtimedeparturesV4.json?key="); 78 client.print(RTD4APIKey); 79 client.print("&siteid="); 80 client.print(RTD4siteID); 81 client.print("&timewindow="); 82 client.print(RTD4timeWindow); 83 client.println(" HTTP/1.0"); 84 client.println("Host: api.sl.se"); 85 client.println("Connection: close"); 86 client.println(); 87 88 if (lookForMetros) { 89 findTransport("Metros"); 90 } 91 92 if (lookForBuses) { 93 findTransport("Buses"); 94 } 95 96 if (lookForTrains) { 97 findTransport("Trains"); 98 } 99 100 if (lookForTrams) { 101 findTransport("Trams"); 102 } 103 104 if (lookForShips) { 105 findTransport("Ships"); 106 } 107 108 if (lookForStopPointDeviations) { 109 findStopPointDeviations(); 110 } 111 112 113 client.stop(); 114 115 delay(300000); //GET Data at every 5 minutes 116} 117 118void stopInfoFetcher(const char* APIkey, const char* siteID) { 119 client.connect("api.sl.se", 80); 120 121 client.print("GET /api2/typeahead.json?key="); 122 client.print(APIkey); 123 client.print("&searchstring="); 124 client.print(siteID); 125 client.print("&stationsonly=True&maxresults=1"); 126 client.println(" HTTP/1.0"); 127 client.println("Host: api.sl.se"); 128 client.println("Connection: close"); 129 client.println(); 130 131 client.find("\\"ResponseData\\":["); 132 Serial.println(); 133 Serial.println(F("Stop Point Info: ")); 134 do { 135 // Parse the JSON object 136 deserializeJson(doc, client); 137 if (doc.isNull()) { 138 Serial.println("No stop info found."); 139 break; 140 } 141 Serial.print(F("Name: ")); 142 Serial.println(doc["Name"].as<char*>()); 143 Serial.print(F("SiteId: ")); 144 Serial.println(doc["SiteId"].as<char*>()); 145 Serial.print(F("Type: ")); 146 Serial.println(doc["Type"].as<char*>()); 147 Serial.print(F("X: ")); 148 Serial.println(doc["X"].as<char*>()); 149 Serial.print(F("Y: ")); 150 Serial.println(doc["Y"].as<char*>()); 151 Serial.print(F("Products: ")); 152 Serial.println(doc["Products"].as<char*>()); 153 } 154 while (client.findUntil(",", "]")); 155 156 client.stop(); 157 158} 159 160 161 162 163void findTransport(char* type) { 164 Serial.println(); 165 Serial.print(F("#### ")); 166 Serial.print(type); 167 Serial.println(F(" ####")); 168 char* beginning = "\\""; 169 char* ending = "\\":["; 170 char searchTerm[20]; 171 sprintf(searchTerm, "%s%s%s", beginning, type, ending); 172 173 client.find(searchTerm); 174 175 do { 176 // Parse the JSON object 177 deserializeJson(doc, client); 178 if (doc.isNull()) { 179 Serial.print("No "); 180 Serial.print(type); 181 Serial.println(" found."); 182 break; 183 } 184 Serial.println(); 185 Serial.print(F("GroupOfLine: ")); 186 Serial.println(doc["GroupOfLine"].as<char*>()); 187 Serial.print(F("DisplayTime: ")); 188 Serial.println(doc["DisplayTime"].as<char*>()); 189 Serial.print(F("TransportMode: ")); 190 Serial.println(doc["TransportMode"].as<char*>()); 191 Serial.print(F("LineNumber: ")); 192 Serial.println(doc["LineNumber"].as<char*>()); 193 Serial.print(F("Destination: ")); 194 Serial.println(doc["Destination"].as<char*>()); 195 Serial.print(F("JourneyDirection: ")); 196 Serial.println(doc["JourneyDirection"].as<int>()); 197 Serial.print(F("StopAreaName: ")); 198 Serial.println(doc["StopAreaName"].as<char*>()); 199 Serial.print(F("StopAreaNumber: ")); 200 Serial.println(doc["StopAreaNumber"].as<int>()); 201 Serial.print(F("StopPointNumber: ")); 202 Serial.println(doc["StopPointNumber"].as<int>()); 203 Serial.print(F("StopPointDesignation: ")); 204 Serial.println(doc["StopPointDesignation"].as<char*>()); 205 Serial.print(F("TimeTabledDateTime: ")); 206 Serial.println(doc["TimeTabledDateTime"].as<char*>()); 207 Serial.print(F("ExpectedDateTime: ")); 208 Serial.println(doc["ExpectedDateTime"].as<char*>()); 209 Serial.print(F("JourneyNumber: ")); 210 Serial.println(doc["JourneyNumber"].as<int>()); 211 if (doc["Deviations"].isNull() == false) { 212 Serial.println(F("# Deviations #")); 213 } 214 for (int i = 0; i < doc["Deviations"].size(); i++) { 215 Serial.print(F("Text: ")); 216 Serial.println(doc["Deviations"][i]["Text"].as<char*>()); 217 Serial.print(F("Consequence: ")); 218 Serial.println(doc["Deviations"][i]["Consequence"].as<char*>()); 219 Serial.print(F("ImportanceLevel: ")); 220 Serial.println(doc["Deviations"][i]["ImportanceLevel"].as<int>()); 221 } 222 223 224 225 } while (client.findUntil(",", "]")); 226} 227 228void findStopPointDeviations() { 229 client.find("\\"StopPointDeviations\\":["); 230 Serial.println(); 231 Serial.println(F("#### Stop Point Deviations ####")); 232 do { 233 // Parse the JSON object 234 deserializeJson(doc, client); 235 if (doc.isNull()) { 236 Serial.println("No stop point deviations found."); 237 break; 238 } 239 Serial.println(F("# StopInfo #")); 240 Serial.print(F("StopAreaNumber: ")); 241 Serial.println(doc["StopInfo"]["StopAreaNumber"].as<int>()); 242 Serial.print(F("StopAreaName: ")); 243 Serial.println(doc["StopInfo"]["StopAreaName"].as<char*>()); 244 Serial.print(F("TransportMode: ")); 245 Serial.println(doc["StopInfo"]["TransportMode"].as<char*>()); 246 Serial.print(F("GroupOfLine: ")); 247 Serial.println(doc["StopInfo"]["GroupOfLine"].as<char*>()); 248 Serial.println(F("# Deviation #")); 249 Serial.print(F("Text: ")); 250 Serial.println(doc["Deviation"]["Text"].as<char*>()); 251 Serial.print(F("Consequence: ")); 252 Serial.println(doc["Deviation"]["Consequence"].as<char*>()); 253 Serial.print(F("ImportanceLevel: ")); 254 Serial.println(doc["Deviation"]["ImportanceLevel"].as<int>()); 255 256 } while (client.findUntil(",", "]")); 257}
SL_Real_Time_Information_4.ino
arduino
Just add API keys and your wifi credentials
1/* 2 This sketch makes use of the SL Realtidsinformation 4 API 3 4 to fetch and present the json data in the serial monitor. 5 It's written to 6 be easily remixable to fit your project. 7 8 Read about the APIs here: 9 10 https://www.trafiklab.se/api/sl-realtidsinformation-4 11 https://www.trafiklab.se/api/sl-platsuppslag 12*/ 13 14 15#include 16 <WiFiClient.h> 17#include <ESP8266WiFi.h> 18#include <ArduinoJson.h> 19 20// 21 Enter your WiFi credentials here: 22const char* wifiName = "your-wifi"; 23const 24 char* wifiPass = "your-pass"; 25 26// Enter your API key for SL Platsuppslag 27 here (if you don't need SL Platsuppslag just set fetchStopInfo to false): 28const 29 char* PUAPIKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; 30 31// Enter your 32 API key for SL Realtidsinformation 4 here: 33const char* RTD4APIKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; 34// 35 Enter site ID (e.g. 9001 for T-centralen, 9192 for Slussen): 36const char* RTD4siteID 37 = "9001"; 38// Enter time window (60 minutes is max): 39const char* RTD4timeWindow 40 = "60"; 41 42const bool fetchStopInfo = true;// Set to false if not using the 43 SL Platsuppslag API. 44 45const bool lookForMetros = true; 46const bool lookForBuses 47 = true; 48const bool lookForTrains = true; 49const bool lookForTrams = true; 50const 51 bool lookForShips = true; 52 53const bool lookForStopPointDeviations = true; 54 55WiFiClient 56 client; 57 58DynamicJsonDocument doc(16 * 1024); 59 60void setup() { 61 62 63 Serial.begin(115200); 64 delay(10); 65 Serial.println(); 66 67 Serial.print("Connecting 68 to "); 69 Serial.println(wifiName); 70 71 WiFi.begin(wifiName, wifiPass); 72 73 74 while (WiFi.status() != WL_CONNECTED) { 75 delay(500); 76 Serial.print("."); 77 78 } 79 80 81 Serial.println(); 82 Serial.println("WiFi connected."); 83 84 Serial.print("IP address: "); 85 Serial.println(WiFi.localIP()); //You can 86 get IP address assigned to ESP 87 88 89 if (fetchStopInfo) { 90 stopInfoFetcher(PUAPIKey, 91 RTD4siteID); 92 } 93 94 95} 96void loop() { 97 98 client.connect("api.sl.se", 99 80); 100 101 client.print("GET /api2/realtimedeparturesV4.json?key="); 102 client.print(RTD4APIKey); 103 104 client.print("&siteid="); 105 client.print(RTD4siteID); 106 client.print("&timewindow="); 107 108 client.print(RTD4timeWindow); 109 client.println(" HTTP/1.0"); 110 client.println("Host: 111 api.sl.se"); 112 client.println("Connection: close"); 113 client.println(); 114 115 116 if (lookForMetros) { 117 findTransport("Metros"); 118 } 119 120 if (lookForBuses) 121 { 122 findTransport("Buses"); 123 } 124 125 if (lookForTrains) { 126 findTransport("Trains"); 127 128 } 129 130 if (lookForTrams) { 131 findTransport("Trams"); 132 } 133 134 135 if (lookForShips) { 136 findTransport("Ships"); 137 } 138 139 if (lookForStopPointDeviations) 140 { 141 findStopPointDeviations(); 142 } 143 144 145 client.stop(); 146 147 delay(300000); 148 //GET Data at every 5 minutes 149} 150 151void stopInfoFetcher(const char* APIkey, 152 const char* siteID) { 153 client.connect("api.sl.se", 80); 154 155 client.print("GET 156 /api2/typeahead.json?key="); 157 client.print(APIkey); 158 client.print("&searchstring="); 159 160 client.print(siteID); 161 client.print("&stationsonly=True&maxresults=1"); 162 163 client.println(" HTTP/1.0"); 164 client.println("Host: api.sl.se"); 165 client.println("Connection: 166 close"); 167 client.println(); 168 169 client.find("\\"ResponseData\\":["); 170 171 Serial.println(); 172 Serial.println(F("Stop Point Info: ")); 173 do { 174 175 // Parse the JSON object 176 deserializeJson(doc, client); 177 if (doc.isNull()) 178 { 179 Serial.println("No stop info found."); 180 break; 181 } 182 183 Serial.print(F("Name: ")); 184 Serial.println(doc["Name"].as<char*>()); 185 186 Serial.print(F("SiteId: ")); 187 Serial.println(doc["SiteId"].as<char*>()); 188 189 Serial.print(F("Type: ")); 190 Serial.println(doc["Type"].as<char*>()); 191 192 Serial.print(F("X: ")); 193 Serial.println(doc["X"].as<char*>()); 194 195 Serial.print(F("Y: ")); 196 Serial.println(doc["Y"].as<char*>()); 197 198 Serial.print(F("Products: ")); 199 Serial.println(doc["Products"].as<char*>()); 200 201 } 202 while (client.findUntil(",", "]")); 203 204 client.stop(); 205 206} 207 208 209 210 211void 212 findTransport(char* type) { 213 Serial.println(); 214 Serial.print(F("#### ")); 215 216 Serial.print(type); 217 Serial.println(F(" ####")); 218 char* beginning = 219 "\\""; 220 char* ending = "\\":["; 221 char searchTerm[20]; 222 sprintf(searchTerm, 223 "%s%s%s", beginning, type, ending); 224 225 client.find(searchTerm); 226 227 228 do { 229 // Parse the JSON object 230 deserializeJson(doc, client); 231 232 if (doc.isNull()) { 233 Serial.print("No "); 234 Serial.print(type); 235 236 Serial.println(" found."); 237 break; 238 } 239 Serial.println(); 240 241 Serial.print(F("GroupOfLine: ")); 242 Serial.println(doc["GroupOfLine"].as<char*>()); 243 244 Serial.print(F("DisplayTime: ")); 245 Serial.println(doc["DisplayTime"].as<char*>()); 246 247 Serial.print(F("TransportMode: ")); 248 Serial.println(doc["TransportMode"].as<char*>()); 249 250 Serial.print(F("LineNumber: ")); 251 Serial.println(doc["LineNumber"].as<char*>()); 252 253 Serial.print(F("Destination: ")); 254 Serial.println(doc["Destination"].as<char*>()); 255 256 Serial.print(F("JourneyDirection: ")); 257 Serial.println(doc["JourneyDirection"].as<int>()); 258 259 Serial.print(F("StopAreaName: ")); 260 Serial.println(doc["StopAreaName"].as<char*>()); 261 262 Serial.print(F("StopAreaNumber: ")); 263 Serial.println(doc["StopAreaNumber"].as<int>()); 264 265 Serial.print(F("StopPointNumber: ")); 266 Serial.println(doc["StopPointNumber"].as<int>()); 267 268 Serial.print(F("StopPointDesignation: ")); 269 Serial.println(doc["StopPointDesignation"].as<char*>()); 270 271 Serial.print(F("TimeTabledDateTime: ")); 272 Serial.println(doc["TimeTabledDateTime"].as<char*>()); 273 274 Serial.print(F("ExpectedDateTime: ")); 275 Serial.println(doc["ExpectedDateTime"].as<char*>()); 276 277 Serial.print(F("JourneyNumber: ")); 278 Serial.println(doc["JourneyNumber"].as<int>()); 279 280 if (doc["Deviations"].isNull() == false) { 281 Serial.println(F("# Deviations 282 #")); 283 } 284 for (int i = 0; i < doc["Deviations"].size(); i++) { 285 286 Serial.print(F("Text: ")); 287 Serial.println(doc["Deviations"][i]["Text"].as<char*>()); 288 289 Serial.print(F("Consequence: ")); 290 Serial.println(doc["Deviations"][i]["Consequence"].as<char*>()); 291 292 Serial.print(F("ImportanceLevel: ")); 293 Serial.println(doc["Deviations"][i]["ImportanceLevel"].as<int>()); 294 295 } 296 297 298 299 } while (client.findUntil(",", "]")); 300} 301 302void 303 findStopPointDeviations() { 304 client.find("\\"StopPointDeviations\\":["); 305 306 Serial.println(); 307 Serial.println(F("#### Stop Point Deviations ####")); 308 309 do { 310 // Parse the JSON object 311 deserializeJson(doc, client); 312 313 if (doc.isNull()) { 314 Serial.println("No stop point deviations found."); 315 316 break; 317 } 318 Serial.println(F("# StopInfo #")); 319 Serial.print(F("StopAreaNumber: 320 ")); 321 Serial.println(doc["StopInfo"]["StopAreaNumber"].as<int>()); 322 323 Serial.print(F("StopAreaName: ")); 324 Serial.println(doc["StopInfo"]["StopAreaName"].as<char*>()); 325 326 Serial.print(F("TransportMode: ")); 327 Serial.println(doc["StopInfo"]["TransportMode"].as<char*>()); 328 329 Serial.print(F("GroupOfLine: ")); 330 Serial.println(doc["StopInfo"]["GroupOfLine"].as<char*>()); 331 332 Serial.println(F("# Deviation #")); 333 Serial.print(F("Text: ")); 334 335 Serial.println(doc["Deviation"]["Text"].as<char*>()); 336 Serial.print(F("Consequence: 337 ")); 338 Serial.println(doc["Deviation"]["Consequence"].as<char*>()); 339 340 Serial.print(F("ImportanceLevel: ")); 341 Serial.println(doc["Deviation"]["ImportanceLevel"].as<int>()); 342 343 344 } while (client.findUntil(",", "]")); 345}
Downloadable files
Breadboard
Schematic of hookup onto the breadboard. The NodeMCU will accept any voltage up to 20 Volts.
Breadboard

Comments
Only logged in users can leave comments