private byte[] FactoryPacket(PacketType type, byte[] data, byte[] sourcePacket) { //A Header, 2 bytes, defined as @@, ASCII code //B Length, 2 bytes, indicates the data length from Header to Tail ([Header, Tail)), statistical length range is A,B,C,D,E,F,G //C Device ID (OBDII product ID), 20 bytes, ASCII bytes. If length < 20 bytes, filled up with '\0'. //D Type, 2 bytes, high byte represents to main identifier and low byte represent to sub identifier. //E Data, random length. //F Checksum, 2 bytes, calculate from Header to Data excluding Checksum and Tail. Checksum algorithm is CRC Checksum Algorithm (see appendix), calculating range is A,B,C,D,E //G Tail, 2 bytes, defined as "\r\n". var len = (Int16)(2 + 2 + 20 + 2 + data.Length + 2 + 2); var res = new byte[len]; Encoding.ASCII.GetBytes("@@").CopyTo(res, 0); BitConverter.GetBytes(len).CopyTo(res, 2); Array.Copy(sourcePacket, 4, res, 4, 20); //Device ID BitConverter_BigEndian.GetBytes((Int16)type).CopyTo(res, 24); Array.Copy(data, 0, res, 26, data.Length); BitConverter.GetBytes(GetChecksum(res, len - 4)).CopyTo(res, len - 4); Encoding.ASCII.GetBytes("\r\n").CopyTo(res, len - 2); return(res); }
public override IMessage Decode(IFrame frame) { var chR = BitConverter_BigEndian.ToInt32(frame.Payload, frame.Payload.Length - 4); var chC = GetChecksum(frame.Payload); if (chC != chR) { STrace.Debug(GetType().FullName, Id, String.Format("Paquete descartado por checksum: checksum {0:X8}:{1:X8} {2}", chC, chR, StringUtils.MakeString(frame.Payload))); return(null); } var tipo = (PacketType)frame.Payload[0]; //var packetLenght = BitConverter_BigEndian.ToInt16(Frame.Payload, 3); var msgId = BitConverter_BigEndian.ToUInt32(frame.Payload, 5); var dt1 = (frame.Payload[11] == 0 || frame.Payload[10] == 0 || frame.Payload[9] == 0) ? DateTime.UtcNow : new DateTime(((DateTime.UtcNow.Year / 100) * 100) + frame.Payload[11], frame.Payload[10], frame.Payload[9], frame.Payload[12], frame.Payload[13], frame.Payload[14]); IMessage res; switch (tipo) { case PacketType.ReportPosition: { var data = Encoding.ASCII.GetString(frame.Payload, 15, frame.Payload.Length - 19).Split(','); var dt2 = DateTimeUtils.SafeParseFormat(data[10] + data[2].Split('.')[0], "ddMMyyHHmmss"); var lat = GPSPoint.ResampleAxis(data[4]) * ((data[5] == "N") ? 1 : -1); var lon = GPSPoint.ResampleAxis(data[6]) * ((data[7] == "E") ? 1 : -1); var vel = Speed.KnotToKm(Convert.ToSingle(data[8], CultureInfo.InvariantCulture)); var dir = Convert.ToSingle(data[9], CultureInfo.InvariantCulture); var pos = GPSPoint.Factory(dt2, lat, lon, vel, dir, 0, 0); res = pos.ToPosition(Id, msgId); var interval = BitConverter_BigEndian.GetBytes((Int16)1); //este numero multiplicado * 10'' es el intervalo de reporte var resdata = new [] { (byte)DateTime.UtcNow.Day, (byte)DateTime.UtcNow.Month, (byte)DateTime.UtcNow.Year, (byte)DateTime.UtcNow.Hour, (byte)DateTime.UtcNow.Minute, (byte)DateTime.UtcNow.Second, interval[0], interval[1] }; res.Response = FactoryResponse(PacketType.AckPosition, frame.Payload, resdata); STrace.Debug(GetType().FullName, Id, String.Format("dt {0} {1}", dt1, pos)); break; } case PacketType.ReportModbusData: { var source = frame.Payload[15]; var count = (frame.Payload.Length - Nondatalen) / Recordlen; //cantidad de bytes de los datos / 4 bytes por cada dato var sb = new StringBuilder(); for (var i = 0; i < count; i++) { var key = GetShort(frame, i, 16); var value = GetShort(frame, i, 18) * 1.0; if (key == 40108) { value /= 10; //para "Fuel Rate" el valor viene expresado en decilitros y es conveniente visualizarlo en "Litros" } if ((value != 0x8000) && (value != 0x80000000)) { sb.AppendFormat(CultureInfo.InvariantCulture, "Modbus_{0}_{1}:{2},", source, key, value); } } res = MessageIdentifier.AnalogicInputs.FactoryEvent(MessageIdentifier.TelemetricData, Id, msgId, null, dt1, null, null); ((Event)res).SensorsDataString = sb.ToString(); res.Response = FactoryResponse(PacketType.AckModbusData, frame.Payload, null); STrace.Debug(GetType().FullName, Id, String.Format("ModbusData {0} dt {1} payload {2}", sb, dt1, StringUtils.MakeString(frame.Payload))); break; } case PacketType.ReplyModbusList: //pendiente Fota.Dequeue(PacketType.Command_ModbusList) STrace.Debug(GetType().FullName, Id, String.Format("ModbusList (dt {0}) {1}", dt1, StringUtils.MakeString(frame.Payload))); res = new UserMessage(Id, msgId); break; case PacketType.RequestBiosNewPage: { STrace.Debug(GetType().FullName, Id, String.Format("BiosNewPage (dt {0}) {1}", dt1, StringUtils.MakeString(frame.Payload))); //pendiente fota de bios //var requestedpagelen = BitConverter_BigEndian.ToUInt16(Frame.Payload, 15); //var requestedpagenumber = BitConverter_BigEndian.ToUInt16(Frame.Payload, 17); //var resdata = new byte[50]; //Array.Copy(biosdata, 0, resdata, 0, 50); res = new UserMessage(Id, msgId); //res.Response = FactoryResponse(PacketType.BiosNewPage, Frame.Payload, resdata); break; } case PacketType.ReportEngineData: { var enginenum = frame.Payload[15]; var engineStateNum = frame.Payload[16]; var engineState = (EngineStates)engineStateNum; MessageIdentifier evcode; var isevent = new List <EngineStates> { EngineStates.Start, EngineStates.Stop }.Contains(engineState); if (_enginesStates.ContainsKey(enginenum) && (!isevent) && ((_enginesStates[enginenum]) == engineState)) { evcode = MessageIdentifier.AnalogicInputs; } else { if (!_enginesStates.ContainsKey(enginenum)) { _enginesStates.Add(enginenum, engineState); } switch (engineState) { case EngineStates.Start: evcode = MessageIdentifier.EngineOn; break; case EngineStates.Stop: evcode = MessageIdentifier.EngineOff; break; //case EngineStates.DataInfo: //case EngineStates.Unknown: default: evcode = MessageIdentifier.TelemetricData; break; } } var sb = new StringBuilder(); var engHours = BitConverter_BigEndian.ToUInt32(frame.Payload, 17); var fuelUsed = BitConverter_BigEndian.ToUInt32(frame.Payload, 21); var kVAhours = BitConverter_BigEndian.ToUInt32(frame.Payload, 25); var kVAhoursParcial = BitConverter_BigEndian.ToUInt32(frame.Payload, 29); var segundosRunParcial = BitConverter_BigEndian.ToUInt32(frame.Payload, 33); sb.AppendFormat(CultureInfo.InvariantCulture, "Modbus_{0}_EngineState:{1},", enginenum, engineState); if ((engHours != 0x8000) && (engHours != 0x80000000)) { sb.AppendFormat(CultureInfo.InvariantCulture, "Modbus_{0}_43587:{1},", enginenum, engHours); } if ((fuelUsed != 0x8000) && (fuelUsed != 0x80000000)) { sb.AppendFormat(CultureInfo.InvariantCulture, "Modbus_{0}_40126:{1},", enginenum, fuelUsed); } if ((kVAhours != 0x8000) && (kVAhours != 0x80000000)) { sb.AppendFormat(CultureInfo.InvariantCulture, "Modbus_{0}_43595:{1},", enginenum, kVAhours); } if ((kVAhoursParcial != 0x8000) && (kVAhoursParcial != 0x80000000)) { sb.AppendFormat(CultureInfo.InvariantCulture, "Modbus_{0}_40337:{1},", enginenum, kVAhoursParcial); } if ((segundosRunParcial != 0x8000) && (segundosRunParcial != 0x80000000)) { sb.AppendFormat(CultureInfo.InvariantCulture, "Modbus_{0}_SegundosRunParcial:{1},", enginenum, segundosRunParcial); } var res_ = evcode.FactoryEvent(MessageIdentifier.TelemetricData, Id, msgId, null, dt1, null, null); res_.SensorsDataString = sb.ToString(); STrace.Debug(GetType().FullName, Id, String.Format("EngineData: {0} Payload: {1}", res_.SensorsDataString, StringUtils.MakeString(frame.Payload))); res_.Response = FactoryResponse(PacketType.AckEngineData, frame.Payload, null); res = res_; break; } default: STrace.Debug(GetType().FullName, Id, String.Format("paquete no reconocido: {0}", StringUtils.MakeString(frame.Payload))); return(null); } //Debug.Assert(res != null); res.Tiempo = dt1; return(res); }