808 lines
25 KiB
C#
808 lines
25 KiB
C#
///
|
|
/// Copyright (c) 2017 Sensus Metering Systems
|
|
///
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Timers;
|
|
using log4net;
|
|
using Renci.SshNet;
|
|
using Config.Entities;
|
|
using TBF.BenchControl.Network.Telnet;
|
|
using TBF.Resources;
|
|
|
|
namespace TBF.BenchControl.Network.Camera.CLP1611
|
|
{
|
|
/// <summary>
|
|
/// This class implements: (1) Camera device, (2) Measurement operation
|
|
/// </summary>
|
|
public class Camera : ComponentBase, GenericDevices.ICamera, Generic.IDevice, IOperation
|
|
{
|
|
private static readonly ILog log = LogManager.GetLogger(typeof(Camera));
|
|
public override string ToString()
|
|
{
|
|
return string.Format("{0}: Name={1}, Addr={2}, IP={3}, s/n={4}, SD={5}",
|
|
this.GetType().Namespace.Substring(17),
|
|
CameraCfg.Name,
|
|
CameraCfg.HardwareAddress,
|
|
ipAddress == null ? "not detected" : ipAddress.ToString(),
|
|
string.IsNullOrEmpty(cpuSerialNr) ? "not detected" : cpuSerialNr,
|
|
string.IsNullOrEmpty(sdCardVer) ? "not detected" : sdCardVer);
|
|
}
|
|
|
|
|
|
const string ClpUserName = "tbf";
|
|
const string ClpPassword = "C1ern4V0d4";
|
|
|
|
|
|
private static Object fileUploadLock = new Object();
|
|
|
|
|
|
///
|
|
/// Properties
|
|
///
|
|
public readonly CameraCfg CameraCfg;
|
|
public readonly GenericDevices.INetworkAdapter NetAdapter;
|
|
|
|
public IPAddress IPAddress { get { return ipAddress; } }
|
|
IPAddress ipAddress;
|
|
|
|
public string CpuHardware { get { return cpuHardware; } }
|
|
string cpuHardware;
|
|
|
|
public string CpuRevision { get { return cpuRevision; } }
|
|
string cpuRevision;
|
|
|
|
public string CpuSerialNr { get { return cpuSerialNr; } }
|
|
string cpuSerialNr;
|
|
|
|
public string SDCardVer { get { return sdCardVer; } }
|
|
string sdCardVer;
|
|
|
|
public bool Running { get { return running; } }
|
|
bool running;
|
|
|
|
public int CameraIdx { get { return cameraIdx; } }
|
|
int cameraIdx;
|
|
///
|
|
static int nextCameraIdx = 0;
|
|
static int GetCameraIdx() { return nextCameraIdx++; } /// Used in Initialize()
|
|
public static new void ResetStaticProperties() { nextCameraIdx = 0; }
|
|
|
|
///
|
|
/// Telnet support
|
|
///
|
|
const string TelnetPrompt = "$ ";
|
|
const bool TelnetSkipFirstLine = true;
|
|
public Telnet.TelnetClient Telnet;
|
|
private TerminalDlg terminalDlg;
|
|
string sha1sumResponse;
|
|
bool sha1sumResponseProcessed;
|
|
|
|
///
|
|
/// scp support
|
|
///
|
|
Thread scpThread;
|
|
PasswordConnectionInfo connectionInfo;
|
|
bool scpConnected;
|
|
bool stopScpThreadFlag;
|
|
string scpRemoteFileName; /// Camera file name
|
|
string scpLocalFileName; /// Local PC file name
|
|
enum ScpCommand
|
|
{
|
|
None,
|
|
Get,
|
|
Put,
|
|
}
|
|
ScpCommand scpCommand;
|
|
|
|
|
|
const int UdpPortBase = 20000; /// Port base for all UDP protocols
|
|
|
|
///
|
|
/// MJpeg RTP protocol support
|
|
///
|
|
int rtpUdpLocalPort;
|
|
UdpClient rtpUdpClient;
|
|
Thread rtpListenerThread;
|
|
static bool stopRtpListenerFlag;
|
|
|
|
///
|
|
/// RTCP protocol (reserved)
|
|
///
|
|
int rtcpUdpLocalPort;
|
|
|
|
///
|
|
/// Measurement results protocol
|
|
///
|
|
int msrmntUdpLocalPort;
|
|
UdpClient msrmntUdpClient; /// If != null msrmntListenerThread
|
|
Thread msrmntListenerThread;
|
|
static bool stopMsrmntListenerFlag;
|
|
|
|
|
|
///
|
|
/// ROI related parameters
|
|
///
|
|
RoisAndResults roisAndResults;
|
|
///
|
|
public void ClearRoiParams() { roisAndResults.ClearRoiParams(); }
|
|
public int RegisterRoi(string roiParams) { return roisAndResults.RegisterRoi(roiParams); }
|
|
public int GetResult(int roiHandle, out long timeMs) { return roisAndResults.GetResult(roiHandle, out timeMs); }
|
|
|
|
|
|
public Camera() {}
|
|
|
|
|
|
public Camera(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
|
: base(cfg)
|
|
{
|
|
CameraCfg = cfg as CameraCfg;
|
|
NetAdapter = TbfComponents.FindComponent(cfg.ParentName, components) as GenericDevices.INetworkAdapter;
|
|
if (NetAdapter == null) throw new ArgumentNullException("no network adapter");
|
|
|
|
Telnet = null;
|
|
terminalDlg = null;
|
|
|
|
roisAndResults = new RoisAndResults(); /// object for measurement results, writes/reads to/from this object are locked
|
|
|
|
running = false;
|
|
}
|
|
|
|
|
|
public void Initialize()
|
|
{
|
|
cameraIdx = GetCameraIdx();
|
|
|
|
if (CameraCfg.DebugLevel == DebugMode.Simulate) return;
|
|
|
|
/// Detect a camera
|
|
bool cameraDetected = DetectCamera(CameraCfg.HardwareAddress % 100, ref ipAddress, true,
|
|
out cpuHardware, out cpuRevision, out cpuSerialNr, out sdCardVer);
|
|
|
|
|
|
if (CameraCfg.DebugLevel == DebugMode.AutoDetect)
|
|
{
|
|
CameraCfg.DebugLevel = cameraDetected ? DebugMode.DetectedOn : DebugMode.DetectedOff;
|
|
}
|
|
else if (!cameraDetected)
|
|
{
|
|
throw new Exception(string.Format("{0}={1}", Strings.Address, CameraCfg.HardwareAddress));
|
|
}
|
|
|
|
if (cameraDetected)
|
|
{
|
|
UiBridge.Bridge.OnCameraInfo(this.cameraIdx, string.Format("{0} ver.{1} {2} s/n {3}", Name, sdCardVer, ipAddress, CameraCfg.HardwareAddress));
|
|
|
|
rtpUdpLocalPort = UdpPortBase + 4 * cameraIdx;
|
|
rtcpUdpLocalPort = UdpPortBase + 4 * cameraIdx + 1;
|
|
msrmntUdpLocalPort = UdpPortBase + 4 * cameraIdx + 2;
|
|
|
|
StartRtpListener(NetAdapter.IPAddress, rtpUdpLocalPort);
|
|
StartMsrmntListener(NetAdapter.IPAddress, msrmntUdpLocalPort);
|
|
|
|
connectionInfo = new PasswordConnectionInfo(IPAddress.ToString(), ClpUserName, ClpPassword);
|
|
|
|
/// Open telnet clint and start the log-in process
|
|
Telnet = new Telnet.TelnetClient(this, CameraCfg.Name, ClpUserName, ClpPassword, TelnetPrompt, TelnetSkipFirstLine, CameraCfg.DisplayTerminal);
|
|
|
|
Telnet.promptReceivedHandler += delegate(object sndr, PromptReceivedEventArgs a)
|
|
{
|
|
OnPromptReceived(sndr, a);
|
|
};
|
|
|
|
if (CameraCfg.DisplayTerminal)
|
|
{
|
|
terminalDlg = new TerminalDlg(CameraCfg.Name, Telnet);
|
|
terminalDlg.Show();
|
|
}
|
|
|
|
Telnet.Enqueue(new Telnet.Command(Network.Telnet.CmdAction.CONNECT, ipAddress.ToString(), 10, 30));
|
|
Telnet.Enqueue(new Telnet.Command(Network.Telnet.CmdAction.CLEAR_RESPONSE));
|
|
Telnet.Enqueue(new Telnet.Command(Network.Telnet.CmdAction.SEND_COMMAND, "sha1sum clp/*"));
|
|
|
|
log.FatalFormat("'{0}' with address {1} detected, IP = {2}, SD = {3}", Name, CameraCfg.HardwareAddress, ipAddress, sdCardVer);
|
|
}
|
|
else
|
|
{
|
|
UiBridge.Bridge.OnCameraInfo(this.cameraIdx, string.Format("{0} s/n {1} was not detected", Name, CameraCfg.HardwareAddress));
|
|
log.FatalFormat("'{0}' with address {1} not detected", Name, CameraCfg.HardwareAddress);
|
|
}
|
|
}
|
|
|
|
public void StopDevice()
|
|
{
|
|
running = false;
|
|
|
|
stopScpThreadFlag = true;
|
|
stopRtpListenerFlag = true;
|
|
stopMsrmntListenerFlag = true;
|
|
|
|
if (Telnet != null)
|
|
{
|
|
Telnet.Dispose();
|
|
Telnet = null;
|
|
}
|
|
}
|
|
|
|
public void StopDevice2()
|
|
{
|
|
if (scpThread != null) scpThread.Join(50);
|
|
if (rtpListenerThread != null) rtpListenerThread.Join(50);
|
|
if (msrmntListenerThread != null) msrmntListenerThread.Join(50);
|
|
|
|
if (rtpUdpClient != null)
|
|
{
|
|
rtpUdpClient.Close();
|
|
rtpUdpClient = null;
|
|
}
|
|
|
|
if (msrmntUdpClient != null)
|
|
{
|
|
msrmntUdpClient.Close();
|
|
msrmntUdpClient = null;
|
|
}
|
|
}
|
|
|
|
public void RunDeviceBefore()
|
|
{
|
|
if (sha1sumResponse != null && !sha1sumResponseProcessed)
|
|
{
|
|
scpThread = new Thread(new ThreadStart(ScpWorker));
|
|
scpThread.Start();
|
|
|
|
sha1sumResponseProcessed = true;
|
|
}
|
|
}
|
|
public void RunDeviceAfter() { }
|
|
|
|
|
|
void OnPromptReceived(object sndr, PromptReceivedEventArgs a)
|
|
{
|
|
if (sha1sumResponse == null)
|
|
{
|
|
sha1sumResponse = a.Response;
|
|
}
|
|
}
|
|
|
|
|
|
#region Configuration Change Handling
|
|
|
|
public static void OnCfgChange(object sender, CfgChangeArgs args)
|
|
{
|
|
if (CfgChangeHandler == null) return;
|
|
try { CfgChangeHandler(sender, args); }
|
|
catch (Exception e) { log.Error("CfgChangeHandler(...) failed", e); }
|
|
}
|
|
|
|
public static event EventHandler<CfgChangeArgs> CfgChangeHandler;
|
|
|
|
public override void StartChangeHandler()
|
|
{
|
|
CfgChangeHandler += delegate(object sender, CfgChangeArgs args)
|
|
{
|
|
CameraCfg tmpcfg = args.Cfg as CameraCfg;
|
|
if (tmpcfg != null && tmpcfg.Name.Equals(Name))
|
|
{
|
|
if (args.Command == CfgChangeCmd.CfgChange)
|
|
{
|
|
CameraCfg.TestImagesMode = tmpcfg.TestImagesMode;
|
|
CameraCfg.TestImagesCount = tmpcfg.TestImagesCount;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#endregion Configuration Change Handling
|
|
|
|
|
|
/// <summary>
|
|
/// Detect the camera with specified hardware address (DIP switches).
|
|
/// Optionally set camera date and time.
|
|
/// </summary>
|
|
/// <param name="hwAddress">Hardware address (DIP switches)</param>
|
|
/// <param name="setDateTime">true = Broadcast 'SetDateTime' to all cameras</param>
|
|
/// <param name="ipAddress">Detected IP address</param>
|
|
/// <param name="hardware">Detected hardware</param>
|
|
/// <param name="revision">Detected HW revision</param>
|
|
/// <param name="serial">Detected serial number</param>
|
|
/// <param name="sdCardVer">Detected OS image</param>
|
|
/// <returns>true when camera detected successfully</returns>
|
|
bool DetectCamera(int hwAddress, ref IPAddress ipAddress, bool setDateTime, out string hardware, out string revision, out string serial, out string sdCardVer)
|
|
{
|
|
for (int trials = 1; trials <= 3; trials++)
|
|
{
|
|
UdpClient udpClient = new UdpClient();
|
|
|
|
try
|
|
{
|
|
if (setDateTime)
|
|
{
|
|
SetDateTime(udpClient, DateTime.Now);
|
|
}
|
|
|
|
///
|
|
/// Send a request for camera information
|
|
///
|
|
DateTime detectionStart = DateTime.Now;
|
|
CameraInfoRequest(udpClient, hwAddress);
|
|
|
|
///
|
|
/// Receive a response or timeout
|
|
///
|
|
IAsyncResult asyncRslt = udpClient.BeginReceive(null, null);
|
|
if (asyncRslt.AsyncWaitHandle.WaitOne(500))
|
|
{
|
|
/// Response received within time limit
|
|
IPEndPoint cameraIPEndpoint = new IPEndPoint(IPAddress.Any, 1852);
|
|
byte[] inputBuffer = udpClient.EndReceive(asyncRslt, ref cameraIPEndpoint);
|
|
|
|
double duration_ms = (DateTime.Now - detectionStart).TotalMilliseconds;
|
|
ipAddress = cameraIPEndpoint.Address;
|
|
|
|
udpClient.Close();
|
|
|
|
string response = Encoding.ASCII.GetString(inputBuffer, 0, inputBuffer.Length);
|
|
string[] strArr = response.Split(new char[] { ' ', '=' });
|
|
if (strArr.Length == 10 && strArr[0] == "Address" && strArr[2] == "Hardware" &&
|
|
strArr[4] == "Revision" && strArr[6] == "Serial" && strArr[8] == "Image")
|
|
{
|
|
hardware = strArr[3];
|
|
revision = strArr[5];
|
|
serial = strArr[7];
|
|
sdCardVer = strArr[9];
|
|
}
|
|
else if (strArr.Length == 8 && strArr[0] == "Address" && strArr[2] == "Hardware" &&
|
|
strArr[4] == "Revision" && strArr[6] == "Serial")
|
|
{
|
|
hardware = strArr[3];
|
|
revision = strArr[5];
|
|
serial = strArr[7];
|
|
sdCardVer = string.Empty;
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
|
|
string msg = string.Format("Camera {0} detected in {1} ms: HWAddress={2} IPAddress={3} {4}",
|
|
CameraCfg.Name,
|
|
duration_ms,
|
|
CameraCfg.HardwareAddress,
|
|
ipAddress == null ? "not detected" : ipAddress.ToString(),
|
|
response);
|
|
log.Info(msg);
|
|
Console.WriteLine(msg);
|
|
|
|
return true; /// Camera detected
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
log.ErrorFormat("Camera {0} with HWAddress={1} not detected : {2}", CameraCfg.Name, CameraCfg.HardwareAddress, exc.Message);
|
|
}
|
|
|
|
udpClient.Close();
|
|
}
|
|
|
|
ipAddress = null;
|
|
hardware = null;
|
|
revision = null;
|
|
serial = null;
|
|
sdCardVer = null;
|
|
return false; /// No camera detected
|
|
}
|
|
|
|
void CameraInfoRequest(UdpClient udpClient, int hardwareAddress)
|
|
{
|
|
string strToSend = string.Format("getinfo {0}", hardwareAddress);
|
|
byte[] dataToSend = Encoding.ASCII.GetBytes(strToSend);
|
|
udpClient.Send(dataToSend, dataToSend.Length, new IPEndPoint(NetAdapter.BroadcastAddress, 1852));
|
|
}
|
|
|
|
void SetDateTime(UdpClient udpClient, DateTime dateTime)
|
|
{
|
|
string strToSend = string.Format("setdatetime {0:yyMMddHHmmss}", dateTime);
|
|
byte[] dataToSend = Encoding.ASCII.GetBytes(strToSend);
|
|
udpClient.Send(dataToSend, dataToSend.Length, new IPEndPoint(NetAdapter.BroadcastAddress, 1852));
|
|
}
|
|
|
|
|
|
|
|
void ScpWorker()
|
|
{
|
|
try
|
|
{
|
|
using (var scpClient = new ScpClient(connectionInfo))
|
|
{
|
|
scpClient.Connect();
|
|
|
|
///
|
|
/// Synchronize files in camera /home/tbf/clp directory with the files in "TBF/CameraBinaryFiles" project folder
|
|
///
|
|
using (var sshClient = new SshClient(connectionInfo))
|
|
{
|
|
sshClient.Connect();
|
|
|
|
DirectoryInfo dirInfo = new DirectoryInfo(Path.Combine(System.Windows.Forms.Application.StartupPath, "CameraBinaryFiles"));
|
|
SHA1 sha1calculator = SHA1.Create();
|
|
StringBuilder sha1str = new StringBuilder();
|
|
|
|
foreach (FileInfo fi in dirInfo.GetFiles())
|
|
{
|
|
lock (fileUploadLock)
|
|
{
|
|
FileStream fs = fi.Open(FileMode.Open);
|
|
fs.Position = 0;
|
|
byte[] sha1 = sha1calculator.ComputeHash(fs);
|
|
fs.Close();
|
|
|
|
sha1str.Clear();
|
|
foreach (var b in sha1) sha1str.Append(b.ToString("x2"));
|
|
|
|
if (!sha1sumResponse.Contains(string.Format("{0} clp/{1}", sha1str, fi.Name)))
|
|
{
|
|
/// Copy a file to the camera if SHA1 sum is different of the file is missing
|
|
log.InfoFormat("{0}, IP={1}, Uploading file {2}", Name, IPAddress, fi.Name);
|
|
scpClient.Upload(fi, string.Format("clp/{0}", fi.Name));
|
|
}
|
|
}
|
|
|
|
if (!sha1sumResponse.Contains(fi.Name))
|
|
{
|
|
/// Change file properties if it was a new file
|
|
string command = string.Format("chmod 755 clp/{0}", fi.Name);
|
|
log.InfoFormat("{0}, IP={1}, Executing command '{2}'", Name, IPAddress, command);
|
|
sshClient.CreateCommand(command).Execute();
|
|
|
|
//if (fi.Name.Equals("runmeonce"))
|
|
//{
|
|
// log.InfoFormat("{0}, IP={1}, Executing command 'sudo clp/runmeonce'", Name, IPAddress);
|
|
// sshClient.CreateCommand("sudo clp/runmeonce").Execute();
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
|
|
scpConnected = scpClient.IsConnected;
|
|
running = true;
|
|
|
|
///
|
|
/// Run SCP command loop
|
|
///
|
|
while (scpConnected && !stopScpThreadFlag)
|
|
{
|
|
switch (scpCommand)
|
|
{
|
|
case ScpCommand.Get:
|
|
scpCommand = ScpCommand.None;
|
|
scpClient.Download(scpRemoteFileName, new System.IO.FileInfo(scpLocalFileName));
|
|
break;
|
|
|
|
case ScpCommand.Put:
|
|
scpCommand = ScpCommand.None;
|
|
scpClient.Upload(new System.IO.FileInfo(scpLocalFileName), scpRemoteFileName);
|
|
break;
|
|
|
|
default:
|
|
Thread.Sleep(250);
|
|
break;
|
|
}
|
|
|
|
scpConnected = scpClient.IsConnected;
|
|
}
|
|
|
|
running = false;
|
|
scpClient.Disconnect();
|
|
scpConnected = false;
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
log.ErrorFormat( "Exception in {0} ScpWorker(): {1}", Name, exc.Message);
|
|
if (exc.InnerException != null)
|
|
{
|
|
log.ErrorFormat(" Inner exception: {0}", exc.InnerException.Message);
|
|
}
|
|
|
|
scpConnected = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Download a file from the camera via SCP
|
|
/// </summary>
|
|
/// <param name="srcFileName"></param>
|
|
/// <returns>0 (success), -1 (busy), -2 (no session)</returns>
|
|
public int DownloadFile(string srcFileName, string dstFileName)
|
|
{
|
|
if (!scpConnected) return -2;
|
|
if (scpCommand != ScpCommand.None) return -1;
|
|
|
|
scpRemoteFileName = srcFileName;
|
|
scpLocalFileName = dstFileName;
|
|
scpCommand = ScpCommand.Get;
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Upload a file to the camera via SCP
|
|
/// </summary>
|
|
/// <param name="srcFileName"></param>
|
|
/// <returns>0 (success), -1 (busy), -2 (no session)</returns>
|
|
public int UploadFile(string srcFileName, string dstFileName)
|
|
{
|
|
if (!scpConnected) return -2;
|
|
if (scpCommand != ScpCommand.None) return -1;
|
|
|
|
scpLocalFileName = srcFileName;
|
|
scpRemoteFileName = dstFileName;
|
|
scpCommand = ScpCommand.Put;
|
|
return 0;
|
|
}
|
|
|
|
|
|
private void StartRtpListener(IPAddress localIP, int localPort)
|
|
{
|
|
rtpUdpClient = new UdpClient(new IPEndPoint(localIP, localPort));
|
|
rtpListenerThread = new Thread(new ThreadStart(RtpListener));
|
|
rtpListenerThread.Start();
|
|
}
|
|
|
|
void RtpListener()
|
|
{
|
|
JpegFrame jpegFrame = new JpegFrame();
|
|
bool synced = false;
|
|
|
|
while (!stopRtpListenerFlag)
|
|
{
|
|
try
|
|
{
|
|
IPEndPoint endpoint = null;
|
|
Byte[] data = rtpUdpClient.Receive(ref endpoint);
|
|
|
|
if (data.Length > 20)
|
|
{
|
|
/// Process the packet
|
|
RtpPacket newPacket = new RtpPacket(data);
|
|
if (synced)
|
|
{
|
|
/// Sychronized: process the new packet
|
|
switch (jpegFrame.AddPacket(newPacket))
|
|
{
|
|
case RtpFrame.STATE.Complete:
|
|
UiBridge.Bridge.OnImage(this.cameraIdx, jpegFrame.ToImage());
|
|
jpegFrame.Clear();
|
|
break;
|
|
case RtpFrame.STATE.Error:
|
|
jpegFrame.Clear();
|
|
synced = false;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (newPacket.Mark)
|
|
{
|
|
/// Synchronize when a packet with Mark occurs, process the next packet
|
|
jpegFrame.Clear();
|
|
synced = true;
|
|
}
|
|
else
|
|
{
|
|
/// Stay unsynchronized
|
|
}
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
string msg = string.Format("Exception in MJpeg RTP listener thread: {0}", exc.Message);
|
|
log.Error(msg);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
private void StartMsrmntListener(IPAddress localIP, int localPort)
|
|
{
|
|
msrmntUdpClient = new UdpClient(new IPEndPoint(localIP, localPort));
|
|
msrmntListenerThread = new Thread(new ThreadStart(MsrmntListener));
|
|
msrmntListenerThread.Start();
|
|
}
|
|
|
|
void MsrmntListener()
|
|
{
|
|
StringBuilder toBeProcessed = new StringBuilder();
|
|
int[] angles = new int[RoisAndResults.MaxRegisteredRois];
|
|
|
|
while (!stopMsrmntListenerFlag)
|
|
{
|
|
try
|
|
{
|
|
IPEndPoint endpoint = null;
|
|
Byte[] data = msrmntUdpClient.Receive(ref endpoint);
|
|
|
|
toBeProcessed.Append(Encoding.ASCII.GetString(data, 0, data.Length));
|
|
log.DebugFormat("MeasurementUdpListener() ... toBeProcessed = {0}", toBeProcessed);
|
|
|
|
while (true)
|
|
{
|
|
int from = toBeProcessed.ToString().IndexOf('[');
|
|
if (from < 0) break;
|
|
|
|
int len = toBeProcessed.ToString(from + 1, toBeProcessed.Length - from - 1).IndexOf(']');
|
|
if (len < 0) break;
|
|
|
|
string[] pulsesArr = toBeProcessed.ToString(from + 1, len).Split(new char[] { ';' });
|
|
|
|
bool fmtError = false;
|
|
long timeMs;
|
|
if ((pulsesArr.Length >= 2) &&
|
|
(pulsesArr.Length <= RoisAndResults.MaxRegisteredRois + 1) &&
|
|
long.TryParse(pulsesArr[0], out timeMs))
|
|
{
|
|
for (int i = 1; i < pulsesArr.Length; i++)
|
|
{
|
|
int val;
|
|
if (int.TryParse(pulsesArr[i], out val))
|
|
{
|
|
angles[i - 1] = Math.Abs(val); /// TODO: pozerat CW/CCW a podla toho dat +/-
|
|
}
|
|
else
|
|
{
|
|
fmtError = true;
|
|
}
|
|
}
|
|
|
|
if (!fmtError) roisAndResults.SetResults(timeMs, angles);
|
|
}
|
|
|
|
toBeProcessed.Remove(0, from + len + 2);
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
string msg = string.Format("Exception in the measurement listener thread: {0}", exc.Message);
|
|
log.Error(msg);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
//public void OnMeasurementDataReceived(object sender, MeasuredDataEventArgs msrmtData)
|
|
//{
|
|
// string[] pulsesArr = msrmtData.MeasuredData.Split(new char[] { ';' });
|
|
|
|
// uint uiVal;
|
|
// if (result != null && result.Length + 1 == pulsesArr.Length && uint.TryParse(pulsesArr[0], out uiVal))
|
|
// {
|
|
// cameraTimeMs = (long)uiVal;
|
|
|
|
// for (int i = 0; i < result.Length; i++)
|
|
// {
|
|
// int val;
|
|
// if (int.TryParse(pulsesArr[i + 1], out val))
|
|
// {
|
|
// result[i] = Math.Abs(val);
|
|
// }
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
|
|
public IOperation LiveStreamOp(bool hiRes)
|
|
{
|
|
int wid = hiRes ? 1280 : 640;
|
|
int hgh = hiRes ? 960 : 480;
|
|
string command = string.Format("/opt/vc/bin/raspivid -t 0 -cd MJPEG -w {0} -h {1} -fps 30 -b 8000000 -o - | gst-launch-1.0 fdsrc ! \"image/jpeg,framerate=30/1\" ! jpegparse ! rtpjpegpay ! udpsink host={2} port={3}",
|
|
wid, hgh, NetAdapter.IPAddress, rtpUdpLocalPort);
|
|
|
|
return new LiveStreamOp(this, Telnet, command);
|
|
}
|
|
|
|
|
|
public IOperation GrabImagesOp(string[] imgFileNames, bool blackAndWhite, bool lowResolution, ImageRotation imageRotation)
|
|
{
|
|
return new GrabImagesOp(this, imgFileNames, blackAndWhite, lowResolution, imageRotation);
|
|
}
|
|
|
|
|
|
public IOperation MeasurementOp()
|
|
{
|
|
if (Telnet != null)
|
|
{
|
|
return this;
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
string command;
|
|
bool measurementCommandSent;
|
|
|
|
|
|
public void Start()
|
|
{
|
|
/// Prepare the telent command
|
|
StringBuilder sb = new StringBuilder();
|
|
for (int i = 1; i <= roisAndResults.RegisteredRoisCount; i++)
|
|
{
|
|
sb.Append(" ");
|
|
sb.Append(roisAndResults.GetRoiParams(i));
|
|
}
|
|
|
|
int logImagesArg;
|
|
switch (CameraCfg.TestImagesMode)
|
|
{
|
|
default:
|
|
case TestImagesMode.None:
|
|
case TestImagesMode.LoadImages:
|
|
logImagesArg = 0;
|
|
break;
|
|
case TestImagesMode.SaveFirstImages:
|
|
logImagesArg = CameraCfg.TestImagesCount;
|
|
break;
|
|
case TestImagesMode.SaveLastImages:
|
|
logImagesArg = -CameraCfg.TestImagesCount;
|
|
break;
|
|
}
|
|
|
|
command = string.Format("clp/Measurement -udp {0} {1}{2}{3} 1 7 0 0 {4}",
|
|
NetAdapter.IPAddress,
|
|
msrmntUdpLocalPort,
|
|
(CameraCfg.TestImagesMode == TestImagesMode.LoadImages) ? (" -l " + CameraCfg.TestImagesCount.ToString()) : string.Empty,
|
|
sb,
|
|
logImagesArg);
|
|
|
|
measurementCommandSent = false;
|
|
|
|
/// If ready send (=enqueue) the command
|
|
if (Telnet.State == TelnetClient.TelnetState.Inactive)
|
|
{
|
|
log.WarnFormat("{0} SEND_MSRMNT_CMD: {1}", Name, command);
|
|
Telnet.Enqueue(new Telnet.Command(CmdAction.SEND_MSRMNT_CMD, command));
|
|
measurementCommandSent = true;
|
|
}
|
|
}
|
|
|
|
public Event Run()
|
|
{
|
|
if (!measurementCommandSent)
|
|
{
|
|
/// When ready send (=enqueue) the command
|
|
if (Telnet.State == TelnetClient.TelnetState.Inactive)
|
|
{
|
|
log.WarnFormat("{0} SEND_MSRMNT_CMD: {1}", Name, command);
|
|
Telnet.Enqueue(new Telnet.Command(CmdAction.SEND_MSRMNT_CMD, command));
|
|
measurementCommandSent = true;
|
|
}
|
|
}
|
|
|
|
return Event.None;
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
if (measurementCommandSent)
|
|
{
|
|
log.WarnFormat("{0} SEND_COMMAND: CTRL-Q", Name);
|
|
Telnet.Enqueue(new Telnet.Command(CmdAction.SEND_COMMAND, TelnetClient.Q_Command));
|
|
}
|
|
}
|
|
}
|
|
}
|