diff --git a/App.config b/App.config
index 1156d13..8f575b3 100644
--- a/App.config
+++ b/App.config
@@ -4,20 +4,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/DataService.cs b/DataService.cs
index 3925ca8..8cbcc49 100644
--- a/DataService.cs
+++ b/DataService.cs
@@ -1,136 +1,89 @@
using System;
using System.Configuration;
+using System.Linq;
using System.Net;
+using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
-using Newtonsoft.Json;
-
namespace TelemetryJsonService
{
- // Source: http://www.gabescode.com/dotnet/2018/11/01/basic-HttpListener-web-service.html
internal static class DataService
{
- private static volatile bool _keepGoing = true;
-
- private static HttpListener Listener;
- private static Task _mainLoop;
-
- public static string Address { get; private set; }
public static int Port { get; private set; }
public static string JsonData { get; set; }
public static void StartWebServer()
{
- if (_mainLoop != null && !_mainLoop.IsCompleted) return;
-
- Address = ConfigurationManager.AppSettings["address"];
Port = int.Parse(ConfigurationManager.AppSettings["port"]);
- Listener = new HttpListener { Prefixes = { $"http://{Address}:{Port}/" } };
- _mainLoop = MainLoop();
+ Task.Run(() => StartTcpListener(Port));
}
- ///
- /// Call this to stop the web server. It will not kill any requests currently being processed.
- ///
- public static void StopWebServer()
+ static async Task StartTcpListener(int port)
{
- _keepGoing = false;
- lock (Listener)
+ TcpListener tcpListener = new TcpListener(IPAddress.Any, port);
+ tcpListener.Start();
+ Console.WriteLine($"Listening on port {port}");
+
+ try
{
- //Use a lock so we don't kill a request that's currently being processed
- Listener.Stop();
+ while (true)
+ {
+ TcpClient client = await tcpListener.AcceptTcpClientAsync();
+ _ = HandleClientAsync(client);
+ }
}
- try
+ catch (Exception ex)
{
- _mainLoop.Wait();
+ Console.WriteLine($"Exception: {ex.Message}");
}
- catch { /* ¯\_(ツ)_/¯ */ }
- }
-
- ///
- /// The main loop to handle requests into the HttpListener
- ///
- ///
- private static async Task MainLoop()
- {
- Listener.Start();
- while (_keepGoing)
+ finally
{
- try
- {
- //GetContextAsync() returns when a new request come in
- var context = await Listener.GetContextAsync();
- lock (Listener)
- {
- if (_keepGoing) ProcessRequest(context);
- }
- }
- catch (Exception e)
- {
- if (e is HttpListenerException) return; //this gets thrown when the listener is stopped
- //TODO: Log the exception
- }
+ tcpListener.Stop();
+ Console.WriteLine("Listener stopped.");
}
}
///
/// Handle an incoming request
///
- /// The context of the incoming request
- private static void ProcessRequest(HttpListenerContext context)
+ static async Task HandleClientAsync(TcpClient tcpClient)
{
- using (var response = context.Response)
+ using (NetworkStream stream = tcpClient.GetStream())
{
- try
- {
- var handled = false;
-
- // CORS
- response.AppendHeader("Access-Control-Allow-Origin", "*");
+ byte[] buffer = new byte[1024];
+ int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
+ string request = Encoding.UTF8.GetString(buffer, 0, bytesRead);
+ Console.WriteLine($"Received request: {request}");
- switch (context.Request.Url.AbsolutePath)
- {
- // Define routes
- case "/":
- switch (context.Request.HttpMethod)
- {
- case "OPTIONS":
- response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With");
- response.AddHeader("Access-Control-Allow-Methods", "OPTIONS, GET");
- response.AddHeader("Access-Control-Max-Age", "1728000");
- response.StatusCode = 200;
- handled = true;
- break;
+ // Parse the HTTP method
+ string httpMethod = "GET";
+ string[] requestLines = request.Split('\n');
+ string firstLine = requestLines.FirstOrDefault();
+ string[] tokens = firstLine?.Split(' ');
- case "GET":
- response.ContentType = "application/json";
- var buffer = Encoding.UTF8.GetBytes(JsonData);
- response.ContentLength64 = buffer.Length;
- response.OutputStream.Write(buffer, 0, buffer.Length);
- handled = true;
- break;
-
- }
- break;
- }
- if (!handled)
- {
- response.StatusCode = 404;
- }
- }
- catch (Exception e)
+ if (tokens != null && tokens.Length >= 2)
{
- //Return the exception details to the client
- response.StatusCode = 500;
- response.ContentType = "application/json";
- var buffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(e));
- response.ContentLength64 = buffer.Length;
- response.OutputStream.Write(buffer, 0, buffer.Length);
+ httpMethod = tokens[0];
+ Console.WriteLine($"HTTP Method: {httpMethod}");
+ }
+
+ string responseText = "HTTP/1.1 200 OK\r\n" +
+ "Content-Type: application/json\r\n" +
+ "Access-Control-Allow-Origin: *\r\n" + // Allow requests from any origin
+ "Access-Control-Allow-Methods: GET, OPTIONS\r\n" + // Specify allowed methods
+ "Access-Control-Allow-Headers: Content-Type, Accept, X-Requested-With\r\n\r\n"; // Specify allowed headers
- //TODO: Log the exception
+ if ( httpMethod == "GET" )
+ {
+ responseText += JsonData;
}
+
+ byte[] responseBytes = Encoding.UTF8.GetBytes(responseText);
+ await stream.WriteAsync(responseBytes, 0, responseBytes.Length);
}
+
+ tcpClient.Close();
}
}
}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
index b65ac4c..2eaeebc 100644
--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -8,9 +8,9 @@
[assembly: AssemblyTitle("TelemetryJsonService")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
+[assembly: AssemblyCompany("dichternebel")]
[assembly: AssemblyProduct("TelemetryJsonService")]
-[assembly: AssemblyCopyright("Copyright © 2022")]
+[assembly: AssemblyCopyright("Copyright © dichternebel 2022")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.9.2.0")]
-[assembly: AssemblyFileVersion("0.9.2.0")]
+[assembly: AssemblyVersion("0.9.5.0")]
+[assembly: AssemblyFileVersion("0.9.5.0")]
diff --git a/README.md b/README.md
index f28f72b..7c7d78f 100644
--- a/README.md
+++ b/README.md
@@ -59,14 +59,15 @@ If you want to create e.g. a **dashboard for ETS2** instead of overlays it might
- Download the [SCS-SDK-plugin v.1.12.1](https://github.com/RenCloud/scs-sdk-plugin/releases/tag/V.1.12.1) and copy the `Win64\scs-telemetry.dll` into `[...]\SteamLibrary\steamapps\common\Euro Truck Simulator 2\bin\win_x64\plugins`
- Download this thing from the [Releases](https://github.com//dichternebel/scs-telemetry-json-service/releases/latest/) section and extract it to wherever you want
- Start the executable and keep it running (it's located to the system tray then)
+- Please confirm the firewall exception if you want to access the service from other LAN devices
## Limitations
- Must run on the same machine as your game
## Customization
-- Change the used port and address in `TelemetryJsonService.exe.config` to match your needs
+- Change the used port in `TelemetryJsonService.exe.config` to match your needs
-## Using it in OBS
+## Using overlays in OBS
- Add two browser sources to OBS for the job and the status telemetry overlays
- Change their width and height sizes filling your OBS resolution (not manually, go to the settings dialog of the browser source!)
- change the source to **local file** and chose `[...]\scs-telemetry-json-service\overlays\overlay-job.html` and the other to `[...]\scs-telemetry-json-service\overlays\overlay-status.html`
diff --git a/TelemetryJsonService.cs b/TelemetryJsonService.cs
index 2ba7951..5f1b16c 100644
--- a/TelemetryJsonService.cs
+++ b/TelemetryJsonService.cs
@@ -27,7 +27,7 @@ public TelemetryJsonService()
DataService.StartWebServer();
this.UpdateSharedJs();
- this.tbUrl.Text = $"http://{DataService.Address}:{DataService.Port}/";
+ this.tbUrl.Text = $"http://localhost:{DataService.Port}/";
}
catch (Exception ex)
{
@@ -74,7 +74,6 @@ private void UpdateSharedJs()
resourceContent = reader.ReadToEnd();
}
- resourceContent = resourceContent.Replace("{{address}}", DataService.Address);
resourceContent = resourceContent.Replace("{{port}}", DataService.Port.ToString());
File.WriteAllText(Path.Combine(baseDir, "overlays/js", "shared.js"), resourceContent);
}
diff --git a/shared-template.js b/shared-template.js
index 3554584..9985292 100644
--- a/shared-template.js
+++ b/shared-template.js
@@ -41,33 +41,30 @@ function setPollingInterval() {
// Slow down polling interval when connection is lost
function checkPollingInterval() {
- if (retryCounter === 10 && timer === 100) {
+ if (retryCounter === 10 && timer === 1000) {
isServiceConnected = false;
- console.log("Too many connection errors: changing interval to 1sec...");
- timer = 1000;
- setPollingInterval();
- }
- if (retryCounter === 19 && timer === 1000) {
- console.log(
- "Too many connection errors: changing interval to 10secs and hiding '.game-connected'...",
- );
+ console.log("Too many connection errors: changing interval to 10sec and hiding '.game-connected'...");
timer = 10000;
setPollingInterval();
-
$(".game-connected").css({
- visibility: "hidden",
+ visibility: "hidden"
});
- } else if (retryCounter === 0 && timer > 100) {
+ }
+ if (retryCounter === 19 && timer === 10000) {
+ console.log("Too many connection errors: changing interval to 30secs...");
+ timer = 30000;
+ setPollingInterval();
+ } else if (retryCounter === 0 && timer > 1000) {
isServiceConnected = true;
- console.log("We are back to business! Changing interval to 100ms...");
- timer = 100;
+ console.log("We are back to business! Changing interval to 1000ms...");
+ timer = 1000;
setPollingInterval();
}
}
// Run that creepy thing!
function execute() {
- $.getJSON("http://{{address}}:{{port}}/", function (json) {
+ $.getJSON("http://localhost:{{port}}/", function (json) {
data = json;
})
.done(function () {