"Refactor CJMS11 image grab functionality with timeout handling and error resilience
- Introduced a new `GrabImageListener` method with asynchronous timeout support for improved response handling. - Enhanced error logging and implemented retry logic for capturing images to address NACK scenarios. - Added overlay rendering and event-based image delivery for better UI integration. - Refined `SendImageListener` logic to include command handling improvements and listener termination checks. - Minor parameter adjustments in `OnImageReceived` for default values support."
This commit is contained in:
parent
3e643854bc
commit
50a38bc557
@ -1088,6 +1088,139 @@ namespace TBF.Rig.Network.Camera.CJMS11
|
|||||||
// Get network stream
|
// Get network stream
|
||||||
|
|
||||||
|
|
||||||
|
using (cameraStream = this.cameraTcpClient.GetStream())
|
||||||
|
using (cameraWriter = new StreamWriter(cameraStream, Encoding.ASCII) { AutoFlush = true })
|
||||||
|
using (cameraReader = new StreamReader(cameraStream, Encoding.ASCII))
|
||||||
|
{
|
||||||
|
cameraStream.ReadTimeout = 1000;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SendCommand(CommandM.prepare_camera_);
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
log.Error($"Initialisation of connection readers failed: {exc.Message}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stopGrabImageListenerFlag = false;
|
||||||
|
int iCountOf_NACK = 0;
|
||||||
|
int iActualImageIndex = 0;
|
||||||
|
|
||||||
|
SendCommand(CommandM.grab_image_);
|
||||||
|
|
||||||
|
|
||||||
|
while (!stopGrabImageListenerFlag)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
Task<string> responseAnswerTask = cameraReader.ReadLineAsync();
|
||||||
|
var timeoutAnswerTask = Task.Delay(TimeSpan.FromSeconds(1));
|
||||||
|
var completedAnswerTask = Task.WhenAny(responseAnswerTask, timeoutAnswerTask).Result;
|
||||||
|
|
||||||
|
if (completedAnswerTask == timeoutAnswerTask)
|
||||||
|
{
|
||||||
|
throw new TimeoutException("Answer response attempt timed out after 1 second.");
|
||||||
|
}
|
||||||
|
|
||||||
|
string responseAnswer = responseAnswerTask.Result;
|
||||||
|
if (responseAnswer.Length > 0)
|
||||||
|
{
|
||||||
|
/// Process the packet
|
||||||
|
JmsPacket newPacket = new JmsPacket(responseAnswer);
|
||||||
|
|
||||||
|
if (newPacket.JmsMessage.Status != MessageStatus.ACK)
|
||||||
|
{
|
||||||
|
if (iCountOf_NACK < 5)
|
||||||
|
{
|
||||||
|
iCountOf_NACK++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.ErrorFormat("Error occured more as 5 time in GrabImageListener: {0}",
|
||||||
|
newPacket.JmsMessage.Status);
|
||||||
|
stopGrabImageListenerFlag = true; // mam obrazok ukoncim a zavriem thread
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (newPacket.JmsMessage.Command)
|
||||||
|
{
|
||||||
|
case CommandM.grab_image_:
|
||||||
|
ParsedImage parsedImage = newPacket.JmsMessage.getImage();
|
||||||
|
if (parsedImage.Encoding == ImageType.BASE_64)
|
||||||
|
{
|
||||||
|
Image image = parsedImage.Image;
|
||||||
|
|
||||||
|
|
||||||
|
if (showOverlayRect && overlayRect != null && overlayThickness > 0)
|
||||||
|
{
|
||||||
|
int penWidth = 1;
|
||||||
|
Pen pen = new Pen(Color.Green, penWidth);
|
||||||
|
using (var grph = Graphics.FromImage(image))
|
||||||
|
{
|
||||||
|
if (penWidth != overlayThickness)
|
||||||
|
{
|
||||||
|
penWidth = overlayThickness;
|
||||||
|
pen = new Pen(Color.Green, penWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
grph.DrawRectangle(pen, overlayRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OnImageReceived(this, this.cameraIdx, image, RoiConfiguration.ImageRotation);
|
||||||
|
iActualImageIndex++;
|
||||||
|
if (iActualImageIndex >= RoiConfiguration.ImageOpacity.Count)
|
||||||
|
{
|
||||||
|
stopGrabImageListenerFlag =
|
||||||
|
true; // mam obrazok ukoncim a zavriem thread
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
log.Error($"Grab Image - Hardware Addr: {CameraCfg.HardwareAddress} Camera IP: {CameraCfg.IPAddressCJMS}, Port: {iPort} Exception in MJpeg RTP listener thread: { exc.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stopGrabImageListenerFlag = false;
|
||||||
|
SendCommandAndWaitToAnswer(cameraWriter, cameraReader, CommandM.close_);
|
||||||
|
SendCommandAndWaitToAnswer(cameraWriter, cameraReader, CommandM.disconnect_);
|
||||||
|
|
||||||
|
CloseCameraResources();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}catch(Exception exc)
|
||||||
|
{
|
||||||
|
log.Error($"Grab Image - Hardware Addr: {CameraCfg.HardwareAddress} Camera IP: {CameraCfg.IPAddressCJMS}, Port: {iPort} exception: {exc.Message}");
|
||||||
|
UiBridge.Bridge.OnImage(this.cameraIdx, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendImageListener()
|
||||||
|
{
|
||||||
|
using (this.cameraTcpClient = new TcpClient())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
EstablishCameraConnection(ref this.cameraTcpClient, CameraCfg.IPAddressCJMS, iPort);
|
||||||
|
|
||||||
|
log.Info(string.Format("Camera connected to server {0}:{1}.", CameraCfg.IPAddressCJMS, iPort));
|
||||||
|
ipAddress = IPAddress.Parse(CameraCfg.IPAddressCJMS);
|
||||||
|
// Get network stream
|
||||||
|
|
||||||
|
|
||||||
using (cameraStream = this.cameraTcpClient.GetStream())
|
using (cameraStream = this.cameraTcpClient.GetStream())
|
||||||
using (cameraWriter = new StreamWriter(cameraStream, Encoding.ASCII) { AutoFlush = true })
|
using (cameraWriter = new StreamWriter(cameraStream, Encoding.ASCII) { AutoFlush = true })
|
||||||
using (cameraReader = new StreamReader(cameraStream, Encoding.ASCII))
|
using (cameraReader = new StreamReader(cameraStream, Encoding.ASCII))
|
||||||
@ -1109,7 +1242,7 @@ namespace TBF.Rig.Network.Camera.CJMS11
|
|||||||
int iActualImageIndex = 0;
|
int iActualImageIndex = 0;
|
||||||
|
|
||||||
//TODO BUMI send grab image or send - based on count of images - but must work similary
|
//TODO BUMI send grab image or send - based on count of images - but must work similary
|
||||||
if (RoiConfiguration.ImageOpacity.Count > 1)
|
if (RoiConfiguration.ImageOpacity.Count <= 1)
|
||||||
{
|
{
|
||||||
SendCommand(CommandM.grab_image_);
|
SendCommand(CommandM.grab_image_);
|
||||||
}
|
}
|
||||||
@ -1156,6 +1289,7 @@ namespace TBF.Rig.Network.Camera.CJMS11
|
|||||||
|
|
||||||
switch (newPacket.JmsMessage.Command)
|
switch (newPacket.JmsMessage.Command)
|
||||||
{
|
{
|
||||||
|
case CommandM.send_:
|
||||||
case CommandM.grab_image_:
|
case CommandM.grab_image_:
|
||||||
ParsedImage parsedImage = newPacket.JmsMessage.getImage();
|
ParsedImage parsedImage = newPacket.JmsMessage.getImage();
|
||||||
if (parsedImage.Encoding == ImageType.BASE_64)
|
if (parsedImage.Encoding == ImageType.BASE_64)
|
||||||
@ -1579,7 +1713,7 @@ namespace TBF.Rig.Network.Camera.CJMS11
|
|||||||
/// This method is called from within this class when
|
/// This method is called from within this class when
|
||||||
/// a prompt string was received from the telnet server.
|
/// a prompt string was received from the telnet server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void OnImageReceived(object sender, int idxImage, Image image, ImageRotation imageRotation, int iImageIdx, int imageCount)
|
public static void OnImageReceived(object sender, int idxImage, Image image, ImageRotation imageRotation, int iImageIdx = 0, int imageCount = 1)
|
||||||
{
|
{
|
||||||
|
|
||||||
log.Info("Image received");
|
log.Info("Image received");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user