public static Packet ReadPacket(Stream stream) { var headerBuffer = new byte[1]; var bytesRead = stream.Read(headerBuffer, 0, 1); if (bytesRead == 0) { return null; } var headerVal = (byte)(headerBuffer[0] >> 4); var payloadLength = (headerBuffer[0] & 0x0F); var packet = new Packet((PacketHeaderType)Enum.Parse(typeof(PacketHeaderType), headerVal.ToString())); var bytesRemaining = payloadLength; var offset = 0; if (payloadLength > 0) { var payloadBytes = new byte[payloadLength]; do { bytesRead = stream.Read(payloadBytes, offset, bytesRemaining); if (bytesRead == 0) { throw new XpressNetProtocolViolationException("Unexpected end of stream"); } bytesRemaining -= bytesRead; offset += bytesRead; } while (bytesRemaining > 0); packet.Payload.AddRange(payloadBytes); // .ToString() is relatively expensive, so only do it if we're logging if (XpressNetConstants.XpressNetTraceSource.Switch.ShouldTrace(TraceEventType.Verbose)) { XpressNetConstants.XpressNetTraceSource.TraceEvent(TraceEventType.Verbose, 0, "Received Packet: {0}", packet.ToString()); } if (Debugger.IsAttached) { Console.Out.WriteLineAsync(string.Format("Received Packet: {0}", packet)); } } //check the xor matches var xorByte = new byte[1]; stream.Read(xorByte, 0, 1); if (xorByte[0] != packet.GetXoredByte()) throw new XpressNetProtocolViolationException("Packet checksum is invalid"); PacketReceived(packet, stream); return packet; }
protected override bool ValidResponse(Packet packet) { if (packet.Header == PacketHeaderType.LocomotiveFunction) //TODO: unit test to check this works { ResponseData = new LocoInfoResp_NormalResp(); //TODO: if the loco is in a dh or mu it may return a different resp?! (it is probably better to modify the response to make it generic! return true; } else { return false; } }
protected override bool ValidResponse(Packet packet) { if (packet.Header == PacketHeaderType.LocomotiveFunction && (packet.Payload[0] > 0x80 && packet.Payload[0] < 0x89)) //TODO: unit test to check this works { ResponseData = new SetMultiUnitOrDoubleHeaderErrorResp(); return true; } else { return false; } }
//TODO: check that this actually happens as the specification is a little ambigous protected override bool ValidResponse(Packet packet) { if (packet.Header == PacketHeaderType.CommandStationOperationResponse && packet.Payload[0] == Convert.ToByte(PacketIdentifier.CommandStationOperationResponse.ServiceModeEntryBroadcast)) { ResponseData = new GeneralResponse(); return true; } else { return false; } }
protected override bool ValidResponse(Packet packet) { if (packet.Header == PacketHeaderType.CommandStationOperationResponse && packet.Payload[0] == Convert.ToByte(PacketIdentifier.CommandStationOperationResponse.CmdStnSoftwareVersion)) { ResponseData = new CmdStnSoftwareVersionResp(); return true; } else { return false; } }
protected override bool ValidResponse(Packet packet) { if (packet.Header == PacketHeaderType.LocomotiveFunction && (packet.Payload[0] > Convert.ToByte(PacketIdentifier.LocomotiveFunctionResponse.MultiUnitOrDoubleHeaderError) && packet.Payload[0] < (Convert.ToByte(PacketIdentifier.LocomotiveFunctionResponse.MultiUnitOrDoubleHeaderError) + 9))) //TODO: unit test to check this works { ResponseData = new SetMultiUnitOrDoubleHeaderErrorResp(); return true; } else { return false; } }
protected override bool ValidResponse(Packet packet) { if (packet.Header == PacketHeaderType.CommandStationOperationResponse && packet.Payload[0] == Convert.ToByte(PacketIdentifier.CommandStationOperationResponse.ServiceModeForRegisterAndPagedMode)) { ResponseData = new ServiceModeProgrammingResultsResp(); return true; } else if (packet.Header == PacketHeaderType.CommandStationOperationResponse && packet.Payload[0] == Convert.ToByte(PacketIdentifier.CommandStationOperationResponse.ServiceModeForDirectCvMode)) { ResponseData = new ServiceModeProgrammingResultsResp(); return true; } else if (packet.Header == PacketHeaderType.CommandStationOperationResponse && packet.Payload[0] == Convert.ToByte(PacketIdentifier.CommandStationOperationResponse.ProgrammingInfoDataByteNotFound)) { ResponseData = new GeneralResponse(); return true; } else if (packet.Header == PacketHeaderType.CommandStationOperationResponse && packet.Payload[0] == Convert.ToByte(PacketIdentifier.CommandStationOperationResponse.ProgrammingInfoShortCircuit)) { ResponseData = new GeneralResponse(); return true; } else if (packet.Header == PacketHeaderType.CommandStationOperationResponse && packet.Payload[0] == Convert.ToByte(PacketIdentifier.CommandStationOperationResponse.ProgrammingInfoCommandStationBusy)) { ResponseData = new GeneralResponse(); return true; } else if (packet.Header == PacketHeaderType.CommandStationOperationResponse && packet.Payload[0] == Convert.ToByte(PacketIdentifier.CommandStationOperationResponse.ProgrammingInfoCommandStationReady)) { ResponseData = new GeneralResponse(); return true; } else if (packet.Header == PacketHeaderType.CommandStationOperationResponse && packet.Payload[0] == Convert.ToByte(PacketIdentifier.CommandStationOperationResponse.InstructionUnsupported)) { ResponseData = new GeneralResponse(); return true; } else { return false; } }
internal async static void PacketReceived(Packet packet, Stream stream) { //Handle Direct return messages : it is possible this should be placed in the packet class! if (packet.Header == PacketHeaderType.CommandStationOperationResponse && packet.Payload[0] == Convert.ToByte(PacketIdentifier.CommandStationOperationResponse.TransferErrors)) { var ackResp = new AckRespMessage(); //if (XpressNetConstants.UseAsyncWrite) //{ // //ackResp.WriteAsync(stream); //} //else //{ await ackResp.WriteAsync(stream); //} } //Handle Broadcast Messages if (packet.Header == PacketHeaderType.EmergencyStopAll) { var bmr = new BroadcastMessageReceivedEventArgs { ResponseType = BroadcastType.EmergencyStop, ReceivedTime = DateTime.Now }; OnBroadcastMessageReceived(bmr); } else if (packet.Header == PacketHeaderType.CommandStationOperationResponse && packet.Payload[0] == Convert.ToByte(PacketIdentifier.CommandStationOperationResponse.NormalOperationsResumedBroadcast)) { var bmr = new BroadcastMessageReceivedEventArgs { ResponseType = BroadcastType.NormalOperationResumed, ReceivedTime = DateTime.Now }; OnBroadcastMessageReceived(bmr); } else if (packet.Header == PacketHeaderType.CommandStationOperationResponse && packet.Payload[0] == Convert.ToByte(PacketIdentifier.CommandStationOperationResponse.TrackPowerOffBroadcast)) { var bmr = new BroadcastMessageReceivedEventArgs { ResponseType = BroadcastType.TrackPowerOff, ReceivedTime = DateTime.Now }; OnBroadcastMessageReceived(bmr); } else if (packet.Header == PacketHeaderType.CommandStationOperationResponse && packet.Payload[0] == Convert.ToByte(PacketIdentifier.CommandStationOperationResponse.ServiceModeEntryBroadcast)) { var bmr = new BroadcastMessageReceivedEventArgs { ResponseType = BroadcastType.ServiceModeEntry, ReceivedTime = DateTime.Now }; OnBroadcastMessageReceived(bmr); } else if (packet.Header == PacketHeaderType.AccessoryDecoderInformation) { var bmr = new BroadcastMessageReceivedEventArgs { ResponseType = BroadcastType.AccessoryFeedback, ReceivedTime = DateTime.Now }; //bmr.Response = OnBroadcastMessageReceived(bmr); } //else if (packet.Header == PacketHeaderType.LocomotiveFunction && packet.Payload[0] == Convert.ToByte(PacketIdentifier.LocomotiveFunctionResponses.LocomotiveOperatedByAnotherDevice)) //{ //BroadcastMessageReceivedEventArgs bmr = new BroadcastMessageReceivedEventArgs(); //bmr.ResponseType = BroadcastType.LocomotiveOperatedByAnotherDevice; //bmr.Response = //OnBroadcastMessageReceived(bmr); //} //else if (packet.Header == PacketHeaderType.LocomotiveFunction && packet.Payload[0] == Convert.ToByte(PacketIdentifier.LocomotiveFunctionResponses.LocomotiveDoubleHeaderOccupied)) //{ //BroadcastMessageReceivedEventArgs bmr = new BroadcastMessageReceivedEventArgs(); //bmr.ResponseType = BroadcastType.DoubleHeaderOccupied; //bmr.Response = //OnBroadcastMessageReceived(bmr); //} //else //we may wish to send the broadcasts on anyway so this else may have to be removed!! //{ var pump = new PacketRouter(); pump.DisseminatePacket(packet); //} }