hawkeye camera support(not tested)
This commit is contained in:
22
framework/Inspectron.HawkEye/Protocol/CameraSettings.cs
Normal file
22
framework/Inspectron.HawkEye/Protocol/CameraSettings.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Inspectron.HawkEye.Protocol
|
||||
{
|
||||
public class CameraSettings
|
||||
{
|
||||
public ImageSettings ImageSettings { get; set; }
|
||||
public int LightPwm1 { get; set; }
|
||||
public int LightPwm2 { get; set; }
|
||||
public string Name { get; set; }
|
||||
public int OffsetX { get; set; }
|
||||
public int ImageWidth { get; set; }
|
||||
public int RescaleWidth { get; set; }
|
||||
public int MinorCutoff { get; set; }
|
||||
public bool BayerFilter { get; set; }
|
||||
public bool LaserTrigger { get; set; }
|
||||
public int LaserTriggerDelay { get; set; }
|
||||
public bool FlipLines { get; set; }
|
||||
public bool MirrorX { get; set; }
|
||||
public bool TriggerLights { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
|
||||
namespace Inspectron.HawkEye.Protocol.Discovery
|
||||
{
|
||||
public class CameraInfo
|
||||
{
|
||||
public string Mac { get; set; }
|
||||
public IPAddress Address { get; set; }
|
||||
public IPAddress AdapterAddress { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Inspectron.HawkEye.Protocol.Discovery
|
||||
{
|
||||
public class DiscoveryClient
|
||||
{
|
||||
public ReadOnlyCollection<CameraInfo> Discovered => new ReadOnlyCollection<CameraInfo>(_discovered);
|
||||
private readonly int _port;
|
||||
private readonly List<CameraInfo> _discovered = new List<CameraInfo>();
|
||||
|
||||
private readonly object _discoveryLock = new object();
|
||||
|
||||
public DiscoveryClient(int port)
|
||||
{
|
||||
_port = port;
|
||||
}
|
||||
|
||||
public event Action<CameraInfo> CameraFound = delegate { };
|
||||
|
||||
public void Discover()
|
||||
{
|
||||
var allInterfaces = NetworkInterface
|
||||
.GetAllNetworkInterfaces()
|
||||
.Where(nic => nic.OperationalStatus == OperationalStatus.Up);
|
||||
|
||||
|
||||
Parallel.ForEach(allInterfaces, DiscoverOnInterface);
|
||||
//foreach (NetworkInterface i in allInterfaces)
|
||||
//{
|
||||
// DiscoverOnInterface(i);
|
||||
//}
|
||||
}
|
||||
|
||||
private void DiscoverOnInterface(NetworkInterface iface)
|
||||
{
|
||||
var address = iface.GetIPProperties().UnicastAddresses
|
||||
.First(x => x.Address.AddressFamily == AddressFamily.InterNetwork).Address;
|
||||
UdpClient client;
|
||||
lock (_discoveryLock)
|
||||
{
|
||||
client = new UdpClient(new IPEndPoint(address, 0));
|
||||
var requestData = Encoding.ASCII.GetBytes("discovery");
|
||||
client.Client.ReceiveTimeout = 2000;
|
||||
|
||||
var s = client.Client;
|
||||
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
|
||||
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
|
||||
client.EnableBroadcast = true;
|
||||
client.Send(requestData, requestData.Length, new IPEndPoint(IPAddress.Broadcast, _port));
|
||||
client.Send(requestData, requestData.Length, new IPEndPoint(IPAddress.Broadcast, _port));
|
||||
client.Send(requestData, requestData.Length, new IPEndPoint(IPAddress.Broadcast, _port));
|
||||
}
|
||||
|
||||
var serverEp = new IPEndPoint(IPAddress.Any, 0);
|
||||
|
||||
byte[] serverResponseData;
|
||||
try
|
||||
{
|
||||
serverResponseData = client.Receive(ref serverEp);
|
||||
var serverResponse = Encoding.ASCII.GetString(serverResponseData);
|
||||
Console.WriteLine("Recived {0} from {1}", serverResponse, serverEp.Address);
|
||||
var found = new CameraInfo {Mac = serverResponse, Address = serverEp.Address,AdapterAddress = address};
|
||||
lock (_discoveryLock)
|
||||
{
|
||||
if (_discovered.Any(x => x.Mac == found.Mac)) return;
|
||||
}
|
||||
|
||||
CameraFound(found);
|
||||
_discovered.Add(found);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace Inspectron.HawkEye.Protocol.Discovery
|
||||
{
|
||||
public class DiscoveryServer
|
||||
{
|
||||
private UdpClient _server;
|
||||
private byte[] _name;
|
||||
|
||||
public DiscoveryServer(int port,string name=null)
|
||||
{
|
||||
_server = new UdpClient(port);
|
||||
|
||||
if(name==null)
|
||||
{ _name = Encoding.UTF8.GetBytes( NetworkInterface
|
||||
.GetAllNetworkInterfaces()
|
||||
.Where(nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback)
|
||||
.Select(nic => nic.GetPhysicalAddress().ToString())
|
||||
.FirstOrDefault());
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_name = Encoding.UTF8.GetBytes(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Thread th = new Thread(DiscoveryLoop);
|
||||
th.Start();
|
||||
}
|
||||
private void DiscoveryLoop()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var clientEp = new IPEndPoint(IPAddress.Any, 0);
|
||||
var clientRequestData = _server.Receive(ref clientEp);
|
||||
var clientRequest = Encoding.ASCII.GetString(clientRequestData);
|
||||
|
||||
Console.WriteLine("Recived {0} from {1}, sending response", clientRequest, clientEp.Address.ToString());
|
||||
_server.Send(_name, _name.Length, clientEp);
|
||||
_server.Send(_name, _name.Length, clientEp);
|
||||
_server.Send(_name, _name.Length, clientEp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
framework/Inspectron.HawkEye/Protocol/ECommand.cs
Normal file
13
framework/Inspectron.HawkEye/Protocol/ECommand.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Inspectron.HawkEye.Protocol
|
||||
{
|
||||
public enum ECommand
|
||||
{
|
||||
Connect,
|
||||
Trigger, StartContinuous, StopContinuous,
|
||||
Settings,SaveSettings,
|
||||
OK,
|
||||
SaveCalibration,
|
||||
GetCalibration,
|
||||
NotOK
|
||||
}
|
||||
}
|
||||
9
framework/Inspectron.HawkEye/Protocol/EData.cs
Normal file
9
framework/Inspectron.HawkEye/Protocol/EData.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Inspectron.HawkEye.Protocol
|
||||
{
|
||||
public enum EData
|
||||
{
|
||||
Image,
|
||||
|
||||
OK
|
||||
}
|
||||
}
|
||||
114
framework/Inspectron.HawkEye/Protocol/ImageClient.cs
Normal file
114
framework/Inspectron.HawkEye/Protocol/ImageClient.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Inspectron.HawkEye.UDPB;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Inspectron.HawkEye.Protocol
|
||||
{
|
||||
public class ImageClient : IDisposable
|
||||
{
|
||||
private static readonly object connectionLock = new object();
|
||||
private readonly IPEndPoint _endpoint;
|
||||
private readonly IPAddress _adapter;
|
||||
|
||||
private readonly UDPBSocket _imageSocket = new UDPBSocket();
|
||||
private readonly UDPBSocket _commandSocket = new UDPBSocket();
|
||||
private bool _isConnected = true;
|
||||
|
||||
public ImageClient(IPEndPoint endpoint,IPAddress adapter)
|
||||
{
|
||||
_endpoint = endpoint;
|
||||
_adapter = adapter;
|
||||
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_isConnected = false;
|
||||
_commandSocket.Dispose();
|
||||
}
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
lock (connectionLock)
|
||||
{
|
||||
_commandSocket.Connect(_endpoint,_adapter);
|
||||
var port = UDPBSocket.FindFreePort(_adapter);
|
||||
var bytesPort = BitConverter.GetBytes(port);
|
||||
_commandSocket.SendData(new[]
|
||||
{(byte) ECommand.Connect, bytesPort[0], bytesPort[1], bytesPort[2], bytesPort[3]});
|
||||
var settingsData0 = _commandSocket.Receive();
|
||||
var b = new byte[settingsData0.Length - 1];
|
||||
Array.Copy(settingsData0, 1, b, 0, b.Length);
|
||||
var settingsString = Encoding.UTF8.GetString(b);
|
||||
SettingsReceived(JsonConvert.DeserializeObject<CameraSettings>(settingsString));
|
||||
_imageSocket.Listen(_adapter,port);
|
||||
var th = new Thread(ReceiveLoop);
|
||||
th.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<byte[]> ImageReceived = delegate { };
|
||||
public event Action<CameraSettings> SettingsReceived = delegate { };
|
||||
|
||||
|
||||
public void Trigger()
|
||||
{
|
||||
_commandSocket.SendData(new[] {(byte) ECommand.Trigger});
|
||||
}
|
||||
|
||||
public void ApplySettings(CameraSettings cameraSettings)
|
||||
{
|
||||
var data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(cameraSettings));
|
||||
var databytes = new byte[1000];
|
||||
databytes[0] = (byte) ECommand.Settings;
|
||||
Array.Copy(data, 0, databytes, 1, data.Length);
|
||||
|
||||
_commandSocket.SendData(databytes);
|
||||
}
|
||||
|
||||
public void StartContinuous()
|
||||
{
|
||||
_commandSocket.SendData(new[] {(byte) ECommand.StartContinuous});
|
||||
}
|
||||
|
||||
public void StopContinuous()
|
||||
{
|
||||
_commandSocket.SendData(new[] {(byte) ECommand.StopContinuous});
|
||||
}
|
||||
|
||||
public void SaveSettingsOnCamera()
|
||||
{
|
||||
_commandSocket.SendData(new[] {(byte) ECommand.SaveSettings});
|
||||
}
|
||||
|
||||
|
||||
private void ReceiveLoop()
|
||||
{
|
||||
while (_isConnected)
|
||||
{
|
||||
var data = _imageSocket.Receive();
|
||||
|
||||
Process(data);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void Process(byte[] data)
|
||||
{
|
||||
switch ((EData) data[0])
|
||||
{
|
||||
case EData.Image:
|
||||
var b = new byte[data.Length - 1];
|
||||
Array.Copy(data, 1, b, 0, b.Length);
|
||||
ImageReceived(data);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
192
framework/Inspectron.HawkEye/Protocol/ImageClientTCP.cs
Normal file
192
framework/Inspectron.HawkEye/Protocol/ImageClientTCP.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Inspectron.HawkEye.UDPB;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Inspectron.HawkEye.Protocol
|
||||
{
|
||||
public class ImageClientTCP : IDisposable
|
||||
{
|
||||
private static readonly object connectionLock = new object();
|
||||
private readonly IPEndPoint _endpoint;
|
||||
private readonly IPAddress _adapter;
|
||||
|
||||
private TcpListener _imageSocket;
|
||||
private TcpClient _commandSocket;
|
||||
private bool _isConnected = true;
|
||||
|
||||
public ImageClientTCP(IPEndPoint endpoint,IPAddress adapter)
|
||||
{
|
||||
_endpoint = endpoint;
|
||||
_adapter = adapter;
|
||||
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_isConnected = false;
|
||||
_commandSocket.Dispose();
|
||||
}
|
||||
byte[] _commandBuffer = new byte[1500];
|
||||
private TcpClient _lastClient;
|
||||
public bool SupportsCalibration { get; set; }
|
||||
public void Connect()
|
||||
{
|
||||
lock (connectionLock)
|
||||
{
|
||||
_commandSocket=new TcpClient(new IPEndPoint(_adapter, 0));
|
||||
Console.WriteLine($"Bind on {_adapter?.ToString()}");
|
||||
|
||||
_commandSocket.Connect(_endpoint);
|
||||
var port = UDPBSocket.FindFreePort(_adapter);
|
||||
Console.WriteLine("Connected");
|
||||
|
||||
_imageSocket = new TcpListener(_adapter, port);
|
||||
_imageSocket.Start();
|
||||
|
||||
Console.WriteLine("TCP started");
|
||||
|
||||
var bytesPort = BitConverter.GetBytes(port);
|
||||
_commandSocket.Client.SendData(new[]
|
||||
{(byte) ECommand.Connect, bytesPort[0], bytesPort[1], bytesPort[2], bytesPort[3]});
|
||||
|
||||
var receivedLen = _commandSocket.Client.Receive(_commandBuffer);
|
||||
Console.WriteLine("received answer length:"+receivedLen);
|
||||
var b = new byte[receivedLen - 1];
|
||||
Array.Copy(_commandBuffer, 1, b, 0, b.Length);
|
||||
var settingsString = Encoding.UTF8.GetString(b);
|
||||
SettingsReceived(JsonConvert.DeserializeObject<CameraSettings>(settingsString));
|
||||
if (SupportsCalibration)
|
||||
{
|
||||
|
||||
_commandSocket.Client.SendData(new[] {(byte) ECommand.GetCalibration});
|
||||
receivedLen = _commandSocket.Client.Receive(_commandBuffer);
|
||||
if (_commandBuffer[0] == (byte) ECommand.OK)
|
||||
{
|
||||
Console.WriteLine($"calibration received {receivedLen} bytes");
|
||||
var c = new byte[receivedLen - 1];
|
||||
Array.Copy(_commandBuffer, 1, c, 0, c.Length);
|
||||
var calibrationString = Encoding.UTF8.GetString(c);
|
||||
CalibrationReceived(JsonConvert.DeserializeObject<List<Dictionary<double,double>>>(calibrationString));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("no calibration received");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var th = new Thread(ReceiveLoop);
|
||||
th.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<byte[]> ImageReceived = delegate { };
|
||||
public event Action<CameraSettings> SettingsReceived = delegate { };
|
||||
public event Action<List<Dictionary<double,double>>> CalibrationReceived = delegate { };
|
||||
|
||||
|
||||
public void Trigger()
|
||||
{
|
||||
_commandSocket.Client.SendData(new[] {(byte) ECommand.Trigger});
|
||||
}
|
||||
|
||||
public void ApplySettings(CameraSettings cameraSettings)
|
||||
{
|
||||
var data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(cameraSettings));
|
||||
var databytes = new byte[1000];
|
||||
databytes[0] = (byte) ECommand.Settings;
|
||||
Array.Copy(data, 0, databytes, 1, data.Length);
|
||||
|
||||
_commandSocket.Client.SendData(databytes);
|
||||
byte[] ok = new byte[1];
|
||||
_commandSocket.Client.Receive(ok);
|
||||
}
|
||||
|
||||
public void StartContinuous()
|
||||
{
|
||||
_commandSocket.Client.SendData(new[] {(byte) ECommand.StartContinuous});
|
||||
}
|
||||
|
||||
public void StopContinuous()
|
||||
{
|
||||
_commandSocket.Client.SendData(new[] {(byte) ECommand.StopContinuous});
|
||||
}
|
||||
|
||||
public void SaveSettingsOnCamera()
|
||||
{
|
||||
_commandSocket.Client.SendData(new[] {(byte) ECommand.SaveSettings});
|
||||
}
|
||||
|
||||
private byte[] _imageBuffer = new byte[10*1024*1024];
|
||||
private void ReceiveLoop()
|
||||
{
|
||||
while (_isConnected)
|
||||
{
|
||||
_lastClient = _imageSocket.AcceptTcpClient();
|
||||
while (true)
|
||||
{
|
||||
int received=0;
|
||||
|
||||
try
|
||||
{
|
||||
_lastClient.Client.Receive(_imageBuffer, 0, 1,
|
||||
SocketFlags.None);
|
||||
Process(_imageBuffer);
|
||||
}
|
||||
catch
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveCalibration(List<Dictionary<double,double>> calibration)
|
||||
{
|
||||
var data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(calibration));
|
||||
var databytes = new byte[1500];
|
||||
databytes[0] = (byte)ECommand.SaveCalibration;
|
||||
Array.Copy(data, 0, databytes, 1, data.Length);
|
||||
|
||||
_commandSocket.Client.SendData(databytes);
|
||||
byte[] ok = new byte[1];
|
||||
_commandSocket.Client.Receive(ok);
|
||||
}
|
||||
|
||||
private void Process(byte[] data)
|
||||
{
|
||||
switch ((EData) data[0])
|
||||
{
|
||||
case EData.Image:
|
||||
_lastClient.Client.Receive(_imageBuffer, 1, 4,
|
||||
SocketFlags.None);
|
||||
var imageSize = BitConverter.ToInt32(_imageBuffer,1);
|
||||
var received = 0;
|
||||
do
|
||||
{
|
||||
received += _lastClient.Client.Receive(_imageBuffer, 5+ received, imageSize- received,
|
||||
SocketFlags.None);
|
||||
} while (received < imageSize);
|
||||
|
||||
var b = new byte[imageSize];
|
||||
Array.Copy(data, 5, b, 0, b.Length);
|
||||
ImageReceived(b);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
164
framework/Inspectron.HawkEye/Protocol/ImageServer.cs
Normal file
164
framework/Inspectron.HawkEye/Protocol/ImageServer.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
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 ImageServer
|
||||
{
|
||||
private readonly IImageSource _imageSource;
|
||||
private readonly ICameraControl _cameraControl;
|
||||
private readonly ILightControl _lightControl;
|
||||
private readonly UDPBSocket _commandSocket = new UDPBSocket();
|
||||
private readonly UDPBSocket _imageSocket = new UDPBSocket();
|
||||
|
||||
private bool _autoTrigger;
|
||||
private bool _applySettings;
|
||||
private CameraSettings _imageSettingsToApply=new CameraSettings(){ImageSettings = new ImageSettings()};
|
||||
|
||||
public ImageServer(IImageSource imageSource, ICameraControl cameraControl, ILightControl lightControl)
|
||||
{
|
||||
_imageSource = imageSource;
|
||||
_cameraControl = cameraControl;
|
||||
_lightControl = lightControl;
|
||||
_imageSocket.LossSimulation = 0;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_commandSocket.Listen(IPAddress.Any, 27001);
|
||||
var th = new Thread(ReceiveLoop);
|
||||
th.Start();
|
||||
if (File.Exists("settings.json"))
|
||||
{
|
||||
var settings = JsonConvert.DeserializeObject<CameraSettings>(File.ReadAllText("settings.json"));
|
||||
_imageSettingsToApply = settings;
|
||||
ApplyParameters(settings);
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyParameters(CameraSettings cameraSettings)
|
||||
{
|
||||
_cameraControl.SetParameters(cameraSettings);
|
||||
|
||||
_lightControl.SetLight(cameraSettings.LightPwm1, cameraSettings.LightPwm2);
|
||||
}
|
||||
|
||||
private void SaveSettingsLocally()
|
||||
{
|
||||
File.WriteAllText("settings.json", JsonConvert.SerializeObject(_imageSettingsToApply));
|
||||
}
|
||||
|
||||
private void ReceiveLoop()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
|
||||
var data = _commandSocket.Receive();
|
||||
try
|
||||
{
|
||||
ProcessCommand(data);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TriggerLoop()
|
||||
{
|
||||
while (_autoTrigger)
|
||||
{
|
||||
|
||||
if (_applySettings)
|
||||
{
|
||||
ApplyParameters(_imageSettingsToApply);
|
||||
_applySettings = false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SendImage();
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
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.Connect(new IPEndPoint((_commandSocket.LastConnection as IPEndPoint).Address, BitConverter.ToInt32(port,0)),null);
|
||||
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;
|
||||
_commandSocket.SendData(databytes);
|
||||
}
|
||||
break;
|
||||
case ECommand.Trigger:
|
||||
{
|
||||
Task.Run(() => { SendImage(); });
|
||||
}
|
||||
break;
|
||||
case ECommand.StartContinuous:
|
||||
{
|
||||
_autoTrigger = true;
|
||||
var th = new Thread(TriggerLoop);
|
||||
th.Start();
|
||||
}
|
||||
break;
|
||||
case ECommand.StopContinuous:
|
||||
{
|
||||
_autoTrigger = false;
|
||||
}
|
||||
break;
|
||||
case ECommand.Settings:
|
||||
{
|
||||
var databytes = new byte[999];
|
||||
Array.Copy(data, 1, databytes, 0, 999);
|
||||
var settings = JsonConvert.DeserializeObject<CameraSettings>(Encoding.UTF8.GetString(databytes));
|
||||
_imageSettingsToApply = settings;
|
||||
if (_autoTrigger)
|
||||
_applySettings = true;
|
||||
else
|
||||
ApplyParameters(_imageSettingsToApply);
|
||||
}
|
||||
break;
|
||||
case ECommand.SaveSettings:
|
||||
{
|
||||
SaveSettingsLocally();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
private void SendImage()
|
||||
{
|
||||
var image = _imageSource.GetImage();
|
||||
var b = new byte[image.Length + 1];
|
||||
b[0] = (byte) EData.Image;
|
||||
Array.Copy(image, 0, b, 1, image.Length);
|
||||
|
||||
_imageSocket.SendData(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
269
framework/Inspectron.HawkEye/Protocol/ImageServerTCP.cs
Normal file
269
framework/Inspectron.HawkEye/Protocol/ImageServerTCP.cs
Normal file
@@ -0,0 +1,269 @@
|
||||
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<CameraSettings>(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<CameraSettings>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
framework/Inspectron.HawkEye/Protocol/ImageSettings.cs
Normal file
17
framework/Inspectron.HawkEye/Protocol/ImageSettings.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Inspectron.HawkEye.Protocol
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 0)]
|
||||
public struct ImageSettings
|
||||
{
|
||||
public int Shutter { get; set; }
|
||||
public int Gain { get; set; }
|
||||
public int SensorWidth { get; set; }
|
||||
public int Lines { get; set; }
|
||||
public int CaptureBuffer { get; set; }
|
||||
public int UseExternalTrigger { get; set; }
|
||||
public int Divider { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Inspectron.HawkEye.Protocol.Interfaces
|
||||
{
|
||||
public interface ICameraControl
|
||||
{
|
||||
|
||||
void SetParameters(CameraSettings imageSettings);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Inspectron.HawkEye.Protocol.Interfaces
|
||||
{
|
||||
public interface IImageSource
|
||||
{
|
||||
byte[] GetImage();
|
||||
void CancelTrigger();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Inspectron.HawkEye.Protocol.Interfaces
|
||||
{
|
||||
public interface ILightControl
|
||||
{
|
||||
void SetLight(int pwm1, int pwm2);
|
||||
}
|
||||
}
|
||||
23
framework/Inspectron.HawkEye/Protocol/SocketExtensions.cs
Normal file
23
framework/Inspectron.HawkEye/Protocol/SocketExtensions.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using Inspectron.HawkEye.RTSP;
|
||||
|
||||
namespace Inspectron.HawkEye.Protocol
|
||||
{
|
||||
public static class SocketExtensions
|
||||
{
|
||||
public static void Listen(this Socket self,IPAddress adapterAddress,int port)
|
||||
{
|
||||
self.Bind(new IPEndPoint(adapterAddress,port));
|
||||
}
|
||||
|
||||
public static void SendData(this Socket self, byte[] data)
|
||||
{
|
||||
Console.WriteLine("send data");
|
||||
|
||||
|
||||
self.Send(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user