#include "opencv2/ccalib/omnidir.hpp"
#include "opencv2/ccalib/multicalib.hpp"
#include "opencv2/ccalib/randpattern.hpp"
using namespace std;
using namespace cv;
const char * usage =
"\n example command line for multi-camera calibration by using random pattern \n"
" multi_cameras_calibration -nc 5 -pw 800 -ph 600 -ct 1 -fe 0 -nm 25 -v 0 multi_camera_omnidir.xml \n"
"\n"
" the file multi_camera_omnidir.xml is generated by imagelist_creator as \n"
" imagelist_creator multi_camera_omnidir.xml *.* \n"
" note the first filename in multi_camera_omnidir.xml is the pattern, the rest are photo names,\n"
" photo names should be in form of cameraIdx-timestamp.*, and cameraIdx starts from 0";
static void help()
{
printf("\n This is a sample for multi-camera calibration, so far it only support random pattern,\n"
"see randomPattern.hpp for detail. Pinhole and omnidirectional cameras are both supported, \n"
"for omnidirectional camera, see omnidir.hpp for detail.\n"
"Usage: mutiCamCalib \n"
" -nc <num_camera> # number of cameras \n"
" -pw <pattern_width> # physical width of random pattern \n"
" -ph <pattern_height> # physical height of random pattern \n"
" -ct <camera_type> # camera type, 0 for pinhole and 1 for omnidirectional \n"
" -fe # whether show feature extraction\n"
" -nm # number of minimal matches of an image \n"
" -v # whether show verbose information \n"
" input_data # text file with pattern file names and a list of photo names, the file is generated by imagelist_creator \n");
printf("\n %s", usage);
}
int main(int argc, char** argv)
{
float patternWidth = 0.0f, patternHeight = 0.0f;
int nCamera = 0, nMiniMatches = 0, cameraType = 0;
const char* outputFilename = "multi-camera-results.xml";
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Google.Protobuf;
using Tango.BL.Entities;
using Tango.Integration.Operation;
using Tango.PMR;
using Tango.PMR.Common;
using Tango.Transport;
using Tango.Transport.Transporters;
using Tango.PMR.Integration;
using Tango.Transport.Discovery;
using Tango.Transport.Servers;
using Tango.Transport.Adapters;
using Tango.PMR.Connection;
using Tango.PMR.Diagnostics;
using Tango.PMR.Debugging;
namespace Tango.Integration.ExternalBridge
{
public class ExternalBridgeService : BasicTransporter, IExternalBridgeService
{
private UdpDiscoveryService<ExternalBridgeUdpDiscoveryPacket> _discoverySevice;
private TcpServer _tcpServer;
private bool _send_app_logs;
private String _app_logs_token;
#region Events
/// <summary>
/// Occurs when a new client is waiting for authentication.
/// </summary>
public event EventHandler<ExternalBridgeClientConnectedEventArgs> ConnectionRequest;
/// <summary>
/// Occurs when the last client has been disconnected.
/// </summary>
public event EventHandler ClientDisconnected;
#endregion
#region Properties
private IMachineOperator _machineOperator;
/// <summary>
/// Gets or sets the machine operator.
/// </summary>
public IMachineOperator MachineOperator
{
get { return _machineOperator; }
set { _machineOperator = value; OnMachineOperatorChanged(); }
}
private Machine _machine;
/// <summary>
/// Gets or sets the machine.
/// </summary>
public Machine Machine
{
get { return _machine; }
set { _machine = value; OnMachineChanged(); }
}
/// <summary>
/// Gets a value indicating whether this instance is started.
/// </summary>
public bool IsStarted { get; private set; }
private bool _enabled;
/// <summary>
/// Gets or sets a value indicating whether this <see cref="IExternalBridgeService" /> is enabled.
/// </summary>
public bool Enabled
{
get { return _enabled; }
set
{
_enabled = value;
if (_enabled)
{
Start();
}
else
{
Stop();
}
RaisePropertyChangedAuto();
}
}
private bool _isInSession;
/// <summary>
/// Gets a value indicating whether a remote client is authenticated and in session.
/// </summary>
public bool IsInSession
{
get { return _isInSession; }
private set { _isInSession = value; RaisePropertyChangedAuto(); }
}
/// <summary>
/// Gets the current session login intent.
/// </summary>
public ExternalBridgeLoginIntent SessionIntent { get; private set; }
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="ExternalBridgeService"/> class.
/// </summary>
public ExternalBridgeService()
{
_tcpServer = new TcpServer(1984);
_tcpServer.ClientConnected += _tcpServer_ClientConnected;
LogManager.NewLog += LogManager_NewLog;
}
/// <summary>
/// Initializes a new instance of the <see cref="ExternalBridgeService"/> class.
/// </summary>
/// <param name="machineOperator">The machine operator.</param>
/// <param name="machine">The machine.</param>
public ExternalBridgeService(IMachineOperator machineOperator, Machine machine) : this()
{
Machine = machine;
MachineOperator = machineOperator;
}
#endregion
#region Properties Changes
/// <summary>
/// Called when the machine has been changed
/// </summary>
protected virtual void OnMachineChanged()
{
if (_discoverySevice != null && _discoverySevice.IsStarted)
{
_discoverySevice.Stop();
}
_discoverySevice = new UdpDiscoveryService<ExternalBridgeUdpDiscoveryPacket>(8888, new ExternalBridgeUdpDiscoveryPacket()
{
SerialNumber = Machine.SerialNumber,
});
}
/// <summary>
/// Called when the machine operator has been changed
/// </summary>
protected virtual void OnMachineOperatorChanged()
{
if (MachineOperator != null)
{
MachineOperator.StateChanged -= MachineOperator_StateChanged;
MachineOperator.StateChanged += MachineOperator_StateChanged;
}
}
#endregion
#region Event Handlers
/// <summary>
/// Handles the ClientConnected event of the _tcpServer control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="ClientConnectedEventArgs"/> instance containing the event data.</param>
private async void _tcpServer_ClientConnected(object sender, ClientConnectedEventArgs e)
{
LogManager.Log("External bridge client connected from: " + e.Socket.GetIPAddress());
Adapter = new TcpTransportAdapter(e.Socket);
await Connect();
}
/// <summary>
/// Machines the operator state changed.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The e.</param>
private void MachineOperator_StateChanged(object sender, TransportComponentState e)
{
//Do nothing right now.
}
private void LogManager_NewLog(object sender, Tango.Logging.LogItemBase e)
{
if (State == TransportComponentState.Connected && _send_app_logs)
{
try
{
SendResponse<StartApplicationLogsResponse>(new StartApplicationLogsResponse()
{
LogItem = ByteString.CopyFrom(e.Serialize())
}, _app_logs_token);
}
catch { }
}
}
#endregion
#region Public Methods
/// <summary>
/// Starts this instance.
/// </summary>
public void Start()
{
if (!IsStarted)
{
_tcpServer.Start();
_discoverySevice.Start();
IsStarted = true;
_enabled = true;
RaisePropertyChanged(nameof(Enabled));
}
}
/// <summary>
/// Stops this instance.
/// </summary>
public async void Stop()
{
if (IsStarted)
{
_tcpServer.Stop();
_discoverySevice.Stop();
IsStarted = false;
IsInSession = false;
_enabled = false;
RaisePropertyChanged(nameof(Enabled));
try
{
await Disconnect();
}
catch { }
}
}
/// <summary>
/// Disconnects the current remote client session.
/// </summary>
public async void DisconnectSession()
{
await Disconnect();
}
#endregion
#region Override Methods
protected override void OnRequestReceived(MessageContainer container)
{
base.OnRequestReceived(container);
try
{
if (Enabled)
{
if (container.Type == MessageType.ConnectRequest || container.Type == MessageType.DisconnectRequest)
{
//Do nothing !
}
else if (container.Type == MessageType.ExternalBridgeLoginRequest)
{
OnExternalBridgeLoginRequest(container);
}
else if (container.Type == MessageType.ExternalBridgeLogoutRequest)
{
OnExternalBridgeLogoutRequest(container);
}
else if (container.Type == MessageType.StartApplicationLogsRequest)
{
_app_logs_token = container.Token;
_send_app_logs = true;
SendResponse<StartApplicationLogsResponse>(new StartApplicationLogsResponse(), container.Token);
}
else if (container.Type == MessageType.StopApplicationLogsRequest)
{
_send_app_logs = false;
SendResponse<StopApplicationLogsResponse>(new StopApplicationLogsResponse() { }, container.Token);
SendResponse<StartApplicationLogsResponse>(new StartApplicationLogsResponse() { }, _app_logs_token, true);
}
else
{
if (IsInSession && SessionIntent == ExternalBridgeLoginIntent.Override)
{
OnAnyRequest(container);
}
}
}
}
catch (Exception ex)
{
LogManager.Log(ex, String.Format("An error occurred while processing a request message '{0}' from the remote host.", container.Type));
}
}
public async override Task Disconnect()
{
_send_app_logs = false;
try
{
if (IsInSession)
{
await SendRequest<ExternalBridgeLogoutRequest, ExternalBridgeLogoutResponse>(new ExternalBridgeLogoutRequest(), TimeSpan.FromSeconds(0.5));
}
}
catch (Exception ex)
{
LogManager.Log(ex, "Error sending an external bridge log out request.");
}
finally
{
ClearQueues();
}
OnClientDisconnected();
}
#endregion
#region Virtual Methods
protected async virtual void OnClientDisconnected()
{
IsInSession = false;
_send_app_logs = false;
if (MachineOperator.State == TransportComponentState.Connected)
{
try
{
await MachineOperator.SendRequest(new StopDiagnosticsRequest());
}
catch (Exception ex)
{
LogManager.Log(ex);
}
try
{
await MachineOperator.SendRequest(new StopDebugLogRequest());
}
catch (Exception ex)
{
LogManager.Log(ex);
}
}
ClientDisconnected?.Invoke(this, new EventArgs());
try
{
await base.Disconnect();
}
catch (Exception ex)
{
LogManager.Log(ex);
}
LogManager.Log("External bridge client disconnected.");
}
#endregion
#region Message Handlers
protected virtual async void OnAnyRequest(MessageContainer container)
{
if (MachineOperator.Status == MachineStatuses.Disconnected)
{
try
{
await SendErrorResponse(new Exception("Machine operator is disconnected."), container.Token);
}
catch { }
return;
}
if (!container.Continuous)
{
try
{
var response = await MachineOperator.SendRequest(container);
await SendResponse(response);
}
//catch (TimeoutException)
//{
//}
catch (Exception ex)
{
await SendErrorResponse(ex, container.Token);
}
}
else
{
MachineOperator.SendContinuousRequest(container).Subscribe((response) =>
{
if (Enabled && IsInSession)
{
SendResponse(response);
}
}, (ex) =>
{
if (Enabled)
{
if (ex is ResponseErrorException)
{
SendResponse((ex as ResponseErrorException).Container);
}
}
});
}
}
protected async virtual void OnExternalBridgeLogoutRequest(MessageContainer container)
{
try
{
await SendResponse<ExternalBridgeLogoutResponse>(new ExternalBridgeLogoutResponse(), container.Token);
}
catch (Exception ex)
{
LogManager.Log(ex);
}
finally
{
ClearQueues();
}
OnClientDisconnected();
}
protected async virtual void OnExternalBridgeLoginRequest(MessageContainer container)
{
var request = MessageFactory.ParseTangoMessageFromContainer<ExternalBridgeLoginRequest>(container);
LogManager.Log(String.Format("External bridge login attempt:{0}{1}", Environment.NewLine, request.Message.ToJsonString()));
if (MachineOperator.Status != MachineStatuses.Printing || request.Message.Intent != ExternalBridgeLoginIntent.Override)
{
ExternalBridgeClientConnectedEventArgs args = new ExternalBridgeClientConnectedEventArgs();
args.Request = request;
args.IpAddress = Adapter.Address;
ConnectionRequest?.Invoke(this, args);
var response = new ExternalBridgeLoginResponse();
response.Authenticated = args.Confirmed;
response.SerialNumber = Machine.SerialNumber;
response.DeviceInformation = MachineOperator.DeviceInformation;
IsInSession = args.Confirmed;
if (IsInSession)
{
LogManager.Log("External bridge client has logged-in successfully.");
MachineOperator.EnableDiagnostics = false;
MachineOperator.EnableEmbeddedDebugging = false;
SessionIntent = request.Message.Intent;
}
else
{
LogManager.Log("External bridge client login failed, invalid password.");
}
await SendResponse<ExternalBridgeLoginResponse>(response, container.Token);
}
else
{
LogManager.Log("External bridge client login failed because the machine is currently printing.");
await SendResponse<ExternalBridgeLoginResponse>(new ExternalBridgeLoginResponse(), container.Token, false, ErrorCode.GeneralError, "Machine connection override is not permitted while printing.");
}
}
#endregion
}
}