package dslog; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.lang.UnsupportedOperationException; import java.time.Duration; import java.time.Instant; import java.util.stream.IntStream; class DslogReader implements Closeable { private final InputStream reader; public final int version; public final Instant startTime; private long i = 0; public DslogReader(InputStream reader) throws IOException { this.reader = reader; this.version = Read.i32(reader); switch (this.version) { case 0: // ????-???? 2012 this.startTime = Read.LVTimestamp(reader); break; case 1: // ????-???? 2014 this.startTime = Read.LVTimestamp(reader); break; case 2: // ????-2015 throw new UnsupportedOperationException("TODO: DSLOG v2 support"); case 3: // 2016-now this.startTime = Read.LVTimestamp(reader); break; default: throw new UnsupportedOperationException("DSLOG file version ("+this.version+") newer than log reader (3)"); } } public static class Entry { public Instant time; public Duration tripTime; public short lostPackets; public double voltageVolts; public double cpuPct; public boolean robotDisable, robotAuto, robotTele, dsDisable, dsAuto, dsTele, watchdog, brownout; public double canPct; public double signalDB; public double bandwidthMb; public short pdpID; public short pdpPad; public double pdpValues[]; public short pdpResistance; public short pdpVoltage; public short pdpTemperature; } /** * @see https://www.chiefdelphi.com/forums/showthread.php?t=104689 */ public Entry readEntry() throws IOException{ switch (version) { case 0: return new Entry() {{ time = startTime.plusMillis(20*i++); /* 0 = 0 */ /* 0+4= 4 */tripTime = Duration.ofNanos((long)(Read.f32(reader)*1000)); /* 4+4= 8 */voltageVolts = Read.f32(reader); /* 8+4=12 */cpuPct = Read.f32(reader); /* 12+1=13 */short bits = Read.u8(reader); robotDisable = (bits & (1<<2)) == 0; robotAuto = (bits & (1<<3)) == 0; robotTele = (bits & (1<<4)) == 0; dsDisable = (bits & (1<<5)) == 0; dsAuto = (bits & (1<<6)) == 0; dsTele = (bits & (1<<7)) == 0; /* 13+1=14 */lostPackets = Read.i8(reader); }}; case 1: return new Entry() {{ time = startTime.plusMillis(20*i++); time = startTime.plusMillis(20*i++); /* 0 = 0 */ /* 0+4= 4 */tripTime = Duration.ofNanos((long)(Read.f32(reader)*1000)); /* 4+4= 8 */voltageVolts = Read.f32(reader); /* 8+4=12 */cpuPct = Read.f32(reader); /* 12+1=13 */short bits = Read.u8(reader); robotDisable = (bits & (1<<0)) == 0; robotAuto = (bits & (1<<1)) == 0; robotTele = (bits & (1<<2)) == 0; dsDisable = (bits & (1<<3)) == 0; dsAuto = (bits & (1<<4)) == 0; dsTele = (bits & (1<<5)) == 0; /* 13+1=14 */lostPackets = Read.i8(reader); }}; case 2: throw new UnsupportedOperationException("TODO: DSLOG v2 support"); case 3: return new Entry() {{ time = startTime.plusMillis(20*i++); // Read the 35-byte structure // Read the 10 bytes of non-PDP data /* 0 = 0 */ /* 0+1= 1 */tripTime = Duration.ofNanos((long)(Util.unpack(Read.u8(reader), 7,1)*1_000_000)); /* 1+1= 2 */lostPackets = Read.u8(reader); /* 2+2= 4 */voltageVolts = Util.unpack(Read.u16(reader), 8,8); /* 5+1= 5 */cpuPct = Util.unpack(Read.u8(reader), 7,1); /* 5+1= 6 */short bits = Read.u8(reader); robotDisable = (bits & (1<<0)) == 0; robotAuto = (bits & (1<<1)) == 0; robotTele = (bits & (1<<2)) == 0; dsDisable = (bits & (1<<3)) == 0; dsAuto = (bits & (1<<4)) == 0; dsTele = (bits & (1<<5)) == 0; watchdog = (bits & (1<<6)) == 0; brownout = (bits & (1<<7)) == 0; /* 6+1= 7 */canPct = Util.unpack(Read.u8(reader), 7,1); /* 7+1= 8 */signalDB = Util.unpack(Read.u8(reader), 7,1); /* 8+2=10 */bandwidthMb = Util.unpack(Read.u16(reader), 8,8); // Read the 25 bytes of PDP data /* 0 = 0 */ /* 0+1= 1 */pdpPad = Read.u8(reader); /* 1+1= 2 */pdpID = Read.u8(reader); pdpValues = IntStream.of(Util.reverse(Util.concat( /* 2+5= 7 */ Read.u10x4(reader), /* 7+5=12 */ Read.u10x4(reader), /* 12+5=17 */ Read.u10x4(reader), /* 17+5=22 */ Read.u10x4(reader)))) .mapToDouble(i -> Util.unpack((short)i, 7,3)) .toArray(); /* 22+1=23 */pdpResistance = Read.u8(reader); /* 23+1=24 */pdpVoltage = Read.u8(reader); /* 24+1=25 */pdpTemperature = Read.u8(reader); }}; default: throw new UnsupportedOperationException("DSLOG file version newer than log reader"); } } public void close() throws IOException { reader.close(); } }