<UserControl x:Class="Tango.PPC.Technician.Controls.DispenserController"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch"
xmlns:local="clr-namespace:Tango.PPC.Technician.Controls"
mc:Ignorable="d"
d:DesignHeight="150" d:DesignWidth="800" x:Name="control">
<Grid>
<Border CornerRadius="5" Background="{StaticResource TangoPrimaryBackgroundBrush}" BorderBrush="{StaticResource TangoLightBorderBrush}" BorderThickness="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="41*"/>
<RowDefinition Height="66*"/>
<RowDefinition Height="41*"/>
</Grid.RowDefinitions>
<Border Grid.Row="1">
<DockPanel Margin="40 0 0 0">
<Grid HorizontalAlignment="Left">
<Ellipse Stroke="{StaticResource TangoGrayBrush}" StrokeThickness="3"></Ellipse>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Security.Authentication;
using System.Text;
using System.Threading.Tasks;
using Tango.BL;
using Tango.BL.Entities;
using Tango.Integration.Operation;
using Tango.Logging;
using Tango.PMR;
using Tango.PMR.Common;
using Tango.PMR.Connection;
using Tango.PMR.Integration;
using Tango.Settings;
using Tango.Transport;
using Tango.Transport.Adapters;
using Tango.Transport.Transporters;
namespace Tango.Integration.ExternalBridge
{
/// <summary>
/// Represents a secure external bridge TCP client.
/// </summary>
/// <seealso cref="Tango.Transport.Transporters.BasicTransporter" />
/// <seealso cref="Tango.Integration.ExternalBridge.IExternalBridgeSecureClient" />
public class ExternalBridgeTcpClient : MachineOperator, IExternalBridgeSecureClient
{
private bool _logs_sent;
#region Properties
private String _serialNumber;
/// <summary>
/// Gets the machine serial number.
/// </summary>
public String SerialNumber
{
get { return _serialNumber; }
set
{
_serialNumber = value;
RaisePropertyChangedAuto();
}
}
private String _ipAddress;
/// <summary>
/// Gets or sets the machine IP address.
/// </summary>
public String IPAddress
{
get { return _ipAddress; }
set { _ipAddress = value; RaisePropertyChangedAuto(); }
}
private bool _enableApplicationLogs;
/// <summary>
/// Gets or sets a value indicating whether to enable receiving application logs.
/// </summary>
public bool EnableApplicationLogs
{
get { return _enableApplicationLogs; }
set
{
_enableApplicationLogs = value;
RaisePropertyChangedAuto();
OnEnableApplicationLogsChanged(value);
}
}
/// <summary>
/// Gets a value indicating whether this client requires authentication.
/// </summary>
public bool RequiresAuthentication => true;
#endregion
public override Task Connect()
{
throw new NotImplementedException("External Bridge TCP client must connect through the dedicated connect method.");
}
/// <summary>
/// Connects to a remote external bridge service using the specified login.
/// </summary>
/// <param name="login">The login.</param>
/// <returns></returns>
/// <exception cref="AuthenticationException">The machine password is invalid.</exception>
public async Task Connect(ExternalBridgeLoginRequest login)
{
if (State != TransportComponentState.Connected)
{
try
{
Adapter = new TcpTransportAdapter(IPAddress, SettingsManager.Default.GetOrCreate<IntegrationSettings>().ExternalBridgeServicePort);
await Adapter.Connect();
State = TransportComponentState.Connected;
StartThreads();
LogManager.Log("External Bridge TCP Client Connected...");
LogRequestSent(login);
var response = await SendRequest<ExternalBridgeLoginRequest, ExternalBridgeLoginResponse>(login);
DeviceInformation = response.Message.DeviceInformation;
if (!response.Message.Authenticated)
{
await Adapter.Disconnect();
throw new AuthenticationException(response.Container.ErrorMessage);
}
Status = MachineStatuses.ReadyToDye;
}
catch (Exception ex)
{
LogRequestFailed(login, ex);
try
{
await Adapter.Disconnect();
}
catch { }
throw ex;
}
OnEnableDiagnosticsChanged(EnableDiagnostics);
OnEnableEmbeddedDebuggingChanged(EnableEmbeddedDebugging);
OnEnableEventsNotification(EnableEventsNotification);
OnEnableApplicationLogsChanged(EnableApplicationLogs);
}
}
private async void OnEnableApplicationLogsChanged(bool value)
{
if (value && State == TransportComponentState.Connected && !_logs_sent)
{
var request = new StartApplicationLogsRequest();
bool responseLogged = false;
_logs_sent = true;
SendContinuousRequest<StartApplicationLogsRequest, StartApplicationLogsResponse>(request).ObserveOn(new NewThreadScheduler())
.Subscribe
(
(response) =>
{
if (!responseLogged)
{
LogResponseReceived(response.Message);
responseLogged = true;
}
OnApplicationLogAvailable(response);
},
(ex) =>
{
_logs_sent = false;
if (!(ex is ContinuousResponseAbortedException))
{
LogRequestFailed(request, ex);
}
},
() =>
{
_logs_sent = false;
});
LogRequestSent(request);
}
else if (_logs_sent)
{
_logs_sent = false;
if (State == TransportComponentState.Connected)
{
var req = new StopApplicationLogsRequest();
try
{
LogRequestSent(req);
var res = await SendRequest<StopApplicationLogsRequest, StopApplicationLogsResponse>(req);
LogResponseReceived(res.Message);
}
catch (Exception ex)
{
LogRequestFailed(req, ex);
}
}
}
}
private void OnApplicationLogAvailable(TangoMessage<StartApplicationLogsResponse> response)
{
try
{
if (response.Message.LogItem.Count() > 0)
{
LogItemBase log = LogItemBase.Deserialize(response.Message.LogItem.ToArray());
log.LogObject = "External Bridge";
LogManager.Log(log);
}
}
catch (Exception ex)
{
LogManager.Log(ex, "Error deserializing incoming application log item!");
}
}
public async override Task Disconnect()
{
if (State == TransportComponentState.Connected)
{
ExternalBridgeLogoutRequest request = new ExternalBridgeLogoutRequest();
LogRequestSent(request);
try
{
var response = await SendRequest<ExternalBridgeLogoutRequest, ExternalBridgeLogoutResponse>(request);
LogResponseReceived(response.Message);
Status = MachineStatuses.Standby;
}
catch (Exception ex)
{
LogRequestFailed(request, ex);
}
}
State = TransportComponentState.Disconnected;
if (Adapter != null)
{
await Adapter.Disconnect();
}
LogManager.Log("External Bridge TCP client disconnected.");
}
/// <summary>
/// Initializes a new instance of the <see cref="ExternalBridgeTcpClient"/> class.
/// </summary>
/// <param name="serialNumber">The machine serial number.</param>
/// <param name="ipAddress">The machine IP address.</param>
public ExternalBridgeTcpClient(String serialNumber, String ipAddress)
{
SerialNumber = serialNumber;
Machine = ObservablesStaticCollections.Instance.Machines.SingleOrDefault(x => x.SerialNumber == serialNumber);
IPAddress = ipAddress;
UseKeepAlive = false;
EnableDiagnostics = true;
}
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public override string ToString()
{
return SerialNumber;
}
/// <summary>
/// Called when a new request has been received.
/// </summary>
/// <param name="request">The request.</param>
protected async override void OnRequestReceived(MessageContainer request)
{
base.OnRequestReceived(request);
if (request.Type == MessageType.ExternalBridgeLogoutRequest)
{
await SendResponse<ExternalBridgeLogoutResponse>(new ExternalBridgeLogoutResponse(), request.Token);
try
{
State = TransportComponentState.Disconnected;
if (Adapter != null)
{
await Adapter.Disconnect();
}
LogManager.Log("External Bridge TCP client disconnected by the remote host.");
}
catch { }
SessionClosed?.Invoke(this, new EventArgs());
}
}
/// <summary>
/// Occurs when the remote host has closed the session.
/// </summary>
public event EventHandler SessionClosed;
/// <summary>
/// Gets the database machine associated with this client.
/// </summary>
public Machine Machine { get; private set; }
/// <summary>
/// Sets the database machine.
/// </summary>
/// <param name="machine">The machine.</param>
public void SetMachine(Machine machine)
{
Machine = machine;
}
}
}