using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using Inspectron.HawkEye.Protocol.Interfaces; using Inspectron.HawkEye.UDPB; using Newtonsoft.Json; namespace Inspectron.HawkEye.Protocol { public class ImageServerTCP { private readonly IImageSource _imageSource; private readonly ICameraControl _cameraControl; private readonly ILightControl _lightControl; private TcpListener _commandSocket; private TcpClient _imageSocket; private bool _autoTrigger; private bool _applySettings; private CameraSettings _imageSettingsToApply=new CameraSettings(){ImageSettings = new ImageSettings()}; private TcpClient _lastClient; public ImageServerTCP(IImageSource imageSource, ICameraControl cameraControl, ILightControl lightControl) { _imageSource = imageSource; _cameraControl = cameraControl; _lightControl = lightControl; } public void Start() { _commandSocket = new TcpListener(IPAddress.Any, 27001); _commandSocket.Start(); Console.WriteLine("listen tcp"); var th = new Thread(ReceiveLoop); th.Start(); if (File.Exists("settings.json")) { var settings = JsonConvert.DeserializeObject(File.ReadAllText("settings.json")); _imageSettingsToApply = settings; ApplyParameters(settings); } } public void ApplyParameters(CameraSettings cameraSettings, bool setLight = false) { Console.WriteLine("Setting parameters:"+JsonConvert.SerializeObject(cameraSettings,Formatting.Indented)); _cameraControl.SetParameters(cameraSettings); if(setLight&&!cameraSettings.TriggerLights) _lightControl.SetLight(cameraSettings.LightPwm1, cameraSettings.LightPwm2); else _lightControl.SetLight(0, 0); } private void SaveSettingsLocally() { File.WriteAllText("settings.json", JsonConvert.SerializeObject(_imageSettingsToApply,Formatting.Indented)); } byte[] _commandBuffer = new byte[1500]; private Task _lastTriggerTask=Task.CompletedTask; private void ReceiveLoop() { while (true) { _lastClient=_commandSocket.AcceptTcpClient(); do { try { _lastClient.GetStream().Read(_commandBuffer, 0, 1500); } catch { break; } ProcessCommand(_commandBuffer); } while (_lastClient.Connected); CancelTrigger(); _lightControl.SetLight(0, 0); } } private void TriggerLoop() { while (_autoTrigger) { if (_applySettings) { ApplyParameters(_imageSettingsToApply,true); _applySettings = false; } try { SendImage(); } catch(Exception e) { Console.WriteLine(e.ToString()); return; } } } private void ProcessCommand(byte[] data) { Console.WriteLine(((ECommand) data[0]).ToString()); switch ((ECommand) data[0]) { case ECommand.Connect: { var port = new byte[4]; Array.Copy(data, 1, port, 0, 4); _imageSocket=new TcpClient(); _imageSocket.Connect(new IPEndPoint((_lastClient.Client.RemoteEndPoint as IPEndPoint).Address, BitConverter.ToInt32(port,0))); var databytes = new byte[1000]; var settings = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(_imageSettingsToApply)); Array.Copy(settings, 0, databytes, 1, settings.Length); databytes[0] = (byte) ECommand.Settings; _lastClient.Client.SendData(databytes); Console.WriteLine("data sent"); _lightControl.SetLight(_imageSettingsToApply.LightPwm1, _imageSettingsToApply.LightPwm2); _autoTrigger = false; } break; case ECommand.GetCalibration: { var databytes = new byte[1500]; if (File.Exists("calibration.calib")) { databytes[0] = (byte)ECommand.OK; Array.Copy(File.ReadAllBytes("calibration.calib"),0,databytes,1,1500-1); _lastClient.Client.SendData(databytes); } else { databytes[0] = (byte)ECommand.NotOK; _lastClient.Client.SendData(databytes); } } break; case ECommand.Trigger: { CancelTrigger(); _lastTriggerTask=Task.Run(() => { try { SendImage(); } catch (Exception e) { Console.WriteLine(e.ToString()); } }); } break; case ECommand.StartContinuous: { _autoTrigger = true; var th = new Thread(TriggerLoop); th.Start(); } break; case ECommand.StopContinuous: { _autoTrigger = false; } break; case ECommand.Settings: { CancelTrigger(); var databytes = new byte[999]; Array.Copy(data, 1, databytes, 0, 999); var settings = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(databytes)); _imageSettingsToApply = settings; if (_autoTrigger) _applySettings = true; else ApplyParameters(_imageSettingsToApply,true); _lastClient.Client.Send(new []{(byte)EData.OK}); } break; case ECommand.SaveCalibration: { var databytes = new byte[1500 - 1]; Array.Copy(data, 1, databytes, 0, 1500 - 1); File.WriteAllBytes("calibration.calib",databytes); _lastClient.Client.Send(new[] { (byte)EData.OK }); } break; case ECommand.SaveSettings: { SaveSettingsLocally(); } break; default: throw new ArgumentOutOfRangeException(); } } private void CancelTrigger() { _imageSource.CancelTrigger(); _lastTriggerTask.Wait(); } private void SendImage() { if (_imageSettingsToApply.TriggerLights) { _lightControl.SetLight(_imageSettingsToApply.LightPwm1, _imageSettingsToApply.LightPwm2); } var image = _imageSource.GetImage(); if (image.Length == 0) return; if (_imageSettingsToApply.TriggerLights) { _lightControl.SetLight(0, 0); } var b = EncodeImage(image); _imageSocket.Client.SendData(b); } private static byte[] EncodeImage(byte[] image) { var b = new byte[image.Length + 5]; b[0] = (byte) EData.Image; var byteSize = BitConverter.GetBytes(image.Length); Array.Copy(byteSize, 0, b, 1, 4); Array.Copy(image, 0, b, 5, image.Length); return b; } private static byte[] EncodeChanneledImage(byte[] image,byte channels) { var b = new byte[image.Length + 6]; b[0] = (byte)EData.Image; b[1] = channels; var byteSize = BitConverter.GetBytes(image.Length); Array.Copy(byteSize, 0, b, 2, 4); Array.Copy(image, 0, b, 6, image.Length); return b; } } }