Example #1
0
        /// <summary>
        /// Do CAL Management  comms transaction, expecting local echo
        /// </summary>
        /// <param name="communicationChannel"></param>
        /// <param name="calCommand"></param>
        /// <returns></returns>
        bool DoCALCommsTransaction(Interface.Communication.ICommunicationChannel communicationChannel, ICBusCommand calCommand)
        {
            var rxBuffer      = new byte[128];
            var commandString = calCommand.ToCBusString();

            Logger.DebugFormat("TX {0}:{1}", calCommand, commandString);
            CBus.Protocol.CBusProtcol.SendCommand(communicationChannel, calCommand);

            Thread.Sleep(200);

            var rxLen        = communicationChannel.ReceiveBytes(rxBuffer, rxBuffer.Length);
            var rxDataString = GetReceivedString(rxBuffer, rxLen);

            if (rxDataString.StartsWith(commandString))
            {
                Logger.DebugFormat("RX:{0}", rxDataString.Substring(commandString.Length));
                return(true);
            }
            else
            {
                Logger.WarnFormat("RX:{0}", rxDataString);
                return(false);
            }
        }
Example #2
0
        protected override void OnThreadEntry(object ThreadContext)
        {
            var context  = ThreadContext as BaseThreadedDevice.ThreadContext;
            var protocol = new CBusProtcol(256);
            var rxBuffer = new byte[256];

            var keepAliveTimeout  = DateTime.Now;
            var keepAliveInterval = TimeSpan.FromSeconds(10);

            CBusSALCommand _pendingCommand = null;

            var _state = new CBusProtcol.CBusStateMachine();

            while (context.KeepRunning)
            {
                var clock = DateTime.Now;
                try
                {
                    if (!_CommunicationChannel.IsOpen)
                    {
                        if (!_CommunicationChannel.Open())
                        {
                            Thread.Sleep(500);
                        }
                        else
                        {
                            if (!PerformLogon(_CommunicationChannel))
                            {
                                Logger.WarnFormat("Logon Failed");
                                _CommunicationChannel.Close();
                            }
                            else
                            {
                                Logger.Info("Logon Success");
                            }
                        }
                    }

                    if (_CommunicationChannel.IsOpen)
                    {
                        #region Process Received Messages
                        int bytesReceived = _CommunicationChannel.ReceiveBytes(rxBuffer, rxBuffer.Length);

                        if (bytesReceived > 0)
                        {
                            var rxCharacterBufferPointer = 0;
                            var receviedCharacters       = Protocol.CBusProtcol.CharacterEncoding.GetChars(rxBuffer, 0, bytesReceived);

                            while (rxCharacterBufferPointer < receviedCharacters.Length)
                            {
                                if (protocol.TryProcessReceivedBytes(receviedCharacters, receviedCharacters.Length, ref rxCharacterBufferPointer, _state))
                                {
                                    //Log received messages
                                    if (Logger.IsDebugEnabled)
                                    {
                                        Logger.DebugFormat("State:{0}", _state);
                                        var cmdString = CBusSALCommand.BinaryArrayToHexString(_state.CommandBytes, _state.CommandLength);

                                        Logger.DebugFormat(
                                            "Rx Message:{0}", cmdString);
                                    }

                                    switch (_state.MessageType)
                                    {
                                    case CBusProtcol.CBusMessageType.ACK:
                                    {
                                        if (_state.ACK_Character.HasValue && _pendingCommand != null && _pendingCommand.AckCharacter.HasValue)
                                        {
                                            //ACK Received
                                            if (_state.ACK_Character.Value == _pendingCommand.AckCharacter.Value)
                                            {
                                                Logger.DebugFormat("Positive ACK Received");
                                                if (_pendingCommand != null)
                                                {
                                                    //When command acked, same as receiving an unsolicited message
                                                    switch (_pendingCommand.ApplicationType)
                                                    {
                                                    case CBusProtcol.ApplicationTypes.LIGHTING:
                                                        ProcessLightingMessageResponse((CBusLightingCommand)_pendingCommand);
                                                        break;

                                                    case CBusProtcol.ApplicationTypes.TRIGGER:
                                                        ProcessTriggerMessageResponse((CBusTriggerCommand)_pendingCommand);
                                                        break;
                                                    }
                                                    _pendingCommand = null;
                                                }
                                            }
                                        }
                                        break;
                                    }

                                    case CBusProtcol.CBusMessageType.NAK:
                                    case CBusProtcol.CBusMessageType.NAK_CORRUPTED:
                                    case CBusProtcol.CBusMessageType.NAK_NO_CLOCK:
                                    case CBusProtcol.CBusMessageType.NAK_MESSAGE_TOO_LONG:
                                        Logger.WarnFormat("NAK Received: {0}", _state.MessageType);
                                        _pendingCommand = null;
                                        break;

                                    case CBusProtcol.CBusMessageType.SAL_MESSAGE_RECEIVED:
                                    case CBusProtcol.CBusMessageType.MONITORED_SAL_MESSAGE_RECEIVED:
                                    {
                                        CBusSALCommand cmd;

                                        var isMonitoredSAL = (_state.MessageType == CBusProtcol.CBusMessageType.MONITORED_SAL_MESSAGE_RECEIVED);

                                        //In smart mode all messages are received in Long format
                                        var isSmartMode = (_configBuilder.Options_1 & CBusProtcol.Interface_Options_1.SMART) != 0;

                                        if (_CBusAddressMap.TryParseCommand(_state.CommandBytes, _state.CommandLength, isMonitoredSAL, !isSmartMode, out cmd))
                                        {
                                            switch (cmd.ApplicationType)
                                            {
                                            case CBusProtcol.ApplicationTypes.LIGHTING:
                                            {
                                                //Process Command
                                                var lightingCommand = (CBus.Protocol.CBusLightingCommand)cmd;
                                                ProcessLightingMessageResponse(lightingCommand);
                                                break;
                                            }

                                            case CBusProtcol.ApplicationTypes.TRIGGER:
                                            {
                                                var triggerCommand = (CBus.Protocol.CBusTriggerCommand)cmd;
                                                ProcessTriggerMessageResponse(triggerCommand);
                                                break;
                                            }

                                            default:
                                                Logger.WarnFormat("Unknown CBus application Type (Discarding), {0}", cmd.ApplicationType);
                                                break;
                                            }
                                        }
                                        else
                                        {
                                            if (Logger.IsWarnEnabled)
                                            {
                                                var cmdString = CBusSALCommand.BinaryArrayToHexString(_state.CommandBytes, _state.CommandLength);
                                                Logger.WarnFormat("Failed to process command, {0}", cmdString);
                                                Logger.WarnFormat("State:{0}", _state);
                                            }
                                        }

                                        break;
                                    }
                                    }//END: Switch

                                    //Reset state after a positive outcome
                                    _state.Reset();
                                }
                                else
                                {
                                    //No message received
                                }
                            }
                        }
                        #endregion


                        #region Tx Command
                        ICommand command = _commandQueue.Dequeue();
                        if (command != null)
                        {
                            if (command is Command.Device.LightingDeviceCommand)
                            {
                                var cmd    = (Command.Device.LightingDeviceCommand)command;
                                var preset = _presetMap.SingleOrDefault(x => x.PresetName == cmd.Preset);

                                if (preset != null)
                                {
                                    if (preset.CBusCommandType == PresetMap.CommandType.Lighting)
                                    {
                                        //byte ApplicationLightingAddress = preset.CBusApplicationId;
                                        //if (_CBusAddressMap.TryGetApplicationAddress(CBusProtcol.ApplicationTypes.LIGHTING, out ApplicationLightingAddress))
                                        {
                                            _pendingCommand = new CBus.Protocol.CBusLightingCommand(
                                                CBus.Protocol.CBusSALCommand.CBusHeader.PPM,
                                                preset.CBusApplicationId,
                                                new CBusLightingCommand.LightingCommand(
                                                    cmd.TargetState ?
                                                    CBusLightingCommand.LightingCommand.LightingCommandId.ON :
                                                    CBusLightingCommand.LightingCommand.LightingCommandId.OFF,
                                                    preset.CBusGroupAddress)
                                                );
                                        }
                                    }
                                    else if (preset.CBusCommandType == PresetMap.CommandType.Trigger)
                                    {
                                        //byte ApplicationTriggerAddress = preset.CBusApplicationId;
                                        //if (_CBusAddressMap.TryGetApplicationAddress(CBusProtcol.ApplicationTypes.TRIGGER, out ApplicationTriggerAddress))
                                        {
                                            _pendingCommand = new CBus.Protocol.CBusTriggerCommand(
                                                CBus.Protocol.CBusSALCommand.CBusHeader.PPM,
                                                preset.CBusApplicationId,

                                                new[] { new CBusTriggerCommand.TriggerCommand(preset.CBusGroupAddress, preset.CBusLevelOrAction) }

                                                );
                                        }
                                    }


                                    if (_pendingCommand != null)
                                    {
                                        _pendingCommand.AckCharacter = protocol.NextConfirmationCharacter();

                                        Logger.DebugFormat("TX {0}:{1}", _pendingCommand, _pendingCommand.ToCBusString());
                                        CBusProtcol.SendCommand(_CommunicationChannel, _pendingCommand);
                                        keepAliveTimeout = clock.Add(keepAliveInterval);
                                    }
                                }
                                else
                                {
                                    //Preset not recognised
                                }
                            }
                            else
                            {
                                //Un Supported Command
                            }
                        }
                        #endregion Tx Command
                        else
                        {
                            if (keepAliveTimeout < clock)
                            {
                                keepAliveTimeout = clock.Add(keepAliveInterval);
                                var ping = Protocol.CBusProtcol.CharacterEncoding.GetBytes("\r\n");
                                _CommunicationChannel.SendBytes(ping, ping.Length);
                                Logger.DebugFormat("Lighting Keep Alive Sent");
                            }
                            else
                            {
                                _commandQueue.Handle.WaitOne(500);
                            }
                        }
                    }
                    else
                    {
                        //Comms not open
                        Thread.Sleep(1000);
                    }
                }
                catch (ThreadInterruptedException)
                {
                    Logger.Debug("Thread Interrupted");
                }
                catch (Exception ex)
                {
                    if (ex is ThreadAbortException)
                    {
                        throw;
                    }
                    else
                    {
                        Logger.Error("Thread Error", ex);
                        Thread.Sleep(1000);
                    }
                }
            }
        }
Example #3
0
        private bool PerformLogon(Interface.Communication.ICommunicationChannel communicationChannel)
        {
            var    rxBuffer     = new byte[128];
            string rxString     = string.Empty;
            var    resetCount   = 3;
            var    resetSuccess = false;

            do
            {
                ICBusCommand calCommand = _configBuilder.ResetCommand();
                Logger.DebugFormat("TX {0}:{1}", calCommand, calCommand.ToCBusString());

                CBus.Protocol.CBusProtcol.SendCommand(communicationChannel, calCommand);
                CBus.Protocol.CBusProtcol.SendCommand(communicationChannel, calCommand);


                //Wait for response
                Thread.Sleep(200);

                var rxLen = communicationChannel.ReceiveBytes(rxBuffer, rxBuffer.Length);
                rxString = GetReceivedString(rxBuffer, rxLen);
                Logger.DebugFormat("RX:{0}", rxString);
                resetCount--;
                resetSuccess = rxString.Contains(CBus.Protocol.CBusProtcol.MODE_RESET_CHAR);
            } while (!resetSuccess && resetCount > 0);

            if (resetSuccess)
            {
                _ActiveApplications.Sort();
                for (int i = 0; i < _ActiveApplications.Count(); i++)
                {
                    var calCommand_App = _configBuilder.RegisterApplication1Monitor(_ActiveApplications[i]);
                    if (!DoCALCommsTransaction(communicationChannel, calCommand_App))
                    {
                        return(false);
                    }
                }
                var calCommand = _configBuilder.Set_CAL_Options3(CBusProtcol.Interface_Options_3.LOCAL_SAL);
                if (!DoCALCommsTransaction(communicationChannel, calCommand))
                {
                    return(false);
                }

                //See 4.3.3.1 CAL Reply, to under stand response (Long Form response as SMART selected)
                //Tx:@A3300059
                //Response: 86FAFA0032300024
                calCommand = _configBuilder.Set_CAL_Options1(
                    CBusProtcol.Interface_Options_1.CONNECT |
                    CBusProtcol.Interface_Options_1.SRCHK |
                    CBusProtcol.Interface_Options_1.SMART |
                    CBusProtcol.Interface_Options_1.IDIOM
                    );

                if (!DoCALCommsTransaction(communicationChannel, calCommand))
                {
                    return(false);
                }


                return(true);
            }


            return(false);
        }