From 06c54375e66875ea3eb7f3231adeddc7b71f139d Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Fri, 11 Mar 2016 23:04:58 +0100 Subject: [PATCH] Implemented retrieval of Division data --- Artemis/Artemis/Artemis.csproj | 7 +- .../Logitech/Utilities/LogitechGSDK.cs | 2 +- Artemis/Artemis/Managers/MainManager.cs | 10 + .../Games/TheDivision/TheDivisionModel.cs | 37 +++- Artemis/Artemis/Resources/LogitechLED.dll | Bin 67584 -> 171520 bytes .../Utilities/LogitechDll/DllManager.cs | 16 +- .../LogitechDll/LogitechNamedPipe.cs | 23 --- .../Utilities/LogitechDll/NamedPipeServer.cs | 189 ++++++++++++++++++ .../Utilities/LogitechDll/PipeServer.cs | 132 ++++++++++++ Artemis/Artemis/packages.config | 1 - 10 files changed, 378 insertions(+), 39 deletions(-) delete mode 100644 Artemis/Artemis/Utilities/LogitechDll/LogitechNamedPipe.cs create mode 100644 Artemis/Artemis/Utilities/LogitechDll/NamedPipeServer.cs create mode 100644 Artemis/Artemis/Utilities/LogitechDll/PipeServer.cs diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index 9a20f58be..c3848c7c9 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -163,10 +163,6 @@ False - - ..\packages\NamedPipeWrapper.1.4.0\lib\net40\NamedPipeWrapper.dll - True - ..\packages\NAudio.1.7.3\lib\net35\NAudio.dll True @@ -371,7 +367,8 @@ - + + diff --git a/Artemis/Artemis/KeyboardProviders/Logitech/Utilities/LogitechGSDK.cs b/Artemis/Artemis/KeyboardProviders/Logitech/Utilities/LogitechGSDK.cs index 87495914c..b3e1bd9ed 100644 --- a/Artemis/Artemis/KeyboardProviders/Logitech/Utilities/LogitechGSDK.cs +++ b/Artemis/Artemis/KeyboardProviders/Logitech/Utilities/LogitechGSDK.cs @@ -68,7 +68,7 @@ namespace Artemis.KeyboardProviders.Logitech.Utilities int greenPercentage, int bluePercentage); [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] - public static extern bool LogiLedSetLightingForKeyWithKeyName(KeyboardNames keyCode, int redPercentage, + public static extern bool LogiLedSetLightingForKeyWithKeyName(int keyCode, int redPercentage, int greenPercentage, int bluePercentage); [DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)] diff --git a/Artemis/Artemis/Managers/MainManager.cs b/Artemis/Artemis/Managers/MainManager.cs index 444aa2c88..79e394518 100644 --- a/Artemis/Artemis/Managers/MainManager.cs +++ b/Artemis/Artemis/Managers/MainManager.cs @@ -2,11 +2,13 @@ using System.Diagnostics; using System.Linq; using System.Threading; +using System.Windows.Forms; using Artemis.Events; using Artemis.Models; using Artemis.Services; using Artemis.Utilities.GameState; using Artemis.Utilities.Keyboard; +using Artemis.Utilities.LogitechDll; using Caliburn.Micro; namespace Artemis.Managers @@ -47,8 +49,13 @@ namespace Artemis.Managers // Create and start the web server GameStateWebServer = new GameStateWebServer(); GameStateWebServer.Start(); + + // Start the named pipe + PipeServer = new PipeServer(); + PipeServer.Start("artemis"); } + public PipeServer PipeServer { get; set; } public BackgroundWorker UpdateWorker { get; set; } public BackgroundWorker ProcessWorker { get; set; } @@ -65,6 +72,7 @@ namespace Artemis.Managers public bool Suspended { get; set; } public bool Running { get; private set; } + public event PauseCallbackHandler PauseCallback; /// @@ -137,7 +145,9 @@ namespace Artemis.Managers { Stop(); ProcessWorker.CancelAsync(); + ProcessWorker.CancelAsync(); GameStateWebServer.Stop(); + //NamedPipeServer.StopServer(); } public void Restart() diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs index a8b25b42e..92dc1a9a6 100644 --- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs +++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs @@ -1,6 +1,10 @@ -using System.Drawing; +using System; +using System.Diagnostics; +using System.Drawing; +using Artemis.KeyboardProviders.Logitech.Utilities; using Artemis.Managers; using Artemis.Models; +using Artemis.Utilities.LogitechDll; namespace Artemis.Modules.Games.TheDivision { @@ -23,17 +27,42 @@ namespace Artemis.Modules.Games.TheDivision public override void Dispose() { Initialized = false; + DllManager.RestoreDll(); } public override void Enable() { Initialized = false; - - // Enable logic, if any - + DllManager.PlaceDll(); + MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage; Initialized = true; } + private void PipeServerOnPipeMessage(string reply) + { + // Convert the given string to a list of ints + var stringParts = reply.Split(' '); + var parts = new int[stringParts.Length]; + for (var i = 0; i < stringParts.Length; i++) + parts[i] = int.Parse(stringParts[i]); + + if (parts[0] == 1) + InterpertrateDivisionKey(parts); + + } + + // Parses Division key data to game data + private void InterpertrateDivisionKey(int[] parts) + { + // F1 to F4 indicate the player and his party. Blinks red on damage taken + + // R blinks white when low on ammo + + // G turns white when holding a grenade, turns off when out of grenades + + // V blinks on low HP + } + public override void Update() { } diff --git a/Artemis/Artemis/Resources/LogitechLED.dll b/Artemis/Artemis/Resources/LogitechLED.dll index 9ecba3c771007852803d73dddedcbd6a01a4d5fd..2d722626e732787023621b9594aeab19152359b2 100644 GIT binary patch literal 171520 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"ArtemisLogitech"); - - LogitechPipe.ClientMessage += LogitechPipeOnClientMessage; - LogitechPipe.Start(); - } - - public NamedPipeServer LogitechPipe { get; set; } - - private void LogitechPipeOnClientMessage(NamedPipeConnection connection, string message) - { - Debug.WriteLine(message); - } - } -} \ No newline at end of file diff --git a/Artemis/Artemis/Utilities/LogitechDll/NamedPipeServer.cs b/Artemis/Artemis/Utilities/LogitechDll/NamedPipeServer.cs new file mode 100644 index 000000000..5557ad0bf --- /dev/null +++ b/Artemis/Artemis/Utilities/LogitechDll/NamedPipeServer.cs @@ -0,0 +1,189 @@ +using System; +using System.IO; +using System.IO.Pipes; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using Microsoft.Win32.SafeHandles; + +namespace Artemis.Utilities.LogitechDll +{ + public class NamedPipeServer + { + public const uint DUPLEX = 0x00000003; + public const uint FILE_FLAG_OVERLAPPED = 0x40000000; + + public const int BUFFER_SIZE = 100; + private SafeFileHandle clientHandle; + public Client clientse; + public int ClientType; + private Thread listenThread; + + public string pipeName; + + public NamedPipeServer(string PName, int Mode) + { + pipeName = PName; + ClientType = Mode; //0 Reading Pipe, 1 Writing Pipe + } + + public event PipeDataReceivedEventHandler PipeDataReceived; + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern SafeFileHandle CreateNamedPipe( + string pipeName, + uint dwOpenMode, + uint dwPipeMode, + uint nMaxInstances, + uint nOutBufferSize, + uint nInBufferSize, + uint nDefaultTimeOut, + IntPtr lpSecurityAttributes); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern int ConnectNamedPipe( + SafeFileHandle hNamedPipe, + IntPtr lpOverlapped); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern int DisconnectNamedPipe( + SafeFileHandle hNamedPipe); + + public void Start() + { + listenThread = new Thread(ListenForClients); + listenThread.Start(); + } + + private void ListenForClients() + { + while (true) + { + clientHandle = CreateNamedPipe(pipeName, DUPLEX | FILE_FLAG_OVERLAPPED, 0, 255, BUFFER_SIZE, BUFFER_SIZE, + 0, IntPtr.Zero); + //could not create named pipe + if (clientHandle.IsInvalid) + return; + + var success = ConnectNamedPipe(clientHandle, IntPtr.Zero); + + //could not connect client + if (success == 0) + return; + + clientse = new Client(); + clientse.handle = clientHandle; + clientse.stream = new FileStream(clientse.handle, FileAccess.ReadWrite, BUFFER_SIZE, true); + + if (ClientType == 0) + { + var readThread = new Thread(Read); + readThread.Start(); + } + } + } + + private void Read() + { + //Client client = (Client)clientObj; + //clientse.stream = new FileStream(clientse.handle, FileAccess.ReadWrite, BUFFER_SIZE, true); + byte[] buffer = null; + var encoder = new ASCIIEncoding(); + + while (true) + { + var bytesRead = 0; + + try + { + buffer = new byte[BUFFER_SIZE]; + bytesRead = clientse.stream.Read(buffer, 0, BUFFER_SIZE); + } + catch + { + //read error has occurred + break; + } + + //client has disconnected + if (bytesRead == 0) + break; + + //fire message received event + //if (this.MessageReceived != null) + // this.MessageReceived(clientse, encoder.GetString(buffer, 0, bytesRead)); + + var ReadLength = 0; + for (var i = 0; i < BUFFER_SIZE; i++) + { + if (buffer[i].ToString("x2") != "cc") + { + ReadLength++; + } + else + break; + } + if (ReadLength > 0) + { + var Rc = new byte[ReadLength]; + Buffer.BlockCopy(buffer, 0, Rc, 0, ReadLength); + OnPipeDataReceived(new PipeDataReceivedEventArgs(encoder.GetString(Rc, 0, ReadLength))); + + buffer.Initialize(); + } + } + + //clean up resources + clientse.stream.Close(); + clientse.handle.Close(); + } + + public void SendMessage(string message, Client client) + { + var encoder = new ASCIIEncoding(); + var messageBuffer = encoder.GetBytes(message); + + if (client.stream.CanWrite) + { + client.stream.Write(messageBuffer, 0, messageBuffer.Length); + client.stream.Flush(); + } + } + + public void StopServer() + { + //clean up resources + + DisconnectNamedPipe(clientHandle); + + + listenThread.Abort(); + } + + private void OnPipeDataReceived(PipeDataReceivedEventArgs e) + { + PipeDataReceived?.Invoke(this, e); + } + + public class Client + { + public SafeFileHandle handle; + public FileStream stream; + } + } + + public delegate void PipeDataReceivedEventHandler( + object sender, PipeDataReceivedEventArgs pipeDataReceivedEventArgs); + + public class PipeDataReceivedEventArgs + { + public PipeDataReceivedEventArgs(string data) + { + Data = data; + } + + public string Data { get; set; } + } + + +} \ No newline at end of file diff --git a/Artemis/Artemis/Utilities/LogitechDll/PipeServer.cs b/Artemis/Artemis/Utilities/LogitechDll/PipeServer.cs new file mode 100644 index 000000000..bb0ac497e --- /dev/null +++ b/Artemis/Artemis/Utilities/LogitechDll/PipeServer.cs @@ -0,0 +1,132 @@ +using System; +using System.Diagnostics; +using System.IO.Pipes; +using System.Security.AccessControl; +using System.Security.Principal; +using System.Text; +using System.Threading.Tasks; + +namespace Artemis.Utilities.LogitechDll +{ + // Delegate for passing received message back to caller + public delegate void DelegateMessage(string reply); + + public class PipeServer + { + private string _pipeName; + + public bool Running { get; set; } + public event DelegateMessage PipeMessage; + + public void Start(string pipeName) + { + Running = true; + _pipeName = pipeName; + var task = new Task(PipeLoop); + task.Start(); + } + + public void Stop() + { + Running = false; + } + + private void PipeLoop() + { + try + { + var security = new PipeSecurity(); + var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null); + security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, + AccessControlType.Allow)); + + while (Running) + { + var namedPipeServerStream = new NamedPipeServerStream(_pipeName, PipeDirection.In, 100, + PipeTransmissionMode.Byte, PipeOptions.None, 100, 100, security); + + namedPipeServerStream.WaitForConnection(); + var buffer = new byte[100]; + namedPipeServerStream.Read(buffer, 0, 100); + namedPipeServerStream.Close(); + + var task = new Task(() => HandleMessage(buffer)); + task.Start(); + } + } + catch + { + // ignored + } + } + + private void HandleMessage(byte[] buffer) + { + var request = Encoding.ASCII.GetString(buffer); + PipeMessage?.Invoke(request); + } + + public void Listen(string pipeName) + { + try + { + var security = new PipeSecurity(); + var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null); + security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, AccessControlType.Allow)); + + // Set to class level var so we can re-use in the async callback method + _pipeName = pipeName; + // Create the new async pipe + var pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.In, 100, PipeTransmissionMode.Byte, + PipeOptions.Asynchronous, 100, 100, security); + + // Wait for a connection + pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer); + } + catch (Exception oEx) + { + Debug.WriteLine(oEx.Message); + } + } + + private void WaitForConnectionCallBack(IAsyncResult iar) + { + try + { + // Get the pipe + var pipeServer = (NamedPipeServerStream) iar.AsyncState; + // End waiting for the connection + pipeServer.EndWaitForConnection(iar); + + var buffer = new byte[255]; + + // Read the incoming message + pipeServer.Read(buffer, 0, 255); + + // Convert byte buffer to string + var stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length); + Debug.WriteLine(stringData + Environment.NewLine); + + // Pass message back to calling form + PipeMessage?.Invoke(stringData); + + // Kill original sever and create new wait server + pipeServer.Close(); + + var security = new PipeSecurity(); + var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null); + security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, AccessControlType.Allow)); + + pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In, 100, PipeTransmissionMode.Byte, + PipeOptions.Asynchronous, 100, 100, security); + + // Recursively wait for the connection again and again.... + pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer); + } + catch + { + // ignored + } + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/packages.config b/Artemis/Artemis/packages.config index d5231ab31..0b67a3431 100644 --- a/Artemis/Artemis/packages.config +++ b/Artemis/Artemis/packages.config @@ -12,7 +12,6 @@ -