Commit a3cc0c2e by Stefan Schreistetter

Changed architecture to reflect separation between web socket server and eye tracker.

parent 4dca5182
...@@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.29209.62 ...@@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.29209.62
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GazeWebSocketServer", "GazeWebSocketServer\GazeWebSocketServer.csproj", "{F8F11E64-7946-4054-8C27-F0FCAF967F1A}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GazeWebSocketServer", "GazeWebSocketServer\GazeWebSocketServer.csproj", "{F8F11E64-7946-4054-8C27-F0FCAF967F1A}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrackerBridge", "TrackerBridge\TrackerBridge.csproj", "{64D52257-ECA7-4F4D-A901-B14D544A1D0A}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
...@@ -15,6 +17,10 @@ Global ...@@ -15,6 +17,10 @@ Global
{F8F11E64-7946-4054-8C27-F0FCAF967F1A}.Debug|Any CPU.Build.0 = Debug|Any CPU {F8F11E64-7946-4054-8C27-F0FCAF967F1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8F11E64-7946-4054-8C27-F0FCAF967F1A}.Release|Any CPU.ActiveCfg = Release|Any CPU {F8F11E64-7946-4054-8C27-F0FCAF967F1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F8F11E64-7946-4054-8C27-F0FCAF967F1A}.Release|Any CPU.Build.0 = Release|Any CPU {F8F11E64-7946-4054-8C27-F0FCAF967F1A}.Release|Any CPU.Build.0 = Release|Any CPU
{64D52257-ECA7-4F4D-A901-B14D544A1D0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{64D52257-ECA7-4F4D-A901-B14D544A1D0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{64D52257-ECA7-4F4D-A901-B14D544A1D0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{64D52257-ECA7-4F4D-A901-B14D544A1D0A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tobii.Research;
namespace GazeWebSocketServer
{
class EyeTrackerClient
{
private IEyeTracker eyeTracker;
private GazeDataProcessor gazeDataProcessor;
private List<GazeCoordinateBehavior> gazeCoordinateBehaviors;
public EyeTrackerClient(ConfigurationData config)
{
gazeCoordinateBehaviors = new List<GazeCoordinateBehavior>();
while (eyeTracker == null)
{
EyeTrackerCollection eyeTrackers = EyeTrackingOperations.FindAllEyeTrackers();
if (eyeTrackers.Count > 0)
{
foreach(IEyeTracker t in eyeTrackers)
{
if(config.TrackerSerialNumber == t.SerialNumber)
{
eyeTracker = t;
}
}
}
}
gazeDataProcessor = new GazeDataProcessor();
eyeTracker.SetGazeOutputFrequency(config.TrackerFrequency);
}
public void Start(GazeCoordinateBehavior gazeCoordinateBehavior)
{
gazeCoordinateBehaviors.Add(gazeCoordinateBehavior);
eyeTracker.GazeDataReceived += GazeDataReceivedHandler;
}
public void Stop()
{
eyeTracker.GazeDataReceived -= GazeDataReceivedHandler;
}
private void GazeDataReceivedHandler(object sender, GazeDataEventArgs e)
{
GazeData gazeData = gazeDataProcessor.Extract(e);
foreach(GazeCoordinateBehavior behavior in gazeCoordinateBehaviors)
{
behavior.Publish(gazeData);
}
Console.WriteLine(gazeData.ToString());
}
}
}
\ No newline at end of file
...@@ -3,34 +3,15 @@ using WebSocketSharp; ...@@ -3,34 +3,15 @@ using WebSocketSharp;
using WebSocketSharp.Server; using WebSocketSharp.Server;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using TrackerBridge;
namespace GazeWebSocketServer namespace GazeWebSocketServer
{ {
public class GazeCoordinateBehavior : WebSocketBehavior public class GazeCoordinateBehavior : WebSocketBehavior
{ {
private EyeTrackerClient eyeTrackerClient; public GazeCoordinateBehavior()
public GazeCoordinateBehavior(ConfigurationData config)
{ {
Console.WriteLine("Creating behavior..."); Console.WriteLine("Creating behavior...");
eyeTrackerClient = new EyeTrackerClient(config);
eyeTrackerClient.Start(this);
}
//~GazeCoordinateBehavior()
//{
// eyeTrackerClient.Stop();
//}
//protected override void OnOpen()
//{
// throw new NotImplementedException();
// //base.OnOpen();
//}
internal void Publish(GazeData gazeData)
{
Sessions?.Broadcast(gazeData.ToString());
} }
} }
} }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WebSocketSharp.Server;
using TrackerBridge;
namespace GazeWebSocketServer
{
class GazeServer
{
private WebSocketServer wssv;
public GazeServer(Int32 port, String endpoint)
{
wssv = new WebSocketServer(port);
wssv.Log.Level = WebSocketSharp.LogLevel.Trace;
wssv.AddWebSocketService(endpoint, () => new GazeCoordinateBehavior());
}
public void Start()
{
wssv.Start();
}
public void Publish(GazeData gazeData)
{
WebSocketServiceManager wssm = wssv.WebSocketServices;
foreach(WebSocketServiceHost serviceHost in wssm.Hosts)
{
if (serviceHost.Type == typeof(GazeCoordinateBehavior))
{
serviceHost.Sessions?.Broadcast(gazeData.ToString());
}
}
}
}
}
...@@ -54,10 +54,8 @@ ...@@ -54,10 +54,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ConfigurationData.cs" /> <Compile Include="ConfigurationData.cs" />
<Compile Include="EyeTrackerClient.cs" />
<Compile Include="GazeCoordinateBehavior.cs" /> <Compile Include="GazeCoordinateBehavior.cs" />
<Compile Include="GazeData.cs" /> <Compile Include="GazeServer.cs" />
<Compile Include="GazeDataProcessor.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
...@@ -66,6 +64,12 @@ ...@@ -66,6 +64,12 @@
<None Include="ClassDiagram1.cd" /> <None Include="ClassDiagram1.cd" />
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TrackerBridge\TrackerBridge.csproj">
<Project>{64d52257-eca7-4f4d-a901-b14d544a1d0a}</Project>
<Name>TrackerBridge</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Tobii.Research.x64.1.7.0.1070\build\Tobii.Research.x64.targets" Condition="Exists('..\packages\Tobii.Research.x64.1.7.0.1070\build\Tobii.Research.x64.targets')" /> <Import Project="..\packages\Tobii.Research.x64.1.7.0.1070\build\Tobii.Research.x64.targets" Condition="Exists('..\packages\Tobii.Research.x64.1.7.0.1070\build\Tobii.Research.x64.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
......
using System; using System;
using System.Threading.Tasks;
using System.Threading;
using WebSocketSharp; using WebSocketSharp;
using WebSocketSharp.Server; using WebSocketSharp.Server;
using Tobii.Research; using Tobii.Research;
using TrackerBridge;
namespace GazeWebSocketServer namespace GazeWebSocketServer
{ {
public class Program public class Program
{ {
private static GazeServer gazeServer;
public static void Main(string[] args) public static void Main(string[] args)
{ {
ConfigurationData.InitializeUnexistingWithDefaults(); ConfigurationData.InitializeUnexistingWithDefaults();
ConfigurationData config = ConfigurationData.ParseToObject(); ConfigurationData config = ConfigurationData.ParseToObject();
var wssv = new WebSocketServer(config.WebSocketPort); TobiiEyeTracker tobiiEyeTracker = new TobiiEyeTracker(config.TrackerSerialNumber);
wssv.KeepClean = true; tobiiEyeTracker.ConnectionEvent += OnConnectionEstablished;
GazeCoordinateBehavior behavior = new GazeCoordinateBehavior(config); tobiiEyeTracker.ConnectionTimeout += OnConnectionTimeout;
wssv.AddWebSocketService(config.WebSocketEndpoint, () => behavior); tobiiEyeTracker.GazeDataAvailable += OnGazeDataAvailable;
tobiiEyeTracker.Connect();
wssv.Start(); gazeServer = new GazeServer(config.WebSocketPort, config.WebSocketEndpoint);
Console.ReadKey(true); gazeServer.Start();
wssv.Stop(); Console.ReadLine();
}
private static void OnGazeDataAvailable(TobiiEyeTracker sender, GazeData data)
{
Console.WriteLine(data);
gazeServer.Publish(data);
}
private static void OnConnectionTimeout(TobiiEyeTracker sender)
{
Console.WriteLine("Timeout while searching for trackers.");
}
private static void OnConnectionEstablished(TobiiEyeTracker sender)
{
Console.WriteLine($"Tracker {sender.ToString()} connected.");
ConfigurationData config = ConfigurationData.ParseToObject();
sender.SetTrackingFrequency(config.TrackerFrequency);
} }
} }
} }
\ No newline at end of file
using System;
namespace TobiiBridge
{
public class EyeTracker
{
public EyeTracker()
{
}
public EyeTracker(String serialNumber)
{
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Tobii.Research.x64" Version="1.7.0.1070" />
</ItemGroup>
</Project>
...@@ -4,9 +4,9 @@ using System.Linq; ...@@ -4,9 +4,9 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace GazeWebSocketServer namespace TrackerBridge
{ {
struct GazeData public struct GazeData
{ {
public readonly float leftX; public readonly float leftX;
public readonly float leftY; public readonly float leftY;
......
...@@ -6,9 +6,9 @@ using System.Text; ...@@ -6,9 +6,9 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Tobii.Research; using Tobii.Research;
namespace GazeWebSocketServer namespace TrackerBridge
{ {
class GazeDataProcessor public class GazeDataProcessor
{ {
readonly float screenHeight; readonly float screenHeight;
readonly float screenWidth; readonly float screenWidth;
......
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die einer Assembly zugeordnet sind.
[assembly: AssemblyTitle("TrackerBridge")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("OTH Regensburg")]
[assembly: AssemblyProduct("TrackerBridge")]
[assembly: AssemblyCopyright("Copyright © OTH Regensburg 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
[assembly: ComVisible(false)]
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
[assembly: Guid("64d52257-eca7-4f4d-a901-b14d544a1d0a")]
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
// Hauptversion
// Nebenversion
// Buildnummer
// Revision
//
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
// indem Sie "*" wie unten gezeigt eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tobii.Research;
namespace TrackerBridge
{
public class TobiiEyeTracker
{
public delegate void ConnectionEventHandler(TobiiEyeTracker sender);
public delegate void GazeDataHandler(TobiiEyeTracker sender, GazeData data);
public event ConnectionEventHandler ConnectionEvent;
public event ConnectionEventHandler ConnectionTimeout;
public event GazeDataHandler GazeDataAvailable;
public Boolean IsConnected { get; private set; }
private IEyeTracker eyeTracker = null;
private String serialNumber = null;
private GazeDataProcessor gazeDataProcessor;
public TobiiEyeTracker()
{
gazeDataProcessor = new GazeDataProcessor();
}
public TobiiEyeTracker(String serialNumber) : this()
{
this.serialNumber = serialNumber;
}
public float GetTrackingFrequency()
{
if (eyeTracker != null)
{
return eyeTracker.GetGazeOutputFrequency();
}
else
{
throw new NullReferenceException();
}
}
public void SetTrackingFrequency(float value)
{
if (eyeTracker != null)
{
eyeTracker.SetGazeOutputFrequency(value);
}
}
public void Connect()
{
Task task = new Task(() => InitiateConnection());
task.Start();
}
private void InitiateConnection()
{
DateTime time = DateTime.Now;
while (eyeTracker == null)
{
EyeTrackerCollection eyeTrackers = EyeTrackingOperations.FindAllEyeTrackers();
if (eyeTrackers.Count > 0)
{
if (serialNumber == null)
{
eyeTracker = eyeTrackers[0];
break;
}
else
{
foreach (IEyeTracker t in eyeTrackers)
{
if (serialNumber == t.SerialNumber)
{
eyeTracker = t;
break;
}
}
}
}
if (eyeTracker != null)
{
break;
}
if ((DateTime.Now - time) > (new TimeSpan(0, 0, 30)))
{
ConnectionTimeout?.Invoke(this);
}
}
eyeTracker.GazeDataReceived += OnGazeDataReceived;
SetTrackingFrequency(600f);
ConnectionEvent?.Invoke(this);
}
private void OnGazeDataReceived(object sender, GazeDataEventArgs e)
{
GazeData gazeData = gazeDataProcessor.Extract(e);
GazeDataAvailable?.Invoke(this, gazeData);
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{64D52257-ECA7-4F4D-A901-B14D544A1D0A}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TrackerBridge</RootNamespace>
<AssemblyName>TrackerBridge</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="Tobii.Research, Version=1.7.0.1070, Culture=neutral, PublicKeyToken=70326046dcdce6cb, processorArchitecture=MSIL">
<HintPath>..\packages\Tobii.Research.x64.1.7.0.1070\lib\net452\Tobii.Research.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="GazeData.cs" />
<Compile Include="GazeDataProcessor.cs" />
<Compile Include="TobiiEyeTracker.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Tobii.Research.x64.1.7.0.1070\build\Tobii.Research.x64.targets" Condition="Exists('..\packages\Tobii.Research.x64.1.7.0.1070\build\Tobii.Research.x64.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}".</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Tobii.Research.x64.1.7.0.1070\build\Tobii.Research.x64.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Tobii.Research.x64.1.7.0.1070\build\Tobii.Research.x64.targets'))" />
</Target>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Tobii.Research.x64" version="1.7.0.1070" targetFramework="net472" />
</packages>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment