public static IMessage GetMessageHandler(RawMessage data) { if (data.Length < 1) { throw new IncompleteMessageException(); } // FIXME XXX TODO LOL - This logic is going to end up somewhere else, but I'll leave it here for now to refactor later MessageType msgType = (MessageType)(data.Byte(1) & ~((byte)BitField.Bit7 | (byte)BitField.Bit8)); // Check we have a class that we can instantiate to handle this MessageFactory.ReflectHandlers(); Type handlerType; if (!_messageHandlers.TryGetValue(msgType, out handlerType)) { throw new MessageNotHandledException(); } // Instantiate and hand back try { IMessage handler = (IMessage)handlerType.GetConstructor(new Type[] {}).Invoke(new object[] {}); handler.Deserialise(data); return handler; } catch { throw new MessageNotHandledException(); } }
public static int MessageLength( RawMessage data ) { if (data.Length < 2) { throw new InvalidOperationException(); } return data.Byte(0); }
public static bool isComplete( RawMessage data ) { // A valid message requires at least 4 bytes (length, number, check1, check2) if( data.Length < 4 ) { return false; } // Check that the last charachter isn't a stuffing byte if( data.Byte( data.Length - 1 ) == Constants.EncodingToken ) { return false; } // Check that we've read enough (length byte, [length] bytes, check1, check2) return (data.Length == (3 + MessageLength(data))); }
public void Deserialise(RawMessage input) { // XXX TODO FIXME DEBUG LOL - Remove the message type ID byte and checksums //this._ackRequiredFlagSet = (input.Byte(1) & (int)BitField.Bit8) == (int)BitField.Bit8; DeserialiseMessage(input); }
protected abstract void DeserialiseMessage(RawMessage input);
protected override void DeserialiseMessage(RawMessage input) { throw new NotImplementedException(); }
protected override void DeserialiseMessage(RawMessage input) { // Remember the first byte is the message id ASCIIEncoding encoding = new ASCIIEncoding(); this.firmwareVersion = encoding.GetString( input.Bytes(1, 4).ToArray() ); for (int i = 6; i <= 11; i++) { bool[] byteFlags = Util.UnpackByte(input.Byte(i-1)); switch (i) { case 6: this.supportsMessage[MessageType.InterfaceConfiguration] = byteFlags[1]; this.supportsMessage[MessageType.ZoneStatus] = byteFlags[4]; this.supportsMessage[MessageType.ZoneSnapshot] = byteFlags[5]; this.supportsMessage[MessageType.PartitionStatus] = byteFlags[6]; this.supportsMessage[MessageType.PartitionSnapshot] = byteFlags[7]; break; case 7: this.supportsMessage[MessageType.SystemStatus] = byteFlags[0]; this.supportsMessage[MessageType.X10MessageReceived] = byteFlags[1]; this.supportsMessage[MessageType.LogEvent] = byteFlags[2]; this.supportsMessage[MessageType.KeypadMessageReceived] = byteFlags[3]; break; case 8: this.supportsMessage[MessageType.InterfaceConfigurationRequest] = byteFlags[1]; this.supportsMessage[MessageType.ZoneNameRequest] = byteFlags[3]; this.supportsMessage[MessageType.ZoneStatusRequest] = byteFlags[4]; this.supportsMessage[MessageType.ZoneSnapshotRequest] = byteFlags[5]; this.supportsMessage[MessageType.PartitionStatusRequest] = byteFlags[6]; this.supportsMessage[MessageType.PartitionSnapshotRequest] = byteFlags[7]; break; case 9: this.supportsMessage[MessageType.SystemStatusRequest] = byteFlags[0]; this.supportsMessage[MessageType.SendX10Message] = byteFlags[1]; this.supportsMessage[MessageType.LogEventRequest] = byteFlags[2]; this.supportsMessage[MessageType.SendKeypadTextMessage] = byteFlags[3]; this.supportsMessage[MessageType.KeypadTerminalModeRequest] = byteFlags[4]; break; case 10: this.supportsMessage[MessageType.ProgramDataRequest] = byteFlags[0]; this.supportsMessage[MessageType.ProgramDataCommand] = byteFlags[1]; this.supportsMessage[MessageType.UserInformationRequestWithPIN] = byteFlags[2]; this.supportsMessage[MessageType.UserInformationRequestWithoutPIN] = byteFlags[3]; this.supportsMessage[MessageType.SetUserCodeCommandWithPIN] = byteFlags[4]; this.supportsMessage[MessageType.SetUserCodeCommandWithoutPIN] = byteFlags[5]; this.supportsMessage[MessageType.SetUserAuthorisationCommandWithPIN] = byteFlags[6]; this.supportsMessage[MessageType.SetUserAuthorisationCommandWithoutPIN] = byteFlags[7]; break; case 11: this.supportsMessage[MessageType.StoreCommunicationEventCommand] = byteFlags[2]; this.supportsMessage[MessageType.SetClockOrCalendarCommand] = byteFlags[3]; this.supportsMessage[MessageType.PrimaryKeypadFunctionWithPIN] = byteFlags[4]; this.supportsMessage[MessageType.PrimaryKeypadFunctionWithoutPIN] = byteFlags[5]; this.supportsMessage[MessageType.SecondaryKeypadFunction] = byteFlags[6]; this.supportsMessage[MessageType.ZoneBypassToggle] = byteFlags[7]; break; } } }
public void MainLoop() { // Initialise serial port //SerialPort serial = new SerialPort("/dev/ttyS0", 19200, Parity.None, 8, StopBits.One); SerialPort serial = new SerialPort("COM3", 19200, Parity.None, 8, StopBits.One); // Set some serial port options serial.Handshake = Handshake.None; serial.RtsEnable = false; serial.Encoding = Encoding.ASCII; // Open serial port and flush buffers serial.Open(); serial.DiscardInBuffer(); serial.DiscardOutBuffer(); // Initialise some stuff we use List<byte> curDataStream = new List<byte>(); List<RawMessage> pending = new List<RawMessage>(); List<IMessage> messages = new List<IMessage>(); Trace("Hurr: " + ((byte)Constants.ProtocolToken).ToString("X")); // Main event loop while (true) { // Read data from the serial device while (serial.BytesToRead > 0) { byte data = (byte)serial.ReadByte(); Trace("Read char: " + data.ToString("X2")); if (data == Constants.ProtocolToken ) { Trace("End of message"); Trace(dodgefmt(curDataStream)); RawMessage msg = new RawMessage(curDataStream); Trace("Message length: " + msg.Length); if (MessageFactory.isComplete(msg)) { pending.Add(msg); } else { Trace("Message incomplete"); } curDataStream = new List<byte>(); continue; } curDataStream.Add(Convert.ToByte(data)); } // Parse any finished messages foreach (RawMessage msg in pending) { Trace("Pulling message out of pending list"); IMessage messageHandler = MessageFactory.GetMessageHandler(msg); messageHandler.FireEvents(); // XXX TODO FIXME DEBUG LOL System.Console.WriteLine(messageHandler.ToString()); if (msg.AcknowledgeRequired) { byte[] data = new common.Messages.PositiveAcknowledge().Serialise().WireBytes(); Trace("Acknowledgement required, sending: " + dodgefmt(data)); serial.Write(data, 0, data.Length); } } pending.Clear(); // XXX TODO FIXME DEBUG LOL - Emit any replies back onto the wire } serial.Close(); }