Kom igång
Exempel på applikationer med kod.
Enkla exempel på nyttjande av Trafikverkets öppna API för trafikinformation (Test).
Javascript
Sök avgångar från en station
Exemplet består av HTML och javascript, ingen egen serverkod behövs. Webbsidan innehåller ett sökfält med autocomplete-funktion för sökning på stationer. Vid vald station listas kommande avgångar.
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css"> <style> table { border: 1px solid #000000; border-collapse: collapse; border-spacing: 0px; } table td { padding: 8px 8px; } </style> <script src="http://code.jquery.com/jquery-1.9.1.js"></script> <script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script> <script type="text/javascript"> var Stations = new Array(); $(document).ready(function () { $.support.cors = true; // Enable Cross domain requests try { $.ajaxSetup({ url: "https://api.trafikinfo.trafikverket.se/v2/data.json", error: function (msg) { if (msg.statusText == "abort") return; alert("Request failed: " + msg.statusText + "\n" + msg.responseText); } }); } catch (e) { alert("Ett fel uppstod vid initialisering."); } // Create an ajax loading indicator var loadingTimer; $("#loader").hide(); $(document).ajaxStart(function () { loadingTimer = setTimeout(function () { $("#loader").show(); }, 200); }).ajaxStop(function () { clearTimeout(loadingTimer); $("#loader").hide(); }); // Load stations PreloadTrainStations(); }); function PreloadTrainStations() { // Request to load all stations var xmlRequest = "<REQUEST>" + // Use your valid authenticationkey "<LOGIN authenticationkey='yourAuthenticationKey'/>" + "<QUERY objecttype='TrainStation' schemaversion='1'>" + "<FILTER/>" + "<INCLUDE>Prognosticated</INCLUDE>" + "<INCLUDE>AdvertisedLocationName</INCLUDE>" + "<INCLUDE>LocationSignature</INCLUDE>" + "</QUERY>" + "</REQUEST>"; $.ajax({ type: "POST", contentType: "text/xml", dataType: "json", data: xmlRequest, success: function (response) { if (response == null) return; try { var stationlist = []; $(response.RESPONSE.RESULT[0].TrainStation).each(function (iterator, item) { // Save a key/value list of stations Stations[item.LocationSignature] = item.AdvertisedLocationName; // Create an array to fill the search field autocomplete. if (item.Prognosticated == true) stationlist.push({ label: item.AdvertisedLocationName, value: item.LocationSignature }); }); fillSearchWidget(stationlist); } catch (ex) { } } }); } function fillSearchWidget(data) { $("#station").val(""); $("#station").autocomplete({ // Make the autocomplete fill with matches that "starts with" only source: function (request, response) { var matches = $.map(data, function (tag) { if (tag.label.toUpperCase().indexOf(request.term.toUpperCase()) === 0) { return { label: tag.label, value: tag.value } } }); response(matches); }, select: function (event, ui) { var selectedObj = ui.item; $("#station").val(selectedObj.label); // Save selected stations signature $("#station").data("sign", selectedObj.value); return false; }, focus: function (event, ui) { var selectedObj = ui.item; // Show station name in search field $("#station").val(selectedObj.label); return false; } }); } function Search() { var sign = $("#station").data("sign"); // Clear html table $('#timeTableDeparture tr:not(:first)').remove(); // Request to load announcements for a station by its signature var xmlRequest = "<REQUEST>" + "<LOGIN authenticationkey='yourAuthenticationKey' />" + "<QUERY objecttype='TrainAnnouncement' " + "orderby='AdvertisedTimeAtLocation' schemaversion='1'>" + "<FILTER>" + "<AND>" + "<OR>" + "<AND>" + "<GT name='AdvertisedTimeAtLocation' " + "value='$dateadd(-00:15:00)' />" + "<LT name='AdvertisedTimeAtLocation' " + "value='$dateadd(14:00:00)' />" + "</AND>" + "<GT name='EstimatedTimeAtLocation' value='$now' />" + "</OR>" + "<EQ name='LocationSignature' value='" + sign + "' />" + "<EQ name='ActivityType' value='Avgang' />" + "</AND>" + "</FILTER>" + // Just include wanted fields to reduce response size. "<INCLUDE>InformationOwner</INCLUDE>" + "<INCLUDE>AdvertisedTimeAtLocation</INCLUDE>" + "<INCLUDE>TrackAtLocation</INCLUDE>" + "<INCLUDE>FromLocation</INCLUDE>" + "<INCLUDE>ToLocation</INCLUDE>" + "</QUERY>" + "</REQUEST>"; $.ajax({ type: "POST", contentType: "text/xml", dataType: "json", data: xmlRequest, success: function (response) { if (response == null) return; if (response.RESPONSE.RESULT[0].TrainAnnouncement == null) jQuery("#timeTableDeparture tr:last"). after("<tr><td colspan='4'>Inga avgångar hittades</td></tr>"); try { renderTrainAnnouncement(response.RESPONSE.RESULT[0].TrainAnnouncement); } catch (ex) { } } }); } function renderTrainAnnouncement(announcement) { $(announcement).each(function (iterator, item) { var advertisedtime = new Date(item.AdvertisedTimeAtLocation); var hours = advertisedtime.getHours() var minutes = advertisedtime.getMinutes() if (minutes < 10) minutes = "0" + minutes var toList = new Array(); $(item.ToLocation).each(function (iterator, toItem) { toList.push(Stations[toItem]); }); var owner = ""; if (item.InformationOwner != null) owner = item.InformationOwner; jQuery("#timeTableDeparture tr:last"). after("<tr><td>" + hours + ":" + minutes + "</td><td>" + toList.join(', ') + "</td><td>" + owner + "</td><td style='text-align: center'>" + item.TrackAtLocation + "</td></tr>"); }); } </script> </head> <body> <div> <input id="station" type="text" /> <input type="button" value="Visa" onclick="javascript: Search()" /> <span id="loader" style="margin-left: 10px">Laddar data ...</span> </div> <div id="result"> <h3>Avgående tåg</h3> <table border="1" id="timeTableDeparture"> <tr> <th scope="col" style="width:40px;">Tid</th> <th scope="col" style="width:200px;">Till</th> <th scope="col" style="width:80px;"></th> <th scope="col" style="width:80px;">Spår</th> </tr> </table> </div> </body> </html>
.NET C#
Hämta meddelanden som XML
En konsolapplikation skriven i .NET C# som gör ett asynkront anrop och hämtar alla meddelanden som påverkar Borlänge station som XML.
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; namespace OpenAPISampleNET { class Program { static void Main(string[] args) { Console.WriteLine("--- Download data sample ---"); WebClient webclient = new WebClient(); webclient.Headers.Add("Referer", "http://www.example.com"); // Replace with your domain here // Registrer a handler that will execute when download is completed. webclient.UploadStringCompleted += (obj, arguments) => { if (arguments.Cancelled == true) { Console.Write("Request cancelled by user"); } else if (arguments.Error != null) { Console.WriteLine(arguments.Error.Message); Console.Write("Request Failed"); } else { Console.WriteLine(formatXML(arguments.Result)); Console.Write("Data downloaded"); } Console.WriteLine(", press 'X' to exit."); }; try { // API server url Uri address = new Uri("https://api.trafikinfo.trafikverket.se/v2/data.xml"); string requestBody = "<REQUEST>" + // Use your valid authenticationkey "<LOGIN authenticationkey='yourAuthenticationKey'/>" + "<QUERY objecttype='TrainMessage' schemaversion='1.3'>" + "<FILTER>" + "<IN name='AffectedLocation' value='Blg'/>" + "</FILTER>" + "<EXCLUDE>Deleted</EXCLUDE>" + "</QUERY>" + "</REQUEST>"; webclient.Headers["Content-Type"] = "text/xml"; Console.WriteLine("Fetching data ... (press 'C' to cancel)"); webclient.UploadStringAsync(address, "POST", requestBody); } catch (UriFormatException) { Console.WriteLine("Malformed url, press 'X' to exit."); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine("An error occured, press 'X' to exit."); } char keychar = ' '; while (keychar != 'X') { keychar = Char.ToUpper(Console.ReadKey().KeyChar); if (keychar == 'C') { webclient.CancelAsync(); } } } // Format xml so it is readable by humans. private static string formatXML(string xml) { // Format xml. XDocument rxml = XDocument.Parse(xml); XmlWriterSettings xmlsettings = new XmlWriterSettings(); xmlsettings.OmitXmlDeclaration = true; xmlsettings.Indent = true; xmlsettings.IndentChars = " "; var sb = new StringBuilder(); using (XmlWriter xmlWriter = XmlWriter.Create(sb, xmlsettings)) { rxml.WriteTo(xmlWriter); } return sb.ToString(); } } }
Karta
Visa vägrelaterade händelser i en karta.
Exemplet består av HTML och javascript, ingen egen serverkod behövs. Webbsidan visar olika vägrelaterade händelser i en interaktiv karta.
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <link rel="stylesheet" href="OpenLayers/ol.css" /> <link href="https://stackpath.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> <script type="text/javascript" src="OpenLayers/ol.js"></script> <style> #map { height: 800px; width: 100%; } .woopwoop { max-width: 100% !important; } .woopwoop h4 { padding-left:20px; background-repeat: no-repeat; background-image: url(https://api.trafikinfo.trafikverket.se/v2/icons/trafficMessage?type=png16x16); } #popup { padding-bottom: 8px; width: 800px; } </style> </head> <body> <div id="map"> <div id="popup"></div> </div> <script type="text/javascript" > var apiUrl = "https://api.trafikinfo.trafikverket.se/v2/"; $.support.cors = true; // Enable Cross domain requests //Initialize the map $(document).ready(function () { try { $.ajaxSetup({ url: apiUrl + "data.json", error: function (msg) { if (msg.statusText == "abort") return; alert("Request failed: " + msg.statusText + "\n" + msg.responseText); } }); } catch (e) { alert("Ett fel uppstod vid initialisering."); } //Creates the OpenLayers map object (http://openlayers.org/en/master/apidoc/ol.Map.html) var map = new ol.Map({ controls: ol.control.defaults().extend([new ol.control.FullScreen()]), target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() //Background layer }) ], view: new ol.View({ center: ol.proj.transform([15, 60], 'EPSG:4326', 'EPSG:3857'), //Transforms coordinates to the coordinate system used by the background layer zoom: 4 }) }); addVectorLayer(map, "Situations"); var element = document.getElementById('popup'); var popup = new ol.Overlay({ element: element, positioning: 'bottom-center', stopEvent: false }); map.addOverlay(popup); $(window).resize(function () { $("#map").height($(window).height()); map.updateSize(); }) $(element).popover({ 'placement': 'top', 'html': true, template: '<div class="popover woopwoop"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>', }); map.on('click', function (evt) { var node = evt.originalEvent.target.parentNode; while (node != null) { //Check if click is inside of popup, then ignore click on map if ($(node).hasClass("woopwoop") == true) return false; node = node.parentNode; } var features = []; map.forEachFeatureAtPixel(evt.pixel, function (feature, layer) { features.push(feature); }); if (features.length == 0) { $(element).popover('hide'); } else { var geometry = features[0].getGeometry(); var coord = geometry.getCoordinates(); popup.setPosition(coord); var header = ""; var text = ""; if (features.length > 1) { //Multiple situations in search result, displaying first two header = "Sökresultat"; $.each(features, function (index, feature) { if (index > 1) { text += "<br/><br/><i>Sökningen gav <b>" + features.length + "</b> resultat. För att se mer information, zooma in i kartan och klicka på önskad företeelse.</i>"; return false; } var managedCause = feature.get('managedCause'); text += "<div class='panel panel-info'><div class='panel-heading'><h3 class='panel-title'> <a data-toggle='collapse' data-target='#collapse" + index + "' href='#collapse" + index + "'>" + managedCause.MessageType + "</a></h3></div><div id='collapse" + index + "' class='panel-collapse collapse " + (index == 0 ? "in" : "") + "'><div class='panel-body'>"; text += "<i>" + (managedCause.LocationDescriptor || "") + "</i>"; $.each(feature.get('data').Deviation, function (index2, deviation) { var active = isActive(deviation); text += "<h4 style='background-image: url(" + apiUrl + "icons/" + deviation.IconId + (!active ? "Planned" : "") + "?type=png16x16)'>" + (deviation.MessageCode || deviation.RoadNumber || "") + ((deviation.Header || null) != null ? (" - " + deviation.Header) : "") + "</h4>"; text += formatDeviationText(deviation); }); text += "</div></div></div>" }); } else { //Single situation in search result header = "Sökresultat"; var managedCause = features[0].get('managedCause'); text += "<div class='panel panel-info'><div class='panel-heading'><h3 class='panel-title'>" + managedCause.MessageType + "</h3></div><div class='panel-body'>" text += "<i>" + (managedCause.LocationDescriptor || "") + "</i>"; $.each(features[0].get('data').Deviation, function (index2, deviation) { var active = isActive(deviation); text += "<h4 style='background-image: url(" + apiUrl + "icons/" + deviation.IconId + (!active ? "Planned" : "") + "?type=png16x16)'>" + (deviation.MessageCode || deviation.RoadNumber || "") + ((deviation.Header || null) != null ? (" - " + deviation.Header) : "") + "</h4>"; text += formatDeviationText(deviation); }); text += "</div></div>" } var offset = $(element).offset(); var top = offset.top; var height = $(document).outerHeight(); var vert = 0.5 * height - top; var vertPlacement = vert > 0 ? 'bottom' : 'top'; $(element).data('bs.popover').options.placement = vertPlacement; $(element).data('bs.popover').options.content = '<h3>' + header + '</h3>' + text $(element).popover('show'); } }); $(window).trigger("resize"); }); //Function for adding vector layers to map function addVectorLayer(mapObject, type) { var features = []; var format = new ol.format.WKT(); switch (type) { case "Situation": default: var xmlRequest = "<REQUEST>" + // Use your valid authenticationkey "<LOGIN authenticationkey='yourAuthenticationKey' />" + "<QUERY objecttype='Situation' schemaversion='1.2'>" + "<FILTER>" + "<GTE name='Deviation.EndTime' value='$now'/>" + "</FILTER>" + "</QUERY>" + "</REQUEST>"; $.ajax({ type: "POST", contentType: "text/xml", dataType: "json", data: xmlRequest, success: function (response) { if (response == null) return; try { $.each(response.RESPONSE.RESULT[0].Situation, function (index, item) { var iconId = null; var managedCause = null; $.each(item.Deviation, function (index2, deviation) { if (deviation.MessageCode == 'Vägen avstängd') iconId = deviation.IconId; if (deviation.ManagedCause) managedCause = deviation; }); var active = isActive(managedCause); if (!active) { //If managed cause is not active, check if underlying is active and in that case, use active Icon $.each(item.Deviation, function (index2, deviation) { if (isActive(deviation)) { active = true; return false; //Check done, break loop } }); } if (typeof ((((managedCause || item.Deviation[0]) || []).Geometry || []).WGS84) != "undefined") { var feature = new ol.Feature({ geometry: format.readGeometry((managedCause || item.Deviation[0]).Geometry.WGS84).transform("EPSG:4326", "EPSG:3857"), data: item, iconId: iconId || managedCause.IconId, active: active, managedCause: managedCause }); features.push(feature); } }); var source = new ol.source.Vector({ //Creates a source for the vector layer features: features }); var getIcon = function (feature, resolution) { var active = feature.get("active"); if(resolution > 40) return apiUrl + "icons/" + feature.get("iconId") + (!active ? "Planned" : "") + "?type=png16x16"; else return apiUrl + "icons/" + feature.get("iconId") + (!active ? "Planned" : "") + "?type=png32x32"; } var styleFunction = function (feature, resolution) { //Function to determine style of icons return [new ol.style.Style({ image: new ol.style.Icon(({ anchor: [0.5, 8], anchorXUnits: 'fraction', anchorYUnits: 'pixels', opacity: 0.75, src: getIcon(feature, resolution) })) })]; }; var vectorLayer = new ol.layer.Vector({ //Creates a layer for deviations source: source, style: styleFunction }); mapObject.addLayer(vectorLayer); } catch (ex) { } }, error: function (xhr, status, error) { var err = status; }, complete: function (xhr, status) { var status = status; } }); break; } } function formatDeviationText(deviation) { var text = ""; switch (deviation.MessageCode) { case "Körfältsavstängningar": text += (deviation.NumberOfLanesRestricted || null) != null ? (deviation.NumberOfLanesRestricted + " körfält avstäng" + (deviation.NumberOfLanesRestricted == 1 ? "t" : "da")) : ""; break; default: text += "<p>" + (((deviation.Message || "") + (deviation.TemporaryLimit || "")) || deviation.LocationDescriptor || "") + "</p>"; text += "<div class='table-responsive'>"; text += "<table class='table table-bordered table-striped'><tbody>"; text += formatDeviationTableRow("Starttid", deviation.StartTime); text += formatDeviationTableRow("Sluttid", deviation.EndTime); text += "</tbody></table>"; text += "</div>"; break; } return text; } function formatDeviationTableRow(header, value) { if (typeof (value) == "undefined") return ""; return "<tr><td class='text-nowrap'><strong>" + header + "</strong></td><td>" + value + "</td></tr>"; } //Checks if a deviation is currently active function isActive(deviation) { var active = false; if (typeof (deviation.Schedule) != "undefined") { $.each(deviation.Schedule, function (scheduleIndex, schedule) { var currentTime = new Date(); var startOfPeriod = new Date(schedule.StartOfPeriod); var endOfPeriod = new Date(schedule.EndOfPeriod); if (startOfPeriod <= currentTime && currentTime <= endOfPeriod) active = true; }); } else { active = true; } if (typeof (deviation.StartTime) != "undefined") { var startTime = new Date(deviation.StartTime); var endTime = new Date(deviation.EndTime) var currentTime = new Date(); if (startTime > currentTime && currentTime < endTime) active = false; } deviation.active = active; return active; } </script> </body> </html>
Streaming - Javascript EventSource Simple
Enkel klient för anslutning mot streaming-endpoint.
Enklast möjliga användning av EventSource i webbläsaren.
<html> <head> <meta charset="UTF-8"> <title>EventSource demo - simple</title> </head> <body> See browser console for output (F12). <div /> <script> var evtSource = new EventSource('https://api.trafikinfo.trafikverket.se/v2/data.json?ssereqid={entersserequestidhere}'); evtSource.onopen = function() { console.log("Connection to server opened."); }; evtSource.onmessage = function (e) { console.log(e.data); return; }; evtSource.onerror = function(e) { console.log("EventSource failed."); }; </script> </body> </html>
Streaming - Javascript Advanced Testbench
Webbapplikation för generering av dynamiska endpoints samt anslutning mot dessa.
Exempel på användarinitierad push.
Avancerad testbänk för generering av dynamiska endpoints och anslutning till dataströmmar för objekttypen TrainAnnouncement.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>EventSource demo - Trafikverket Labs</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css"> <script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.min.js"></script> <!-- Use polyfill for IE --> <script src="https://cdn.polyfill.io/v2/polyfill.js?features=EventSource"></script> <style> .message { margin-bottom: 12px !important; } .message-body { padding: 2px !important; } .table { margin-top: 5px !important; margin-bottom: 0px !important; } .col_longtimestring { width: 200px; } </style> <script> var xmlRequest = null; // Init application $(function () { // Ajax setup try { jQuery.support.cors = true; $.ajaxSetup({ type: "POST", beforeSend: function () { DisplayInfoMessage("Sending request to server"); $("#btnSend").hide(); $("#loader").show(); }, complete: function () { $("#btnSend").show(); $("#loader").hide(); }, error: function (msg) { DisplayAjaxError(msg); } }); } catch (e) { DisplayErrorMessage("An error occured while initializing the console."); } }); // Display methods function DisplayAjaxError(msg) { if (msg.statusText === "abort") return; if (msg.statusText === "error" && msg.hasOwnProperty("responseJSON") && msg.responseJSON == undefined) { DisplayErrorMessage("Request failed."); return; } if (msg.hasOwnProperty("responseJSON") && msg.responseJSON.hasOwnProperty("RESPONSE")) { var data = msg.responseJSON.RESPONSE.RESULT[0].ERROR.MESSAGE; DisplayErrorMessage("Request failed:" + msg.status + " " + msg.statusText + ". " + data); } else if (msg.hasOwnProperty("responseJSON") && msg.responseJSON.hasOwnProperty("Message")) { DisplayErrorMessage("Request failed:" + msg.status + " " + msg.statusText + ". " + msg.responseJSON.Message + ". " + msg.responseJSON.MessageDetail); } else { DisplayErrorMessage("Request failed:" + msg.status + " " + msg.statusText); } } function DisplayErrorMessage(msg) { DisplayMessage(msg, "danger", ""); } function DisplayWarningMessage(msg) { DisplayMessage(msg, "warning", ""); } function DisplayInfoMessage(msg) { DisplayMessage(msg, "info", ""); } function DisplaySuccessMessage(msg, content) { DisplayMessage(msg, "primary", content); } function DisplayMessage(msg, type, content) { const elem = $("#displayMessages"); const date = moment().format('YYYY-MM-DD HH:mm:ss'); var html = "<article class='message is-small is-" + type + "'>" + "<div class='message-body'>" + "<span class='tag is-light'>" + date + "</span> <b>" + msg + "</b><br/>"; if (content !== "") html += "<span class='container' style='padding-left: 10px; padding-right: 10px;'>" + content + "</span>"; html += "</div ></article>"; elem.prepend(html); } function ClearLog() { $("#displayMessages").empty().show(); } // Request methods function CancelRequest() { xmlRequest.abort(); } function sendRequest() { var serverurl = $("#serverUrl").val(); if (serverurl === "") { $("#serverUrl").addClass("is-danger"); return; } var xmlDocument = $("#requestEditor").val(); xmlRequest = $.ajax({ url: serverurl, contentType: "text/plain", dataType: "json", data: xmlDocument, success: function (response) { if (response === null) return; renderResponseData(response.RESPONSE.RESULT[0].TrainAnnouncement); // Render data to view try { if (response.RESPONSE.RESULT[0].INFO.SSEURL) { SseUrl = response.RESPONSE.RESULT[0].INFO.SSEURL; var responseid = Date.now(); var connectButton = " <span class='button is-small is-info is-outlined'>Click to connect to server</span>"; DisplayMessage("ServerSentEventURL received <span onclick='ConnectToSseServer(\"" + SseUrl + "&lasteventid=\", \"" + responseid + "\")' class='button is-small is-info is-outlined'>Click to connect to server</span><input id=\"" + responseid +"\" style='width: 200px;' class='input is-small is-rounded' type='text' placeholder='LastEventID (optional)'>", "info", SseUrl); } } catch (e) { SseUrl = ""; } } }); } // Render methods function renderResponseData(data) { var content = renderData(data); DisplaySuccessMessage("Response received", content); } function renderEventSourceData(eventid, data) { var content = renderData(data); DisplaySuccessMessage("EventSource message received. <span class='tag is-primary'>id: \"" + eventid + "\"</span>", content); } function renderData(data) { var content = "<table class='table is-bordered is-striped is-narrow is-fullwidth'><thead><tr><th class='col_longtimestring'>Train</th><th>Station</th><th>Time at location</th></tr></thead><tbody>"; $.each(data, function (index, value) { content += "<tr><td>" + value.AdvertisedTrainIdent + "</td><td>" + value.LocationSignature + "</td><td>" + value.TimeAtLocation + "</td></tr>"; }); content += "</tbody></table >"; return content; } // EventSource methods var SseUrl = ""; var evtSource; function ConnectToSseServer(url, requestid) { if (evtSource && evtSource.readyState !== 2) { if (evtSource.readyState === 0) DisplayInfoMessage('Already trying to reconnect.'); if (evtSource.readyState === 1) DisplayInfoMessage('Connection already established.'); return; } $('html, body').animate({ scrollTop: $('#eventSourceStatus').offset().top - 20 }, 'slow'); if (typeof (EventSource) == "undefined") { DisplayErrorMessage("EventSource not supported, please consider using a polyfill."); return; } evtSource = new EventSource(url + $("#"+requestid).val()); DisplayInfoMessage("Connecting to server"); evtSource.onopen = function () { setEventSourceStatus("connected"); }; evtSource.onmessage = function (e) { var data = JSON.parse(e.data); if (data.RESPONSE.RESULT[0].ERROR) { evtSource.close(); DisplayErrorMessage(data.RESPONSE.RESULT[0].ERROR.MESSAGE); setEventSourceStatus("notconnected"); return; } var arr = data.RESPONSE.RESULT[0].TrainAnnouncement; renderEventSourceData(e.lastEventId, arr); return; } evtSource.onerror = function (e) { if(this.readyState==0) setEventSourceStatus("reconnecting"); else setEventSourceStatus("failed"); }; } function DisconnectFromSseServer() { try { evtSource.close(); setEventSourceStatus("closed"); } catch (e) { // continue regardless of error } } function setEventSourceStatus(status) { $(".esstatus").hide(); switch (status) { case "failed": $("#notconnected").show(); DisplayErrorMessage('EventSource failed'); setEventSourceStatus("closed"); break; case "notconnected": $("#notconnected").show(); DisplayInfoMessage('Not connected'); break; case "connected": $("#connected").show(); DisplayInfoMessage("Connection to server opened"); break; case "reconnecting": $("#reconnecting").show(); DisplayErrorMessage("EventSource failed. Reconnecting ..."); break; case "closed": $("#closed").show(); DisplayInfoMessage('Connection closed'); break; } } </script> </head> <body> <section class="section"> <div class="container"> <h1 class="title"> EventSource demo </h1> <p class="subtitle"> Trafikverket Labs </p> <hr style="margin-bottom: 10px;"> <div class="field"> <label class="label">Server URL</label> <div class="control"> <input id="serverUrl" class="input is-primary" type="text" value="https://api.trafikinfo.trafikverket.se/v2/data.json"/> </div> </div> <div class="field"> <label class="label">Query</label> <div class="control"> <textarea id="requestEditor" class="textarea is-primary is-small" > <REQUEST> <LOGIN authenticationkey='yourauthenticationkey' /> <QUERY objecttype='TrainAnnouncement' schemaversion='1.3' limit='5' orderby='TimeAtLocation' sseurl="false"> <FILTER> <GT name="TimeAtLocation" value="2999-01-01T12:00:00.000+02:00" /> </FILTER> <INCLUDE>AdvertisedTrainIdent</INCLUDE> <INCLUDE>LocationSignature</INCLUDE> <INCLUDE>TimeAtLocation</INCLUDE> </QUERY> </REQUEST></textarea> </div> </div> <div class="field"> <div class="content"> <ol> <li>Set the datetime in the filter to a value that makes sense.</li> <li>Test to set the sseurl-attribute to 'true'.</li> </ol> </div> <div class="buttons is-right"> <span id="btnSend" class="button is-primary is-outlined" onclick="sendRequest()">SEND</span> <span id="loader" style="display: none" class="button is-primary is-loading">SEND</span> <span onclick="CancelRequest()" class="button is-primary is-outlined">Cancel</span> </div> </div> <hr style="margin-bottom: 10px;"> <div id="eventSourceStatus" class="content"> <label class="label">EventSource status</label> <span id="notconnected" class="esstatus tag is-info">Not connected</span> <span id="connected" class="esstatus" style="display:none"><span class="tag is-primary">Connected to server</span> <span onclick="DisconnectFromSseServer()" class="button is-small is-primary is-outlined">Close connection</span></span> <span id="reconnecting" class="esstatus" style="display:none"><span class="tag is-warning">Connection failed, reconnecting ...</span> <span onclick="DisconnectFromSseServer()" class="button is-small is-warning is-outlined">Cancel</span></span> <span id="closed" class="esstatus tag is-danger" style="display:none">Connection closed</span> </div> <hr style="margin-bottom: 10px;"> <div class="content"> <div class="columns"> <div class="column"> <label class="label">Log</label> </div> <div class="column"> <div class="buttons is-right"> <span onclick="ClearLog()" class="button is-primary is-outlined is-small">Clear log</span> </div> </div> </div> </div> <div id="displayMessages" class="content"></div> </div> </section> </body> </html>
Streaming - .NET client
.NET-applikation i C# som demonstrerar klient som prenumerarar på tågannonseringar.
Exempel på användarinitierad push.
.NET-applikation i C# som demonstrerar klient som prenumerarar på tågannonseringar.