using Google.Protobuf; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Tango.Transport.Servers; using Tango.Logging; using Tango.PMR; using Tango.PMR.Common; using Tango.PMR.Stubs; using Tango.Core.Commands; using Tango.Transport; using Tango.PMR.Integration; using Tango.PMR.Diagnostics; using System.Windows.Forms; using Google.Protobuf.Collections; using Tango.PMR.Printing; using Tango.BL.Entities; using Tango.PMR.Debugging; using Tango.BL.Enumerations; using Tango.BL; using Tango.PMR.Connection; using Tango.PMR.Hardware; using System.Runtime.InteropServices; using Tango.PMR.IO; using System.IO; using Tango.Integration.Operation; using Tango.PMR.FirmwareUpgrade; using System.Diagnostics; using Tango.Core.ExtensionMethods; using Tango.PMR.MachineStatus; namespace Tango.Emulations.Emulators { /// /// Represents a Tango machine emulator. /// /// public class MachineEmulator : EmulatorBase { [DllImport("Tango.Emulations.Native.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ProcessMessage")] public static extern int ProcessMessageNative(IntPtr data, int size, ref IntPtr output); private class ContinousResponseToken { public bool Canceled { get; set; } } private const int MAX_CHUNK_LENGTH = 4000; private StartDiagnosticsRequest _diagnosticsRequest; private bool _cancelJob; private List _motorJoggingRequestTypes; private List _motorHomingRequestCodes; private List _dispenserJoggingRequestCodes; private List _dispenserHomingRequestCodes; private double _graphAmplitude; private double _graphFrequency; private List _digitalOutputPinsStates; private List _digitalInputPinsStates; private List _componentsStates; private List _heater_states; private List _continousResponseTokens; public List EventsStates { get; set; } private bool _diagnostics_enabled; private bool _debug_logs_enabled; private bool _events_enabled; private bool _machine_updates_enabled; private List _blower_states; private List _valveStates; private JobTicket _current_job_ticket; private String _current_job_resume_token; private FileUploadRequest _lastFileUploadRequest; #region Properties private bool _performNativeRoundTrip; /// /// Gets or sets a value indicating whether [perform native round trip]. /// public bool PerformNativeRoundTrip { get { return _performNativeRoundTrip; } set { _performNativeRoundTrip = value; RaisePropertyChangedAuto(); } } private bool _emulateCorruption; /// /// Gets or sets a value indicating whether emulate corruption in keep alive and job response. /// public bool EmulateCorruption { get { return _emulateCorruption; } set { _emulateCorruption = value; RaisePropertyChangedAuto(); Transporter.EnableKeepAliveAutoResponse = !_emulateCorruption; } } public MachineStatus MachineStatus { get; set; } #endregion #region Constructors /// /// Initializes a new instance of the class. /// public MachineEmulator() : base() { Init(); } /// /// Initializes a new instance of the class. /// /// The transporter. public MachineEmulator(ITransporter transporter) : base(transporter) { LogManager.Log("Machine emulator initialized using transporter " + transporter.ToString()); Init(); } #endregion #region Private Methods private ContinousResponseToken CreateCancelToken() { ContinousResponseToken t = new ContinousResponseToken(); _continousResponseTokens.Add(t); return t; } private void Init() { MachineStatus = new MachineStatus(); MachineStatus.State = MachineState.Ready; for (int i = 0; i < 8; i++) { MachineStatus.IDSPacksLevels.Add(new IDSPackLevel() { Index = i, DispenserLevel = 130000000, MidTankLevel = 2500, }); } EventsStates = MachineEventState.GetAllEventsStates(); _valveStates = new List(); _blower_states = new List(); _heater_states = new List(); _continousResponseTokens = new List(); _motorJoggingRequestTypes = new List(); _motorHomingRequestCodes = new List(); _dispenserJoggingRequestCodes = new List(); _dispenserHomingRequestCodes = new List(); _digitalOutputPinsStates = new List(); _componentsStates = new List(); ObservablesStaticCollections adapter = ObservablesStaticCollections.Instance; adapter.Initialize(); _digitalOutputPinsStates = adapter.TechIos.Where(x => x.Type == IOType.DigitalOutput.ToInt32()).Select(x => new DigitalInterfaceState() { InterfaceIO = (InterfaceIOs)x.Code, }).ToList(); _digitalInputPinsStates = adapter.TechIos.Where(x => x.Type == IOType.DigitalInput.ToInt32()).Select(x => new DigitalInterfaceState() { InterfaceIO = (InterfaceIOs)x.Code, }).ToList(); foreach (var item in adapter.TechControllers) { _componentsStates.Add(new ValueComponentState() { Component = (ValueComponent)item.Code, Value = item.Min }); } foreach (var item in adapter.TechHeaters) { _heater_states.Add(new HeaterState() { HeaterType = (HeaterType)item.Code, }); } foreach (var item in adapter.HardwareBlowerTypes) { _blower_states.Add(new SetBlowerStateRequest() { BlowerType = (PMR.Hardware.HardwareBlowerType)item.Code, }); } foreach (var item in adapter.TechValves) { _valveStates.Add(new ValveState() { ValveType = (ValveType)item.Code, State = (ValveStateCode)Enum.Parse(typeof(ValveStateCode), item.State1.Replace(" ", ""), true), }); } ResetGraphFactors(); } private void ResetGraphFactors() { _graphAmplitude = 75; _graphFrequency = 1; } #endregion #region Override Methods /// /// Called on new request message. /// /// The sender. /// The container. protected override void OnTransporterRequestReceived(object sender, MessageContainer container) { if (container.Type != MessageType.FileChunkUploadRequest && container.Type != MessageType.FileChunkDownloadRequest) { LogManager.Log(container.Type.ToString().ToWords() + " received." + Environment.NewLine + MessageFactory.ExtractMessageFromContainer(container).ToJsonString()); } if (PerformNativeRoundTrip) { NativePMR nativePMR = new NativePMR(ProcessMessageNative); var response = nativePMR.Invoke(container); if (response != null) { container = response; } else { LogManager.Log("Native RoundTrip is not available for " + container.Type.ToString() + "."); } } switch (container.Type) { case MessageType.CalculateRequest: HandleCalculateRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.ProgressRequest: HandleProgressRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.StartDiagnosticsRequest: HandleStartDiagnosticsRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.StopDiagnosticsRequest: HandleStopDiagnosticsRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.StartEventsNotificationRequest: HandleStartEventsNotificationRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.StopEventsNotificationRequest: HandleStopEventsNotificationRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.StartMachineStatusUpdateRequest: HandleStartMachineStatusUpdateRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.StopMachineStatusUpdateRequest: HandleStopMachineStatusUpdateRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.JobRequest: HandleJobRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.AbortJobRequest: HandleAbortJobRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.MotorJoggingRequest: HandleMotorJoggingRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.MotorAbortJoggingRequest: HandleAbortMotorJoggingRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.MotorHomingRequest: HandleMotorHomingRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.MotorAbortHomingRequest: HandleAbortMotorHomingRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.DispenserJoggingRequest: HandleDispenserJoggingRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.DispenserAbortJoggingRequest: HandleAbortDispenserJoggingRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.DispenserHomingRequest: HandleDispenserHomingRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.DispenserAbortHomingRequest: HandleAbortDispenserHomingRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.SetDigitalOutRequest: HandleSetDigitalOutRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.ThreadJoggingRequest: HandleThreadJoggingRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.ThreadAbortJoggingRequest: HandleThreadAbortJoggingRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.StartDebugLogRequest: HandleStartDebugLogRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.StopDebugLogRequest: HandleStopDebugLogRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.UploadProcessParametersRequest: HandleUploadProcessParametersRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.SetComponentValueRequest: HandleSetComponentValueRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.ResolveEventRequest: HandleResolveEventRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.DisconnectRequest: HandleDisconnectRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.ConnectRequest: HandleConnectRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.UploadHardwareConfigurationRequest: HandleUploadHardwareConfigurationRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.StubFpgaWriteRegRequest: HandleResetRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.SetHeaterStateRequest: HandleSetHeaterStateRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.SetBlowerStateRequest: HandleSetBlowerStateRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.SetValveStateRequest: HandleSetValveStateRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.CurrentJobRequest: HandleCurrentJobRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.ResumeCurrentJobRequest: HandleResumeCurrentJobRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.GetStorageInfoRequest: HandleGetStorageInfoRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.GetFilesRequest: HandleGetFilesRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.FileDownloadRequest: HandleFileDownloadRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.FileChunkDownloadRequest: HandleFileChunkDownloadRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.CreateRequest: HandleCreateRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.DeleteRequest: HandleDeleteRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.FileUploadRequest: HandleFileUploadRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.FileChunkUploadRequest: HandleFileChunkUploadRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.ValidateVersionRequest: HandleValidateVersionRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; case MessageType.ActivateVersionRequest: HandleActivateVersionRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; } } #endregion #region Request Handlers private void HandleCalculateRequest(TangoMessage request) { Task.Factory.StartNew(() => { var response = MessageFactory.CreateTangoMessage(request.Container.Token); response.Message.Sum = request.Message.A + request.Message.B; Transporter.SendResponse(response); }); } private void HandleProgressRequest(TangoMessage request) { Task.Factory.StartNew(() => { for (int i = 0; i < request.Message.Amount; i++) { Thread.Sleep(request.Message.Delay * 10); var res = MessageFactory.CreateTangoMessage(request.Container.Token); res.Message.Progress = i; if (i == request.Message.Amount - 1) res.Container.Completed = true; Transporter.SendResponse(res); } }); } private void HandleStartDiagnosticsRequest(TangoMessage request) { _diagnostics_enabled = true; _diagnosticsRequest = request.Message; int value = 0; Random rnd = new Random(); var cancelToken = CreateCancelToken(); Task.Factory.StartNew(() => { while (_diagnostics_enabled && Transporter.State == TransportComponentState.Connected && !cancelToken.Canceled) { StartDiagnosticsResponse res = new StartDiagnosticsResponse(); DiagnosticsMonitors monitors = new DiagnosticsMonitors(); res.Monitors = monitors; for (int i = 0; i < 10; i++) { value++; monitors.Dancer1Angle.Add((int)(150 + _graphAmplitude * Math.Sin(2 * 3.14 * ((int)_graphFrequency) * value))); } var blower_state = _blower_states.FirstOrDefault(); if (blower_state != null) { monitors.BlowerVoltage.Add(blower_state.IsActive ? blower_state.Voltage : 0); } int y = Cursor.Position.Y; for (int i = 0; i < 1; i++) { monitors.Dancer2Angle.Add(y); } for (int i = 0; i < 30; i++) { monitors.Dancer3Angle.Add(y); } for (int i = 0; i < MachineStatus.IDSPacksLevels.Count; i++) { var dispensers = new DoubleArray(); dispensers.Data.Add(MachineStatus.IDSPacksLevels[i].DispenserLevel); monitors.DispensersInkLevel.Add(dispensers); var midTanks = new DoubleArray(); midTanks.Data.Add(MachineStatus.IDSPacksLevels[i].MidTankLevel); monitors.MidTanksInkLevel.Add(midTanks); } var dispenserFrequencies = new RepeatedField(); double cPosition = Cursor.Position.Y; for (int i = 0; i < 8; i++) { DoubleArray singleDispenser = new DoubleArray(); for (int j = 0; j < 10; j++) { singleDispenser.Data.Add(cPosition + (i * 50)); } dispenserFrequencies.Add(singleDispenser); } monitors.DispensersMotorsFrequency.AddRange(dispenserFrequencies); monitors.Dispenser1MotorFrequency.AddRange(dispenserFrequencies[0].Data); monitors.Dispenser2MotorFrequency.AddRange(dispenserFrequencies[1].Data); monitors.Dispenser3MotorFrequency.AddRange(dispenserFrequencies[2].Data); monitors.Dispenser4MotorFrequency.AddRange(dispenserFrequencies[3].Data); monitors.Dispenser5MotorFrequency.AddRange(dispenserFrequencies[4].Data); monitors.Dispenser6MotorFrequency.AddRange(dispenserFrequencies[5].Data); monitors.Dispenser7MotorFrequency.AddRange(dispenserFrequencies[6].Data); monitors.Dispenser8MotorFrequency.AddRange(dispenserFrequencies[7].Data); res.DigitalInterfaceStates.AddRange(_digitalOutputPinsStates.Concat(_digitalInputPinsStates)); res.ComponentsStates.AddRange(_componentsStates); res.HeatersStates.AddRange(_heater_states); res.ValvesStates.AddRange(_valveStates); if (!EmulateCorruption) { Transporter.SendResponse(res, request.Container.Token); } Thread.Sleep(300); } }); } private void HandleStopDiagnosticsRequest(TangoMessage request) { _diagnostics_enabled = false; Transporter.SendResponse(new StopDiagnosticsResponse(), request.Container.Token); } private void HandleStartEventsNotificationRequest(TangoMessage request) { _events_enabled = true; var cancelToken = CreateCancelToken(); Task.Factory.StartNew(() => { while (_events_enabled && Transporter.State == TransportComponentState.Connected && !cancelToken.Canceled) { var res = new StartEventsNotificationResponse(); res.Events.AddRange(EventsStates.Where(x => x.IsActive).Select(x => new Event() { Type = x.EventType, Message = "Generated by Tango Embedded Emulator" })); if (!EmulateCorruption) { Transporter.SendResponse(res, request.Container.Token); } Thread.Sleep(1000); } }); } private void HandleStopEventsNotificationRequest(TangoMessage request) { _events_enabled = false; Transporter.SendResponse(new StopEventsNotificationResponse(), request.Container.Token); } private void HandleStartMachineStatusUpdateRequest(TangoMessage request) { _machine_updates_enabled = true; var cancelToken = CreateCancelToken(); Task.Factory.StartNew(() => { while (_machine_updates_enabled && Transporter.State == TransportComponentState.Connected && !cancelToken.Canceled) { var res = new StartMachineStatusUpdateResponse(); res.Status = MachineStatus; if (!EmulateCorruption) { Transporter.SendResponse(res, request.Container.Token); } Thread.Sleep(1000); } }); } private void HandleStopMachineStatusUpdateRequest(TangoMessage request) { _machine_updates_enabled = false; Transporter.SendResponse(new StopMachineStatusUpdateResponse(), request.Container.Token); } private void HandleStartDebugLogRequest(TangoMessage request) { _debug_logs_enabled = true; int counter = 1; int counter_message = 0; var cancelToken = CreateCancelToken(); Task.Factory.StartNew(() => { while (_debug_logs_enabled && Transporter.State == TransportComponentState.Connected && !cancelToken.Canceled) { StartDebugLogResponse res = new StartDebugLogResponse(); res.FileName = "C:\\demoFile.c"; res.LineNumber = 100; res.Filter = 1; res.Message = "This is a false message " + counter; res.Category = DebugLogCategory.Info; if (!EmulateCorruption) { Transporter.SendResponse(res, request.Container.Token); } Thread.Sleep(10); counter_message++; if (counter_message > 10) { counter_message = 0; counter++; } } }); } private void HandleJobRequest(TangoMessage request) { MachineStatus.State = MachineState.PreparingJob; JobTicket job = request.Message.JobTicket; _current_job_ticket = job; _current_job_resume_token = null; if (_current_job_ticket.UploadStrategy == JobUploadStrategy.JobDescriptionFile) { using (FileStream fs = new FileStream(_current_job_ticket.JobDescriptionFile, FileMode.Open)) { var segments = JobDescriptionFile.ReadJobDescriptionFile(fs); _current_job_ticket.Segments.AddRange(segments); } var logedTicket = _current_job_ticket.Clone(); foreach (var segment in logedTicket.Segments) { if (segment.BrushStops.Count > 2) { var first = segment.BrushStops.First(); var last = segment.BrushStops.Last(); segment.BrushStops.Clear(); segment.BrushStops.Add(first); segment.BrushStops.Add(last); } } LogManager.Log("Parsed Job Upload File (Showing first and last brush stop for segment):\n" + logedTicket.ToJsonString()); } double centimeter_per_second = request.Message.JobTicket.ProcessParameters.DyeingSpeed; double progress = 0; _cancelJob = false; bool message_sent = false; double length = job.Segments.Sum(x => x.Length) * (Math.Max(job.NumberOfUnits, 1)); Task.Factory.StartNew(() => { MachineStatus.State = MachineState.RunningJob; while (progress < length + job.ProcessParameters.DryerBufferLength * ProcessParametersTable.DRYER_METERS_PER_CYCLE && !_cancelJob) { var status = new PMR.Printing.JobStatus(); status.Progress = progress; if (!message_sent) { message_sent = true; status.Message = "Demo Message From Emulator..."; } if (!EmulateCorruption) { if (_current_job_resume_token == null) { Transporter.SendResponse(new JobResponse() { Status = status, }, request.Container.Token); } else { Transporter.SendResponse(new ResumeCurrentJobResponse() { Status = status, }, _current_job_resume_token); } } progress += Math.Min((centimeter_per_second / 1000d), (length + job.ProcessParameters.DryerBufferLength * ProcessParametersTable.DRYER_METERS_PER_CYCLE) - progress); Thread.Sleep(100); } _current_job_ticket = null; if (_cancelJob) { if (_current_job_resume_token == null) { Transporter.SendResponse(new JobResponse() { }, request.Container.Token, false, ErrorCode.ContinuousResponseAborted); } else { Transporter.SendResponse(new ResumeCurrentJobResponse() { }, _current_job_resume_token, false, ErrorCode.ContinuousResponseAborted); } } else { if (_current_job_resume_token == null) { Transporter.SendResponse(new JobResponse() { Status = new PMR.Printing.JobStatus() { Progress = length + job.ProcessParameters.DryerBufferLength * ProcessParametersTable.DRYER_METERS_PER_CYCLE, } }, request.Container.Token, !_cancelJob); } else { Transporter.SendResponse(new ResumeCurrentJobResponse() { Status = new PMR.Printing.JobStatus() { Progress = length + job.ProcessParameters.DryerBufferLength * ProcessParametersTable.DRYER_METERS_PER_CYCLE, } }, _current_job_resume_token, !_cancelJob); } } MachineStatus.State = MachineState.Ready; }); } private void HandleAbortJobRequest(TangoMessage request) { _cancelJob = true; Transporter.SendResponse(new AbortJobResponse(), request.Container.Token); } private void HandleMotorJoggingRequest(TangoMessage request) { var jogRequest = request.Message; _motorJoggingRequestTypes.Add(jogRequest.MotorType); Task.Factory.StartNew(() => { while (_motorJoggingRequestTypes.Contains(jogRequest.MotorType)) { if (jogRequest.Direction == MotorDirection.Forward) { _graphFrequency = 10; } else { _graphFrequency = 18; } Thread.Sleep(30); } ResetGraphFactors(); }); Transporter.SendResponse(new MotorJoggingResponse(), request.Container.Token); } private void HandleAbortMotorJoggingRequest(TangoMessage request) { _motorJoggingRequestTypes.RemoveAll(x => x == request.Message.MotorType); ResetGraphFactors(); Transporter.SendResponse(new MotorAbortJoggingResponse(), request.Container.Token); } private void HandleMotorHomingRequest(TangoMessage request) { var homeRequest = request.Message; _motorHomingRequestCodes.Add(homeRequest.MotorType); Task.Factory.StartNew(() => { _graphFrequency = 10; var inputPin = _digitalInputPinsStates.FirstOrDefault(); for (int i = 0; i < 100; i++) { if (inputPin != null) { inputPin.Value = !inputPin.Value; } Transporter.SendResponse(new MotorHomingResponse() { MaxProgress = 100, Progress = i }, request.Container.Token); if (!_motorHomingRequestCodes.Contains(homeRequest.MotorType)) { ResetGraphFactors(); return; } Thread.Sleep(30); } Transporter.SendResponse(new MotorHomingResponse() { MaxProgress = 100, Progress = 100 }, request.Container.Token, true); _motorHomingRequestCodes.Remove(homeRequest.MotorType); ResetGraphFactors(); }); } private void HandleAbortMotorHomingRequest(TangoMessage request) { _motorHomingRequestCodes.RemoveAll(x => x == request.Message.MotorType); ResetGraphFactors(); Transporter.SendResponse(new MotorAbortHomingResponse(), request.Container.Token); } private void HandleDispenserJoggingRequest(TangoMessage request) { var jogRequest = request.Message; _dispenserJoggingRequestCodes.Add(jogRequest.Index); Task.Factory.StartNew(() => { while (_dispenserJoggingRequestCodes.Contains(jogRequest.Index)) { if (jogRequest.Direction == MotorDirection.Forward) { _graphFrequency = 10; } else { _graphFrequency = 18; } Thread.Sleep(30); } ResetGraphFactors(); }); Transporter.SendResponse(new DispenserJoggingResponse(), request.Container.Token); } private void HandleAbortDispenserJoggingRequest(TangoMessage request) { _dispenserJoggingRequestCodes.RemoveAll(x => x == request.Message.Index); ResetGraphFactors(); Transporter.SendResponse(new DispenserAbortJoggingResponse(), request.Container.Token); } private void HandleDispenserHomingRequest(TangoMessage request) { var homeRequest = request.Message; _dispenserHomingRequestCodes.Add(homeRequest.Index); Task.Factory.StartNew(() => { _graphFrequency = 10; for (int i = 0; i < 100; i++) { Transporter.SendResponse(new DispenserHomingResponse() { MaxProgress = 100, Progress = i }, request.Container.Token); if (!_dispenserHomingRequestCodes.Contains(homeRequest.Index)) { ResetGraphFactors(); return; } Thread.Sleep(30); } Transporter.SendResponse(new DispenserHomingResponse() { MaxProgress = 100, Progress = 100 }, request.Container.Token, true); _dispenserHomingRequestCodes.Remove(homeRequest.Index); ResetGraphFactors(); }); } private void HandleAbortDispenserHomingRequest(TangoMessage request) { _dispenserHomingRequestCodes.RemoveAll(x => x == request.Message.Index); ResetGraphFactors(); Transporter.SendResponse(new DispenserAbortHomingResponse(), request.Container.Token); } private void HandleSetDigitalOutRequest(TangoMessage request) { var pinState = _digitalOutputPinsStates.SingleOrDefault(x => x.InterfaceIO == request.Message.InterfaceIO); if (pinState != null) { pinState.Value = request.Message.Value; Transporter.SendResponse(new SetDigitalOutResponse(), request.Container.Token); } else { Transporter.SendResponse(new SetDigitalOutResponse(), request.Container.Token, null, ErrorCode.InvalidDigitalPinNumber); } } private void HandleThreadJoggingRequest(TangoMessage request) { Transporter.SendResponse(new ThreadJoggingResponse(), request.Container.Token); } private void HandleThreadAbortJoggingRequest(TangoMessage request) { Transporter.SendResponse(new ThreadAbortJoggingResponse(), request.Container.Token); } private void HandleUploadProcessParametersRequest(TangoMessage request) { Task.Factory.StartNew(() => { Thread.Sleep(1000); Transporter.SendResponse(new UploadProcessParametersResponse(), request.Container.Token); }); } private void HandleSetComponentValueRequest(TangoMessage request) { var componentState = _componentsStates.SingleOrDefault(x => x.Component == request.Message.Component); double startValue = componentState.Value; double targetValue = request.Message.Value; Transporter.SendResponse(new SetComponentValueResponse(), request.Container.Token); Task.Factory.StartNew(() => { if (targetValue > startValue) { while (componentState.Value < targetValue) { componentState.Value++; Thread.Sleep(30); } } else { while (componentState.Value > targetValue) { componentState.Value--; Thread.Sleep(30); } } }); } private void HandleResolveEventRequest(TangoMessage request) { EventsStates.Where(x => x.EventType == request.Message.Type).ToList().ForEach(x => x.IsActive = false); Transporter.SendResponse(new ResolveEventResponse(), request.Container.Token); } private void HandleDisconnectRequest(TangoMessage request) { foreach (var cancelToken in _continousResponseTokens) { cancelToken.Canceled = true; } _continousResponseTokens.Clear(); try { Transporter.SendResponse(new DisconnectResponse(), request.Container.Token); } catch { } } private void HandleConnectRequest(TangoMessage request) { if (!EmulateCorruption) { foreach (var cancelToken in _continousResponseTokens) { cancelToken.Canceled = true; } _continousResponseTokens.Clear(); Transporter.SendResponse(new ConnectResponse() { DeviceInformation = new DeviceInformation() { Version = "1.0.0.0", BuildDate = DateTime.Now.ToString(), Name = "Machine Emulator", FPGA1Version = "1.1", FPGA2Version = "2.2", FPGA3Version = "3.3" }, }, request.Container.Token, null, request.Message.Password == "1234" ? ErrorCode.None : ErrorCode.UnauthorizedConnection); } } private void HandleStopDebugLogRequest(TangoMessage request) { _debug_logs_enabled = false; Transporter.SendResponse(new StopDebugLogResponse(), request.Container.Token); } private void HandleUploadHardwareConfigurationRequest(TangoMessage request) { Transporter.SendResponse(new UploadHardwareConfigurationResponse(), request.Container.Token); } private void HandleResetRequest(TangoMessage request) { Transporter.SendResponse(new StubFpgaWriteRegResponse(), request.Container.Token); } private void HandleSetHeaterStateRequest(TangoMessage request) { var heater = _heater_states.SingleOrDefault(x => x.HeaterType == request.Message.HeaterType); if (heater != null) { double startValue = heater.CurrentValue; double targetValue = request.Message.SetPoint; Task.Factory.StartNew(() => { heater.IsRampingUp = true; heater.IsActive = true; heater.IsInSetPoint = false; heater.SetPoint = targetValue; if (targetValue > startValue) { while (heater.CurrentValue < targetValue) { heater.CurrentValue++; Thread.Sleep(30); } } else { while (heater.CurrentValue > targetValue) { heater.CurrentValue--; Thread.Sleep(30); } } heater.IsRampingUp = false; heater.IsActive = false; heater.IsInSetPoint = true; }); } Transporter.SendResponse(new SetHeaterStateResponse(), request.Container.Token); } private void HandleSetBlowerStateRequest(TangoMessage request) { var blower_state = _blower_states.FirstOrDefault(); if (blower_state != null) { blower_state.Voltage = request.Message.Voltage; blower_state.IsActive = request.Message.IsActive; } Transporter.SendResponse(new SetBlowerStateResponse(), request.Container.Token); } private void HandleSetValveStateRequest(TangoMessage request) { var valve_state = _valveStates.SingleOrDefault(x => x.ValveType == request.Message.ValveType); if (valve_state != null) { valve_state.State = request.Message.State; } Transporter.SendResponse(new SetValveStateResponse(), request.Container.Token); } private void HandleCurrentJobRequest(TangoMessage request) { Transporter.SendResponse(new CurrentJobResponse() { IsJobInProgress = _current_job_ticket != null, JobTicket = _current_job_ticket, }, request.Container.Token); } private void HandleResumeCurrentJobRequest(TangoMessage request) { if (_current_job_ticket != null) { _current_job_resume_token = request.Container.Token; } else { Transporter.SendResponse(new ResumeCurrentJobResponse(), request.Container.Token, true, ErrorCode.NoJobInProgress); } } private void HandleGetStorageInfoRequest(TangoMessage request) { var d = new DriveInfo("C"); Directory.CreateDirectory("C:\\EmulatorStorage"); Transporter.SendResponse(new GetStorageInfoResponse() { Capacity = d.TotalSize, FreeSpace = d.TotalFreeSpace, Root = "/" }, request.Container.Token); } private void HandleGetFilesRequest(TangoMessage request) { GetFilesResponse response = new GetFilesResponse(); bool failed = false; String msg = null; try { String path = request.Message.Path; bool replaceSlash = path.Contains("/"); foreach (var dir in Directory.GetDirectories(path)) { DirectoryInfo dirInfo = new DirectoryInfo(dir); response.Items.Add(new PMR.IO.FileInfo() { Attribute = FileAttribute.Directory, FullPath = replaceSlash ? dir.Replace("\\", "/") : dir, LastModifiedDate = dirInfo.LastWriteTime.DayOfYear, LastModifiedTime = dirInfo.LastWriteTime.Hour, Name = Path.GetFileName(dir), }); } foreach (var file in Directory.GetFiles(path)) { System.IO.FileInfo fileInfo = new System.IO.FileInfo(file); response.Items.Add(new PMR.IO.FileInfo() { Attribute = FileAttribute.Unspecified, FullPath = replaceSlash ? file.Replace("\\", "/") : file, LastModifiedDate = fileInfo.LastWriteTime.DayOfYear, LastModifiedTime = fileInfo.LastWriteTime.Hour, Name = Path.GetFileName(file), Length = (int)fileInfo.Length, }); } } catch (Exception ex) { failed = true; msg = ex.Message; } Transporter.SendResponse(response, request.Container.Token, false, failed ? ErrorCode.GeneralError : ErrorCode.None, msg); } private void HandleFileDownloadRequest(TangoMessage request) { long length = File.Exists(request.Message.FileName) ? new System.IO.FileInfo(request.Message.FileName).Length : 0; Transporter.SendResponse(new FileDownloadResponse() { DownloadID = Guid.NewGuid().ToString(), MaxChunkLength = Math.Min(MAX_CHUNK_LENGTH, length), }, request.Container.Token, null, File.Exists(request.Message.FileName) ? ErrorCode.None : ErrorCode.FileNotFound); } private void HandleFileChunkDownloadRequest(TangoMessage request) { var message = request.Message; try { using (FileStream fs = new FileStream(message.FileName, FileMode.Open)) { fs.Position = message.Position; byte[] buffer = new byte[Math.Min(MAX_CHUNK_LENGTH, fs.Length - fs.Position)]; fs.Read(buffer, 0, buffer.Length); Transporter.SendResponse(new FileChunkDownloadResponse() { Buffer = ByteString.CopyFrom(buffer), }, request.Container.Token); } } catch (Exception ex) { Transporter.SendResponse(new FileChunkDownloadResponse() { }, request.Container.Token, null, ErrorCode.FileRequestDenied, ex.Message); } } private void HandleCreateRequest(TangoMessage request) { try { Directory.CreateDirectory(request.Message.Path); Transporter.SendResponse(new CreateResponse(), request.Container.Token); } catch (Exception ex) { Transporter.SendResponse(new CreateResponse(), request.Container.Token, null, ErrorCode.FileRequestInvalidParameter, ex.Message); } } private void HandleDeleteRequest(TangoMessage request) { try { if (request.Message.Attribute == FileAttribute.Directory) { Directory.Delete(request.Message.Path, true); } else { File.Delete(request.Message.Path); } Transporter.SendResponse(new DeleteResponse(), request.Container.Token); } catch (Exception ex) { Transporter.SendResponse(new DeleteResponse(), request.Container.Token, null, ErrorCode.FileRequestInvalidParameter, ex.Message); } } private void HandleFileUploadRequest(TangoMessage request) { var message = request.Message; _lastFileUploadRequest = message; Transporter.SendResponse(new FileUploadResponse() { MaxChunkLength = MAX_CHUNK_LENGTH, UploadID = Guid.NewGuid().ToString(), }, request.Container.Token); } private void HandleFileChunkUploadRequest(TangoMessage request) { var message = request.Message; try { using (FileStream fs = new FileStream(message.Path, FileMode.Append)) { byte[] buffer = message.Buffer.ToByteArray(); fs.Write(buffer, 0, buffer.Length); Debug.WriteLine($"Emulator file upload '{_lastFileUploadRequest.Path}' {fs.Length}/{_lastFileUploadRequest.Length} ..."); } Transporter.SendResponse(new FileChunkUploadResponse(), request.Container.Token); } catch (Exception ex) { Transporter.SendResponse(new FileChunkUploadResponse(), request.Container.Token, null, ErrorCode.GeneralError, ex.Message); } } private void HandleValidateVersionRequest(TangoMessage request) { Task.Factory.StartNew(() => { Thread.Sleep(3000); try { using (FileStream fs = new FileStream(Path.Combine(request.Message.Path, MachineOperator.FIRMWARE_UPGRADE_CONFIG_FILE_NAME), FileMode.Open)) { VersionPackageDescriptor package = VersionPackageDescriptor.Parser.ParseFrom(fs); } Transporter.SendResponse(new ValidateVersionResponse(), request.Container.Token); } catch (Exception ex) { Transporter.SendResponse(new ValidateVersionResponse(), request.Container.Token, null, ErrorCode.GeneralError, ex.Message); } }); } private void HandleActivateVersionRequest(TangoMessage request) { Task.Factory.StartNew(() => { Thread.Sleep(3000); try { using (FileStream fs = new FileStream(Path.Combine(request.Message.Path, MachineOperator.FIRMWARE_UPGRADE_CONFIG_FILE_NAME), FileMode.Open)) { VersionPackageDescriptor package = VersionPackageDescriptor.Parser.ParseFrom(fs); } Transporter.SendResponse(new ActivateVersionResponse(), request.Container.Token); } catch (Exception ex) { Transporter.SendResponse(new ActivateVersionResponse(), request.Container.Token, null, ErrorCode.GeneralError, ex.Message); } }); } #endregion #region Public Methods public async Task ValidateCartridge() { var response = await Transporter.SendRequest(new CartridgeValidationRequest() { Action = CartridgeAction.Inserted, }, TimeSpan.FromSeconds(10)); return response.Message.Index; } #endregion } }