Inheritance: CommandFrameBase
Example #1
0
        /// <summary>
        /// Casts the parsed <see cref="IChannelFrame"/> to its specific implementation (i.e., <see cref="DataFrame"/>, <see cref="ConfigurationFrame"/> or <see cref="CommandFrame"/>).
        /// </summary>
        /// <param name="frame"><see cref="IChannelFrame"/> that was parsed by <see cref="FrameImageParserBase{TTypeIdentifier,TOutputType}"/> that implements protocol specific common frame header interface.</param>
        protected override void OnReceivedChannelFrame(IChannelFrame frame)
        {
            // Raise abstract channel frame events as a priority (i.e., IDataFrame, IConfigurationFrame, etc.)
            base.OnReceivedChannelFrame(frame);

            // Raise IEC 61850-90-5 specific channel frame events, if any have been subscribed
            if (frame != null && (ReceivedDataFrame != null || ReceivedConfigurationFrame != null || ReceivedCommandFrame != null))
            {
                DataFrame dataFrame = frame as DataFrame;

                if (dataFrame != null)
                {
                    if (ReceivedDataFrame != null)
                    {
                        ReceivedDataFrame(this, new EventArgs <DataFrame>(dataFrame));
                    }
                }
                else
                {
                    ConfigurationFrame configFrame = frame as ConfigurationFrame;

                    if (configFrame != null)
                    {
                        if (ReceivedConfigurationFrame != null)
                        {
                            ReceivedConfigurationFrame(this, new EventArgs <ConfigurationFrame>(configFrame));
                        }
                    }
                    else
                    {
                        CommandFrame commandFrame = frame as CommandFrame;

                        if (commandFrame != null)
                        {
                            if (ReceivedCommandFrame != null)
                            {
                                ReceivedCommandFrame(this, new EventArgs <CommandFrame>(commandFrame));
                            }
                        }
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Sends the specified <see cref="DeviceCommand"/> to the remote device.
        /// </summary>
        /// <param name="command"><see cref="DeviceCommand"/> to send to the remote device.</param>
        /// <remarks>
        /// Command will only be sent if <see cref="DeviceSupportsCommands"/> is <c>true</c> and <see cref="MultiProtocolFrameParser"/>.
        /// </remarks>
        /// <returns>A <see cref="WaitHandle"/>.</returns>
        public WaitHandle SendDeviceCommand(DeviceCommand command)
        {
            WaitHandle handle = null;

            try
            {
                if (m_deviceSupportsCommands && ((object)m_dataChannel != null || (object)m_serverBasedDataChannel != null || (object)m_commandChannel != null))
                {
                    ICommandFrame commandFrame;

                    // Only the IEEE, SEL Fast Message and Macrodyne protocols support commands
                    switch (m_phasorProtocol)
                    {
                        case PhasorProtocol.IEEEC37_118V2:
                        case PhasorProtocol.IEEEC37_118V1:
                        case PhasorProtocol.IEEEC37_118D6:
                            commandFrame = new IEEEC37_118.CommandFrame(m_deviceID, command, 1);
                            break;
                        case PhasorProtocol.IEEE1344:
                            commandFrame = new IEEE1344.CommandFrame(m_deviceID, command);
                            break;
                        case PhasorProtocol.IEC61850_90_5:
                            commandFrame = new IEC61850_90_5.CommandFrame(m_deviceID, command, 1);
                            break;
                        case PhasorProtocol.SelFastMessage:
                            // Get defined message period
                            MessagePeriod messagePeriod = MessagePeriod.DefaultRate;
                            SelFastMessage.ConnectionParameters connectionParameters = m_connectionParameters as SelFastMessage.ConnectionParameters;

                            if ((object)connectionParameters != null)
                                messagePeriod = connectionParameters.MessagePeriod;

                            commandFrame = new SelFastMessage.CommandFrame(command, messagePeriod);
                            break;
                        case PhasorProtocol.Macrodyne:
                            commandFrame = new Macrodyne.CommandFrame(command);
                            break;
                        default:
                            commandFrame = null;
                            break;
                    }

                    if ((object)commandFrame != null)
                    {
                        byte[] buffer = commandFrame.BinaryImage();

                        // Send command over appropriate communications channel - command channel, if defined,
                        // will take precedence over other communications channels for command traffic...
                        if ((object)m_commandChannel != null && m_commandChannel.CurrentState == ClientState.Connected)
                        {
                            handle = m_commandChannel.SendAsync(buffer, 0, buffer.Length);
                        }
                        else if ((object)m_dataChannel != null && m_dataChannel.CurrentState == ClientState.Connected)
                        {
                            handle = m_dataChannel.SendAsync(buffer, 0, buffer.Length);
                        }
                        else if ((object)m_serverBasedDataChannel != null && m_serverBasedDataChannel.CurrentState == ServerState.Running)
                        {
                            WaitHandle[] handles = m_serverBasedDataChannel.MulticastAsync(buffer, 0, buffer.Length);

                            if ((object)handles != null && handles.Length > 0)
                                handle = handles[0];
                        }

                        if ((object)SentCommandFrame != null)
                            SentCommandFrame(this, new EventArgs<ICommandFrame>(commandFrame));
                    }
                }
            }
            catch (Exception ex)
            {
                OnParsingException(ex, "Failed to send device command \"{0}\": {1}", command, ex.Message);
            }

            return handle;
        }
        /// <summary>
        /// Handles incoming commands from devices connected over the command channel.
        /// </summary>
        /// <param name="clientID">Guid of client that sent the command.</param>
        /// <param name="connectionID">Remote client connection identification (i.e., IP:Port).</param>
        /// <param name="commandBuffer">Data buffer received from connected client device.</param>
        /// <param name="length">Valid length of data within the buffer.</param>
        protected override void DeviceCommandHandler(Guid clientID, string connectionID, byte[] commandBuffer, int length)
        {
            try
            {
                // Interpret data received from a client as a command frame
                CommandFrame commandFrame = new CommandFrame(commandBuffer, 0, length);
                IServer commandChannel = (IServer)CommandChannel ?? DataChannel;

                // Validate incoming ID code if requested
                if (!m_validateIDCode || commandFrame.IDCode == this.IDCode)
                {
                    switch (commandFrame.Command)
                    {
                        case DeviceCommand.SendConfigurationFrame1:
                        case DeviceCommand.SendConfigurationFrame2:
                            if (commandChannel != null)
                            {
                                commandChannel.SendToAsync(clientID, m_configurationFrame.BinaryImage, 0, m_configurationFrame.BinaryLength);
                                OnStatusMessage(MessageLevel.Info, $"Received request for \"{commandFrame.Command}\" from \"{connectionID}\" - frame was returned.");
                            }
                            break;
                        case DeviceCommand.EnableRealTimeData:
                            // Only responding to stream control command if auto-start data channel is false
                            if (!AutoStartDataChannel)
                            {
                                StartDataChannel();
                                OnStatusMessage(MessageLevel.Info, $"Received request for \"EnableRealTimeData\" from \"{connectionID}\" - concentrator real-time data stream was started.");
                            }
                            else
                            {
                                OnStatusMessage(MessageLevel.Info, $"Request for \"EnableRealTimeData\" from \"{connectionID}\" was ignored - concentrator data channel is set for auto-start.");
                            }
                            break;
                        case DeviceCommand.DisableRealTimeData:
                            // Only responding to stream control command if auto-start data channel is false
                            if (!AutoStartDataChannel)
                            {
                                StopDataChannel();
                                OnStatusMessage(MessageLevel.Info, $"Received request for \"DisableRealTimeData\" from \"{connectionID}\" - concentrator real-time data stream was stopped.");
                            }
                            else
                            {
                                OnStatusMessage(MessageLevel.Info, $"Request for \"DisableRealTimeData\" from \"{connectionID}\" was ignored - concentrator data channel is set for auto-start.");
                            }
                            break;
                        default:
                            OnStatusMessage(MessageLevel.Info, $"Request for \"{commandFrame.Command}\" from \"{connectionID}\" was ignored - device command is unsupported.");
                            break;
                    }
                }
                else
                {
                    OnStatusMessage(MessageLevel.Warning, $"Concentrator ID code validation failed for device command \"{commandFrame.Command}\" from \"{connectionID}\" - no action was taken.");                    
                }
            }
            catch (Exception ex)
            {
                OnProcessException(MessageLevel.Warning, new InvalidOperationException($"Remotely connected device \"{connectionID}\" sent an unrecognized data sequence to the concentrator, no action was taken. Exception details: {ex.Message}", ex));
            }
        }