Files
2025-08-19 12:45:50 +02:00

192 lines
6.6 KiB
C#

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();
}
}
}
}