/// <summary> /// Acknowledgment received. /// </summary> /// <param name="messageProcessing">Message processing.</param> internal static void AcknowledgmentReceived(MessageProcessDto messageProcessing) { IDevice iDevice = null; if (messageProcessing.MessageTo != null) { // configuration command if (messageProcessing.MessageTo.IsConfiguration) { iDevice = new ConfigurationBusiness(); } // constructor command else if (messageProcessing.MessageTo.IsConstructor) { iDevice = new ConstructorBusiness(); } // generic response else { var processAttr = ReflectionHelper.GetEnumValueAttribute<DeviceClassGeneric, DataReceivedAttribute>(messageProcessing.MessageTo.Node.DeviceClassGeneric); if (processAttr != null) iDevice = ReflectionHelper.CreateInstance<IDevice>(processAttr.ClassType); } // execute iDevice?.AcknowlegmentReceived(messageProcessing.MessageFrom); } }
/// <summary> /// Connect to a port. /// </summary> /// <param name="controller">Controller to connect.</param> /// <returns>Connected controller.</returns> internal static ControllerDto Connect(ControllerDto controller) { // close existing port Close(controller.Port); // connect port controller.Port = PortBusiness.Connect(controller.Port); // initialize queue Queue = new MessageProcessDto { Controller = controller }; // start listener if (Queue.TaskReceive == null) { Queue.TaskContinue = true; Queue.TaskReceive = new Task(() => ReceiveTask(Queue)); Queue.TaskReceive.Start(); } return controller; }
/// <summary> /// Send an acknowledgment. /// </summary> /// <param name="messageProcess">Message processing to use.</param> private static void SendAcknowledgment(MessageProcessDto messageProcess) { Thread.Sleep(MessageConstants.WaitForRoundTimeTrip); var message = new MessageDto { Content = new List<byte> { messageProcess.MessageFrom.IsValid ? (byte) MessageHeader.Acknowledgment : (byte) MessageHeader.NotAcknowledgment } }; PortBusiness.Send(messageProcess.Controller.Port, message); }
/// <summary> /// Process a start of frame (SOF). /// </summary> /// <param name="messageProcess">Message processing.</param> private static void ProcessFrame(MessageProcessDto messageProcess) { // special request if (messageProcess.MessageFrom.Type == MessageType.Request && messageProcess.MessageFrom.Content.Count > 1) { messageProcess.MessageFrom.Node = messageProcess.Controller.Nodes.FirstOrDefault(x => x.ZIdentifier == messageProcess.MessageFrom.ZIdentifier); } // complete received message if it's a response (SOF and ACK) else if (messageProcess.MessageTo != null) { messageProcess.MessageFrom.Node = messageProcess.MessageTo.Node; messageProcess.MessageFrom.ZIdentifier = messageProcess.MessageTo.ZIdentifier; } // Data frame (SOF) if (messageProcess.MessageFrom.Header == MessageHeader.StartOfFrame && messageProcess.MessageFrom.Node != null) { // process response if (messageProcess.MessageTo != null && messageProcess.MessageFrom.Type == MessageType.Response && messageProcess.MessageTo.Command == messageProcess.MessageFrom.Command) { DevicesBusiness.ResponseReceived(messageProcess); messageProcess.WaitMessageSending.Set(); // release message sending lock } // process request else if (messageProcess.MessageFrom.Type == MessageType.Request && messageProcess.MessageFrom.RequestCommand != RequestCommandClass.None) { DevicesBusiness.RequestReceived(messageProcess.MessageFrom); } } // ACK else { DevicesBusiness.AcknowledgmentReceived(messageProcess); } }
/// <summary> /// Called when a message is received. /// </summary> /// <param name="messageProcess">Concerned queue.</param> private static async void ReceiveTask(MessageProcessDto messageProcess) { while (messageProcess.TaskContinue) { // get reception lock messageProcess.WaitMessageReception.WaitOne(DeviceConstants.WaitEventTimeout); // get message var serialMessage = PortBusiness.Receive(messageProcess.Controller.Port); // process if (serialMessage.IsComplete) { // get message using (var ctx = new MessageProcessDtoFactory()) { messageProcess.MessageFrom = ctx.Convert(serialMessage); } // send ACK if (messageProcess.MessageFrom.Header == MessageHeader.StartOfFrame) SendAcknowledgment(messageProcess); // process received message if(messageProcess.MessageFrom.IsValid) ProcessFrame(messageProcess); } // round trip time if (serialMessage.Content.Count == 0) await Task.Delay(MessageConstants.WaitReceiveTask); // release reception & request lock messageProcess.WaitMessageReception.Set(); } }