aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs
blob: 2a18aff573202939c886b26472bfe8fcff3fca47 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#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
    }
}