diff --git a/.classpath b/.classpath index f619a53..530fc8a 100644 --- a/.classpath +++ b/.classpath @@ -8,16 +8,18 @@ + - + - + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index ec4300d..91ca62e 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,5 +1,14 @@ eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 -org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.source=1.7 +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/pom.xml b/pom.xml index caac5c2..1018df8 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,5 @@ - 4.0.0 @@ -21,8 +22,8 @@ maven-compiler-plugin 3.5.1 - 1.7 - 1.7 + 1.8 + 1.8 @@ -51,11 +52,10 @@ guava 18.0 - - commons-lang - commons-lang - 2.6 + com.sun.istack + istack-commons-runtime + 3.0.5 diff --git a/src/main/java/com/monstarmike/tlmreader/App.java b/src/main/java/com/monstarmike/tlmreader/App.java index e0695ec..0aaca6f 100644 --- a/src/main/java/com/monstarmike/tlmreader/App.java +++ b/src/main/java/com/monstarmike/tlmreader/App.java @@ -8,9 +8,25 @@ import org.joda.time.format.PeriodFormatter; import org.joda.time.format.PeriodFormatterBuilder; +import com.monstarmike.tlmreader.datablock.AirspeedBlock; +import com.monstarmike.tlmreader.datablock.AltitudeBlock; +import com.monstarmike.tlmreader.datablock.AltitudeZeroBlock; +import com.monstarmike.tlmreader.datablock.CurrentBlock; import com.monstarmike.tlmreader.datablock.DataBlock; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.EscBlock; +import com.monstarmike.tlmreader.datablock.FlightPackBlock; +import com.monstarmike.tlmreader.datablock.GForceBlock; +import com.monstarmike.tlmreader.datablock.GPSCollectorBlock; +import com.monstarmike.tlmreader.datablock.GPSLocationBlock; +import com.monstarmike.tlmreader.datablock.GPSStatusBlock; +import com.monstarmike.tlmreader.datablock.JetCatBlock; +import com.monstarmike.tlmreader.datablock.PowerBoxBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; +import com.monstarmike.tlmreader.datablock.ServoDataBlock; import com.monstarmike.tlmreader.datablock.StandardBlock; +import com.monstarmike.tlmreader.datablock.TemperatureBlock; +import com.monstarmike.tlmreader.datablock.VarioBlock; +import com.monstarmike.tlmreader.datablock.VoltageBlock; public class App { @@ -34,7 +50,6 @@ public static void main(String[] args) { long end = System.currentTimeMillis(); System.out.println("duration: " + (end - start) + " ms"); } catch (IOException e) { - // TODO Auto-generated catch block e.printStackTrace(); } } @@ -45,41 +60,71 @@ private static void printFlightDefinitions(IFlight flight) { } private static void printDataBlocks(Flight flight) { - int lastTimestamp = 0; for (DataBlock dataBlock : flight.getDataBlocks()) { - // if (dataBlock instanceof StandardBlock) { - // System.out.println("Timestamp: " + dataBlock.getTimestamp()); - // if (lastTimestamp >= dataBlock.getTimestamp()) { - // System.out.println( - // " ---------------- last: " + lastTimestamp + " current: " + - // dataBlock.getTimestamp()); - // } - // } - // printStandardBlock(dataBlock); - // printRxBlock(dataBlock); - } - } - - private static void printRxBlock(DataBlock dataBlock) { - if (dataBlock instanceof RXBlock) { - RXBlock rxBlock = (RXBlock) dataBlock; - System.out.println(rxBlock); - // System.out.println("A: " + rxBlock.getLostPacketsReceiverA() + ", - // B: " + rxBlock.getLostPacketsReceiverB() + ", L: " + - // rxBlock.getLostPacketsReceiverL() - // + ", R: " + rxBlock.getLostPacketsReceiverR() + ", FrameLoss: " + - // rxBlock.getFrameLoss() + ", Holds: " - // + rxBlock.getHolds()); - } - } + if (dataBlock instanceof StandardBlock) { + System.out.println(((StandardBlock) dataBlock).toString()); + } + else if (dataBlock instanceof RxBlock) { + System.out.println(((RxBlock) dataBlock).toString()); + } + else if (dataBlock instanceof VarioBlock) { + System.out.println(((VarioBlock) dataBlock).toString()); + } + //primitive data blocks + else if (dataBlock instanceof AltitudeBlock) { + System.out.println(((AltitudeBlock) dataBlock).toString()); + } + else if (dataBlock instanceof AltitudeZeroBlock) { + System.out.println(((AltitudeZeroBlock) dataBlock).toString()); + } + else if (dataBlock instanceof VoltageBlock) { + System.out.println(((VoltageBlock) dataBlock).toString()); + } + else if (dataBlock instanceof CurrentBlock) { + System.out.println(((CurrentBlock) dataBlock).toString()); + } + else if (dataBlock instanceof TemperatureBlock) { + System.out.println(((TemperatureBlock) dataBlock).toString()); + } + else if (dataBlock instanceof AirspeedBlock) { + System.out.println(((AirspeedBlock) dataBlock).toString()); + } + //other important data blocks + else if (dataBlock instanceof GPSLocationBlock) { + System.out.println(((GPSLocationBlock) dataBlock).toString()); + GPSCollectorBlock.getInstance().updateLocation((GPSLocationBlock) dataBlock); + if (GPSCollectorBlock.getInstance().isUpdated()) { + System.out.println(GPSCollectorBlock.getInstance().toString()); + } + } + else if (dataBlock instanceof GPSStatusBlock) { + System.out.println(((GPSStatusBlock) dataBlock).toString()); + GPSCollectorBlock.getInstance().updateStatus((GPSStatusBlock) dataBlock); + if (GPSCollectorBlock.getInstance().isUpdated()) { + System.out.println(GPSCollectorBlock.getInstance().toString()); + } + } + else if (dataBlock instanceof FlightPackBlock) { + System.out.println(((FlightPackBlock) dataBlock).toString()); + } + else if (dataBlock instanceof EscBlock) { + System.out.println(((EscBlock) dataBlock).toString()); + } + else if (dataBlock instanceof PowerBoxBlock) { + System.out.println(((PowerBoxBlock) dataBlock).toString()); + } + else if (dataBlock instanceof JetCatBlock) { + System.out.println(((JetCatBlock) dataBlock).toString()); + } + else if (dataBlock instanceof GForceBlock) { + System.out.println(((GForceBlock) dataBlock).toString()); + } + else if (dataBlock instanceof ServoDataBlock) { + System.out.println(((ServoDataBlock) dataBlock).toString()); + } + else //undefined dataBlocks + System.out.println(dataBlock.toString()); - private static void printStandardBlock(DataBlock dataBlock) { - if (dataBlock instanceof StandardBlock) { - StandardBlock standardBlock = (StandardBlock) dataBlock; - System.out.println("Std: rpm: " + standardBlock.getRpm() + "(" + standardBlock.hasValidRpmData() - + ") volt: " + standardBlock.getVoltageInHunderthOfVolts() + "(" - + standardBlock.hasValidVoltageData() + ") temp: " + standardBlock.getTemperatureInGradFahrenheit() - + "(" + standardBlock.hasValidTemperatureData() + ")"); } } diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/AirspeedBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/AirspeedBlock.java index 908c16c..03b9b2f 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/AirspeedBlock.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/AirspeedBlock.java @@ -4,19 +4,29 @@ public class AirspeedBlock extends DataBlock { +// typedef struct +// { +// UINT8 identifier; +// UINT8 sID; // Secondary ID +// UINT16 airspeed; // 1 km/h increments +// UINT16 maxAirspeed; // 1 km/h increments +// } STRU_TELE_SPEED; /* * Address 0x11: Airspeed * * 11.00.MSB,LSB,01,F9,00,00,00,00,00,00,00,00,00,00 MSB and LSB are a 16Bit - * value, 1 unit is 1 km/h. Displays up to 65535 km/h, maximum alarm value + * id, 1 unit is 1 km/h. Displays up to 65535 km/h, maximum alarm id * 563 km/h */ - private short airspeedKmPerHour; + private short airspeedKmPerHour; public AirspeedBlock(final byte[] rawData) { super(rawData); decode(rawData); + measurementNames.add("AirSpeed"); + measurementUnits.add("km/h"); + measurementFactors.add(1.0); } public short getAirspeedInKmPerHour() { @@ -26,12 +36,14 @@ public short getAirspeedInKmPerHour() { public boolean areValuesEquals(DataBlock block) { if (block instanceof AirspeedBlock) { AirspeedBlock air = (AirspeedBlock) block; - return air.getAirspeedInKmPerHour() == this.airspeedKmPerHour; + return air.airspeedKmPerHour == this.airspeedKmPerHour; } return false; } private void decode(byte[] rawData) { airspeedKmPerHour = Shorts.fromBytes(rawData[6], rawData[7]); + measurementValues.add((int)getAirspeedInKmPerHour()); } + } diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/AltitudeBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/AltitudeBlock.java index 1394fd7..fc6ccb2 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/AltitudeBlock.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/AltitudeBlock.java @@ -12,18 +12,29 @@ public final class AltitudeBlock extends DataBlock { * is -3276.8m */ +// typedef struct +// { +// UINT8 identifier; +// UINT8 sID; // Secondary ID +// INT16 altitude; // .1m increments +// INT16 maxAltitude; // .1m increments +// } STRU_TELE_ALT; + private short altitudeInTenthOfMeter; public AltitudeBlock(byte[] rawData) { super(rawData); decode(rawData); + measurementNames.add("Altitude A"); + measurementUnits.add("m"); + measurementFactors.add(0.1); } @Override public boolean areValuesEquals(DataBlock block) { if (block instanceof AltitudeBlock) { AltitudeBlock alt = (AltitudeBlock) block; - return alt.getAltitudeInTenthOfMeter() == this.altitudeInTenthOfMeter; + return alt.altitudeInTenthOfMeter == this.altitudeInTenthOfMeter; } return false; } @@ -34,6 +45,7 @@ public short getAltitudeInTenthOfMeter() { private void decode(byte[] rawData) { altitudeInTenthOfMeter = Shorts.fromBytes(rawData[6], rawData[7]); + measurementValues.add((int)getAltitudeInTenthOfMeter()); } } diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/AltitudeZeroBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/AltitudeZeroBlock.java new file mode 100644 index 0000000..b431092 --- /dev/null +++ b/src/main/java/com/monstarmike/tlmreader/datablock/AltitudeZeroBlock.java @@ -0,0 +1,39 @@ +package com.monstarmike.tlmreader.datablock; + +import com.google.common.primitives.Ints; + +public class AltitudeZeroBlock extends DataBlock { + +// typedef struct +// { +// UINT8 identifier; // Source device = 0x7B +// UINT8 sID; // Secondary ID +// UINT8 spare[2]; +// UINT32 altOffset; // Altitude "zero" log +// } STRU_TELE_ALT_ZERO; + + private int altOffset; + + public AltitudeZeroBlock(byte[] rawData) { + super(rawData); + altOffset = Ints.fromBytes(rawData[8], rawData[9], rawData[10], rawData[11]); + measurementNames.add("Altitude Offset"); + measurementUnits.add("m"); + measurementFactors.add(0.1); + measurementValues.add((int)getAltOffset()); + } + + @Override + public boolean areValuesEquals(DataBlock block) { + if (block instanceof AltitudeBlock) { + AltitudeZeroBlock alt = (AltitudeZeroBlock) block; + return alt.altOffset == this.altOffset; + } + return false; + } + + public int getAltOffset() { + return altOffset; + } + +} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/Block.java b/src/main/java/com/monstarmike/tlmreader/datablock/Block.java deleted file mode 100644 index 17a2835..0000000 --- a/src/main/java/com/monstarmike/tlmreader/datablock/Block.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.monstarmike.tlmreader.datablock; - -public interface Block { - int getSize(); -} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/CurrentBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/CurrentBlock.java index 2a412a6..5a16f60 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/CurrentBlock.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/CurrentBlock.java @@ -8,36 +8,36 @@ public class CurrentBlock extends DataBlock { * 1.01. * * 03,00,MSB,LSB,00,00,00,00,00,00,00,00,00,00,00,00 MSB and LSB are a 16bit - * value, 1 unit is 0.1967A, seems to be some sensor related value. You can + * id, 1 unit is 0.1967A, seems to be some sensor related id. You can * display 4 digits, I tried up to 0x2000 (displaying 1612A). Please beware - * that the maximum alarm value you can set in the radio is 200A. + * that the maximum alarm id you can set in the radio is 200A. */ - private float current; + private short current; public CurrentBlock(byte[] rawData) { super(rawData); decode(rawData); + measurementNames.add("Current C"); + measurementUnits.add("A"); + measurementFactors.add(0.1967); } @Override public boolean areValuesEquals(DataBlock block) { if (block instanceof CurrentBlock) { CurrentBlock current = (CurrentBlock) block; - return current.getCurrent() == this.current; + return current.current == this.current; } return false; } - public float getCurrent() { + public short getCurrent() { return current; } private void decode(byte[] rawData) { - current = 0.1967f * Shorts.fromBytes(rawData[6], rawData[7]); + current = Shorts.fromBytes(rawData[6], rawData[7]); + measurementValues.add((int)getCurrent()); } - @Override - public String toString() { - return super.toString() + " - " + getCurrent(); - } } diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/DataBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/DataBlock.java index d2eaa29..53e4180 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/DataBlock.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/DataBlock.java @@ -1,24 +1,125 @@ package com.monstarmike.tlmreader.datablock; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + import com.google.common.primitives.Ints; +import com.sun.istack.Nullable; + +public abstract class DataBlock implements IBlock{ + + public enum SensorType { + NODATA(0x00), // No data in packet, but telemetry is alive + VOLTAGE(0x01), // High-Voltage sensor (INTERNAL) + TEMPERATURE(0x02), // Temperature Sensor (INTERNAL) + AMPS(0x03), // Amps (INTERNAL) + FLITECTRL(0x05), // Flight Controller Status Report + PBOX(0x0A), // PowerBox + LAPTIMER(0x0B), // Lap Timer + VTX (0x0D), // Video Transmitter Feedback + AIRSPEED(0x11), // Air Speed (Eagle Tree Sensor) + ALTITUDE(0x12), // Altitude (Eagle Tree Sensor) + GMETER(0x14), // G-Force (Eagle Tree Sensor) + JETCAT(0x15), // Turbine interface (Eagle Tree) + GPS_LOC(0x16), // GPS Location Data (Eagle Tree) + GPS_STATS(0x17), // GPS Status (Eagle Tree) + RX_MAH(0x18), // Receiver Pack Capacity (Dual) + JETCAT_2(0x19), // Turbine interface, message 2 format (Eagle Tree) + GYRO(0x1A), // 3-axis gyro + ATTMAG(0x1B), // Attitude and Magnetic Compass + TILT(0x1C), // Surface Tilt Sensor + AS6X_GAIN(0x1E), // Active AS6X Gains (new mode) + AS3X_LEGACYGAIN(0x1F), // Active AS3X Gains for legacy mode + ESC(0x20), // Electronic Speed Control + FUEL(0x22), // Fuel Flow Meter + ALPHA6(0x24), // Alpha6 Stabilizer + GPS_BINARY(0x26), // GPS, binary format + FLIGHT_PACK(0x34), // Flight Battery Capacity (Dual) + DIGITAL_AIR(0x36), // Digital Inputs & Tank Pressure + STRAIN(0x38), // Thrust/Strain Gauge + LIPOMON(0x3A), // 6S Cell Monitor (LiPo taps) + LIPOMON_14(0x3F), // 14S Cell Monitor (LiPo taps) + VARIO_S(0x40), // Vario + SMARTBATT(0x42), // Spektrum SMART Battery (multiple structs) + VSPEAK(0x60), // Reserved for V-Speak + SMOKE_EL(0x61), // Reserved for Smoke-EL.de + CROSSFIRE(0x62), // Reserved for Crossfire devices + ALT_ZERO(0x7B), // Pseudo-device setting Altitude "zero" + RTC(0x7C), // Pseudo-device giving timestamp + FRAMEDATA(0x7D), // Transmitter frame data + RPM(0x7E), // RPM sensor + QOS(0x7F); // RxV + flight log data + + final int id; + final String name; + public static final SensorType VALUES[] = values(); // use this to avoid cloning if calling values() + + SensorType(int value) { + this.id = value; + this.name = this.name(); + } + + @Nullable + public static SensorType fromSensorByte(byte sensorByte) { + for (SensorType sensor : SensorType.VALUES) { + if (sensor.id == sensorByte) + return sensor; + } + return NODATA; + } -public abstract class DataBlock implements Block { + /** + * @return the id + */ + public int getId() { + return id; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + } private static int currentSeq = 0; - private int sequence = currentSeq++; - private int timestamp; + protected int sequence = currentSeq++; + protected int timestamp; + + protected List measurementNames = new ArrayList(); + protected List measurementUnits = new ArrayList(); + protected List measurementFactors = new ArrayList(); + protected List measurementValues = new ArrayList(); + + /** + * default constructor used for GPSCollectorBlock only + */ + protected DataBlock() {}; + /** + * normal constructor to be used to fill internal values like timestamp + * @param rawData + */ public DataBlock(byte[] rawData) { decode(rawData); } + + /** + * copy constructor only used in GPSCollectorBlock + * @param that + */ + protected DataBlock(DataBlock that) { + this.timestamp = that.timestamp; + this.sequence = that.sequence; + } public int getSequence() { return sequence; } - public abstract boolean areValuesEquals(DataBlock block); - /** * Timestamp in hunderth of seconds */ @@ -40,85 +141,181 @@ public static DataBlock createDataBlock(byte[] bytes, HeaderRpmBlock rpmHeaderBl break; case 0xFF: - block = new RXBlock(bytes); + block = new RxBlock(bytes); break; } } else if (bytes[4] == 0x09 && bytes[5] == 0x06) { block = new ServoDataBlock(bytes); } else { - switch (bytes[4]) { - case 0: - // unknown + switch (SensorType.fromSensorByte(bytes[4])) { + default: + case NODATA: // unknown + //System.err.println(String.format("unknown sensorByte 0x%02X", bytes[4])); break; - case 0x01: - // voltmeter - appears to be legacy. + case VOLTAGE: + block = new VoltageBlock(bytes); break; - case 0x02: - // temperature - appears to be legacy. + case TEMPERATURE: + block = new TemperatureBlock(bytes); break; - case 0x03: - // current (amperage) usage + case AMPS: // current (amperage) usage block = new CurrentBlock(bytes); break; - case 0x0a: - // powerbox - block = new PowerboxBlock(bytes); + case PBOX: // powerbox + block = new PowerBoxBlock(bytes); break; - case 0x11: - // airspeed + case AIRSPEED: // airspeed block = new AirspeedBlock(bytes); break; - case 0x12: - // altitude + case ALTITUDE: // altitude block = new AltitudeBlock(bytes); break; - case 0x14: - // g-force + case GMETER: // g-force block = new GForceBlock(bytes); break; - case 0x15: - // JetCat - block = new JetCat(bytes); + case JETCAT: // JetCatBlock + block = new JetCatBlock(bytes); break; - case 0x16: - // GPS Location Data + case GPS_LOC: // GPS Location Data block = new GPSLocationBlock(bytes); break; - case 0x17: - // GPS Status + case GPS_STATS: // GPS Status block = new GPSStatusBlock(bytes); break; - case 0x40: - // Vario + case RX_MAH: // Receiver Pack Capacity (Dual) + block = new RxPackCapacityBlock(bytes); + break; + + case VARIO_S: // Vario block = new VarioBlock(bytes); break; - case 0x7E: - // rpm, temperature, rx volts + case ESC: // Electronic Speed Control + block = new EscBlock(bytes); + break; + + case FLIGHT_PACK: // Flight Battery Capacity (Dual) + block = new FlightPackBlock(bytes); + break; + + case RPM: // rpm, temperature, rx volts, dbm_A, dbm_B block = new StandardBlock(bytes, rpmHeaderBlock); break; - case 0x7F: - // signal info - block = new RXBlock(bytes); + case ALT_ZERO: // Pseudo-device setting Altitude "zero" + block = new AltitudeZeroBlock(bytes); + break; + + case RTC: // Pseudo-device giving timestamp + block = new RtcBlock(bytes); + break; + + case FRAMEDATA: // Transmitter frame data + block = new FrameDataBlock(bytes); + break; + + case QOS: // signal info + block = new RxBlock(bytes); break; } } return block; } + /** + * helper to convert a byte array into a 2 hex character string representation to create test block content + * @param bytes + * @param size + * @return converted string + */ + public String byte2Hex2CharString(byte[] bytes, int size) { + StringBuffer sb = new StringBuffer().append("{"); + for (int i = 0; i < size; i++) { + sb.append(String.format(" (byte)0x%02X,", bytes[i])); //$NON-NLS-1$ + } + sb.setCharAt(sb.length()-1, '}'); + return sb.toString(); + } public int getSize() { return 20; } + + @Override + public List getMeasurementValues() { + return measurementValues; + } + + @Override + public List getMeasurementNames() { + return measurementNames; + } + + @Override + public List getMeasurementUnits() { + return measurementUnits; + } + + @Override + public List getMeasurementFactors() { + return measurementFactors; + } + + /** + * generic toString method for all derived BlockData classes excluding GPS related classes + */ + public String toString() { + StringBuilder sb = new StringBuilder().append(String.format(Locale.ENGLISH, "%-18s", this.getClass().getSimpleName())).append(getTimestamp()).append(" - "); + measurementNames = getMeasurementNames(); + measurementUnits = getMeasurementUnits(); + measurementFactors = getMeasurementFactors(); + measurementValues = getMeasurementValues(); + for(int i=0; i < measurementNames.size(); ++i) { + sb.append(measurementNames.get(i)) + .append(" = ") + .append(measurementFactors.get(i) != 1.0 + ? String.format(Locale.ENGLISH, "%.1f", (measurementValues.get(i) * measurementFactors.get(i))) + : String.format(Locale.ENGLISH, "%d", (int)(measurementValues.get(i) * measurementFactors.get(i)))) + .append(" ") + .append(measurementUnits.get(i)) + .append("; "); + } + return sb.toString(); + } + + /** + * generic method for all derived BlockData classes to be used as CSV export header line + */ + public String getNamesAndUnitsAsCCV() { + StringBuilder sb = new StringBuilder().append(String.format(Locale.ENGLISH, "%-18s, Time [ms],", this.getClass().getSimpleName())); + measurementNames = getMeasurementNames(); + measurementUnits = getMeasurementUnits(); + for(int i=0; i < measurementNames.size(); ++i) { + sb.append(measurementNames.get(i)).append(" [").append(measurementUnits.get(i)).append("],"); + } + return sb.toString(); + } + + /** + * generic method for all derived BlockData classes to be used as CSV export data line + */ + public String getCorrectedValuesAsCCV() { + StringBuilder sb = new StringBuilder().append(String.format(Locale.ENGLISH, "%-18s, %d,", this.getClass().getSimpleName(), getTimestamp() * 10)); + measurementValues = getMeasurementValues(); + measurementFactors = getMeasurementFactors(); + for(int i=0; i < measurementValues.size(); ++i) { + sb.append(String.format(Locale.ENGLISH, " %7.2f,", measurementValues.get(i) * measurementFactors.get(i))); + } + return sb.toString(); + } } diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/EscBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/EscBlock.java new file mode 100644 index 0000000..4a98f46 --- /dev/null +++ b/src/main/java/com/monstarmike/tlmreader/datablock/EscBlock.java @@ -0,0 +1,177 @@ +package com.monstarmike.tlmreader.datablock; + +import com.google.common.primitives.Ints; + +public class EscBlock extends DataBlock { + +//Uses big-endian byte order +// typedef struct +// { +// UINT8 identifier; // Source device = 0x20 +// UINT8 sID; // Secondary ID +// UINT16 RPM; // Electrical RPM, 10RPM (0-655340 RPM) 0xFFFF --> "No data" +// UINT16 voltsInput; // Volts, 0.01v (0-655.34V) 0xFFFF --> "No data" +// UINT16 tempFET; // Temperature, 0.1C (0-6553.4C) 0xFFFF --> "No data" +// UINT16 currentMotor; // Current, 10mA (0-655.34A) 0xFFFF --> "No data" +// UINT16 tempBEC; // Temperature, 0.1C (0-6553.4C) 0xFFFF --> "No data" +// UINT8 currentBEC; // BEC Current, 100mA (0-25.4A) 0xFF ----> "No data" +// UINT8 voltsBEC; // BEC Volts, 0.05V (0-12.70V) 0xFF ----> "No data" +// UINT8 throttle; // 0.5% (0-100%) 0xFF ----> "No data" +// UINT8 powerOut; // Power Output, 0.5% (0-127%) 0xFF ----> "No data" +// } STRU_TELE_ESC; + + private int rpmFactorThen; + private int voltsInputInHundredthOfVolt; + private int tempFETInTenthOfDegreeCelsius; + private int currentMotorInHundredthAmps; + private int tempBECInTenthOfDegreeCelsius; + private int currentBECInTenthOfAmps; + private int voltsBECInHundredthOfVolt; + private int throttleInPercent; + private int powerOutInPercent; + + public EscBlock(byte[] rawData) { + super(rawData); + decode(rawData); + + measurementNames.add("RPM ESC"); + measurementNames.add("Voltage ESC"); + measurementNames.add("TempFET ESC"); + measurementNames.add("Current ESC"); + measurementNames.add("CurrentBEC ESC"); + measurementNames.add("VoltsBEC ESC"); + measurementNames.add("Throttle ESC"); + measurementNames.add("PowerOut ESC"); + measurementNames.add("PowerIn ESC"); + + measurementUnits.add("1/min"); + measurementUnits.add("V"); + measurementUnits.add("°C"); + measurementUnits.add("A"); + measurementUnits.add("A"); + measurementUnits.add("V"); + measurementUnits.add("%"); + measurementUnits.add("%"); + measurementUnits.add("W"); + + measurementFactors.add(10.0); + measurementFactors.add(0.01); + measurementFactors.add(0.1); + measurementFactors.add(0.01); + measurementFactors.add(0.1); + measurementFactors.add(0.05); + measurementFactors.add(0.5); + measurementFactors.add(0.5); + measurementFactors.add(0.1); + } + + private void decode(byte[] rawData) { + rpmFactorThen = Ints.fromBytes((byte)0, (byte)0, rawData[6], rawData[7]); + voltsInputInHundredthOfVolt = Ints.fromBytes((byte)0, (byte)0, rawData[8], rawData[9]); + tempFETInTenthOfDegreeCelsius = Ints.fromBytes((byte)0, (byte)0, rawData[10], rawData[11]); + currentMotorInHundredthAmps = Ints.fromBytes((byte)0, (byte)0, rawData[12], rawData[13]); + tempBECInTenthOfDegreeCelsius = Ints.fromBytes((byte)0, (byte)0, rawData[14], rawData[15]); + currentBECInTenthOfAmps = rawData[16]; + voltsBECInHundredthOfVolt = rawData[17]; + throttleInPercent = rawData[18]; + powerOutInPercent = rawData[19]; + + measurementValues.add((int)getRpmFactorThen()); + measurementValues.add((int)getVoltsInputInHundredthOfVolt()); + measurementValues.add((int)getTempFETInTenthOfDegreeCelsius()); + measurementValues.add((int)getCurrentMotorInHundredthAmps()); + measurementValues.add((int)getCurrentBECInTenthOfAmps()); + measurementValues.add((int)getVoltsBECInHundredthOfVolt()); + measurementValues.add((int)getThrottleInPercent()); + measurementValues.add((int)getPowerOutInPercent()); + measurementValues.add((int)getPowerInTenthsOfW()); + } + + @Override + public boolean areValuesEquals(DataBlock block) { + if (block instanceof EscBlock) { + EscBlock esc = (EscBlock) block; + return esc.rpmFactorThen == rpmFactorThen + && esc.voltsInputInHundredthOfVolt == voltsInputInHundredthOfVolt + && esc.tempFETInTenthOfDegreeCelsius == tempFETInTenthOfDegreeCelsius + && esc.currentMotorInHundredthAmps == currentMotorInHundredthAmps + && esc.tempBECInTenthOfDegreeCelsius == tempBECInTenthOfDegreeCelsius + && esc.currentBECInTenthOfAmps == currentBECInTenthOfAmps + && esc.voltsBECInHundredthOfVolt == voltsBECInHundredthOfVolt + && esc.throttleInPercent == throttleInPercent + && esc.powerOutInPercent == powerOutInPercent; + } + return false; + } + + /** + * @return the rpmFactorThen + */ + public int getRpmFactorThen() { + return rpmFactorThen != 0xFFFF ? rpmFactorThen : 0; + } + + /** + * @return the voltsInputInHundredthOfVolt + */ + public int getVoltsInputInHundredthOfVolt() { + return voltsInputInHundredthOfVolt != 0xFFFF ? voltsInputInHundredthOfVolt : 0; + } + + /** + * @return the tempFETInTenthOfDegreeCelsius + */ + public int getTempFETInTenthOfDegreeCelsius() { + return tempFETInTenthOfDegreeCelsius != 0xFFFF ? tempFETInTenthOfDegreeCelsius : 0; + } + + /** + * @return the currentMotorInHundredthAmps + */ + public int getCurrentMotorInHundredthAmps() { + return currentMotorInHundredthAmps != 0xFFFF ? currentMotorInHundredthAmps : 0; + } + + /** + * @return the tempBECInTenthOfDegreeCelsius + */ + public int getTempBECInTenthOfDegreeCelsius() { + return tempBECInTenthOfDegreeCelsius != 0xFFFF ? tempBECInTenthOfDegreeCelsius : 0; + } + + /** + * @return the currentBECInTenthOfAmps + */ + public int getCurrentBECInTenthOfAmps() { + return currentBECInTenthOfAmps != 0xFF ? currentBECInTenthOfAmps & 0xFF: 0; + } + + /** + * @return the voltsBECInHundredthOfVolt + */ + public int getVoltsBECInHundredthOfVolt() { + return voltsBECInHundredthOfVolt != 0xFF ? voltsBECInHundredthOfVolt & 0xFF : 0; + } + + /** + * @return the throttleInPercent + */ + public int getThrottleInPercent() { + return throttleInPercent != -1 ? throttleInPercent & 0xFF : 0; + } + + /** + * @return the powerOutInPercent + */ + public int getPowerOutInPercent() { + return powerOutInPercent != 0xFF ? powerOutInPercent & 0xFF : 0; + } + + /** + * @return the powerOutInPercent + */ + public int getPowerInTenthsOfW() { + return (int) (getCurrentMotorInHundredthAmps() / 1000.0 * getVoltsInputInHundredthOfVolt()); + } + +} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/FlightPackBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/FlightPackBlock.java new file mode 100644 index 0000000..ad4d405 --- /dev/null +++ b/src/main/java/com/monstarmike/tlmreader/datablock/FlightPackBlock.java @@ -0,0 +1,125 @@ +package com.monstarmike.tlmreader.datablock; + +import com.google.common.primitives.Ints; + +public class FlightPackBlock extends DataBlock { + +// typedef struct +// { +// UINT8 identifier; // Source device = 0x34 +// UINT8 sID; // Secondary ID +// INT16 current_A; // Instantaneous current, 0.1A (0-3276.6A) +// INT16 chargeUsed_A; // Integrated mAh used, 1mAh (0-32.766Ah) +// UINT16 temp_A; // Temperature, 0.1C (0-150C, 0x7FFF indicates not populated) +// INT16 current_B; // Instantaneous current, 0.1A (0-3276.6A) +// INT16 chargeUsed_B; // Integrated mAh used, 1mAh (0-32.766Ah) +// UINT16 temp_B; // Temperature, 0.1C (0-150C, 0x7FFF indicates not populated) +// UINT16 spare; // Not used +// } STRU_TELE_FP_MAH; + + private int currentAInTenthOfAmps; + private int chargeUsedAInMilliAmpsHours; + private int temperatureAInTenthOfDegreeCelsius; + private int currentBInTenthOfAmps; + private int chargeUsedBInMilliAmpsHours; + private int temperatureBInTenthOfDegreeCelsius; + + public FlightPackBlock(byte[] rawData) { + super(rawData); + decode(rawData); + + measurementNames.add("Current FPA"); + measurementNames.add("Capacity FPA"); + measurementNames.add("Temperature FPA"); + measurementNames.add("Current FPB"); + measurementNames.add("Capacity FPB"); + measurementNames.add("Temperature FPB"); + + measurementUnits.add("A"); + measurementUnits.add("mAh"); + measurementUnits.add("°C"); + measurementUnits.add("A"); + measurementUnits.add("mAh"); + measurementUnits.add("°C"); + + measurementFactors.add(0.1); + measurementFactors.add(1.0); + measurementFactors.add(0.1); + measurementFactors.add(0.1); + measurementFactors.add(1.0); + measurementFactors.add(0.1); + } + + private void decode(byte[] rawData) { + currentAInTenthOfAmps = Ints.fromBytes((byte)0, (byte)0, rawData[7], rawData[6]); + chargeUsedAInMilliAmpsHours = Ints.fromBytes((byte)0, (byte)0, rawData[9], rawData[8]); + temperatureAInTenthOfDegreeCelsius = Ints.fromBytes((byte)0, (byte)0, rawData[11], rawData[10]); + currentBInTenthOfAmps = Ints.fromBytes((byte)0, (byte)0, rawData[13], rawData[12]); + chargeUsedBInMilliAmpsHours = Ints.fromBytes((byte)0, (byte)0, rawData[15], rawData[14]); + temperatureBInTenthOfDegreeCelsius = Ints.fromBytes((byte)0, (byte)0, rawData[17], rawData[16]); + + measurementValues.add((int)getCurrentAInTenthOfAmps()); + measurementValues.add((int)getChargeUsedAInMilliAmpsHours()); + measurementValues.add((int)getTemperatureAInTenthOfDegreeCelsius()); + measurementValues.add((int)getCurrentBInTenthOfAmps()); + measurementValues.add((int)getChargeUsedBInMilliAmpsHours()); + measurementValues.add((int)getTemperatureBInTenthOfDegreeCelsius()); +} + + @Override + public boolean areValuesEquals(DataBlock block) { + if (block instanceof FlightPackBlock) { + FlightPackBlock fp = (FlightPackBlock) block; + return fp.currentAInTenthOfAmps == currentAInTenthOfAmps + && fp.chargeUsedAInMilliAmpsHours == chargeUsedAInMilliAmpsHours + && fp.temperatureAInTenthOfDegreeCelsius == temperatureAInTenthOfDegreeCelsius + && fp.currentBInTenthOfAmps == currentBInTenthOfAmps + && fp.chargeUsedBInMilliAmpsHours == chargeUsedBInMilliAmpsHours + && fp.temperatureBInTenthOfDegreeCelsius == temperatureBInTenthOfDegreeCelsius; + } + return false; + } + + /** + * @return the currentAInTenthOfAmps + */ + public int getCurrentAInTenthOfAmps() { + return currentAInTenthOfAmps < 3000 ? currentAInTenthOfAmps : 0; + } + + /** + * @return the chargeUsedAInMilliAmpsHours + */ + public int getChargeUsedAInMilliAmpsHours() { + return chargeUsedAInMilliAmpsHours; + } + + /** + * @return the temperatureAInTenthOfDegreeCelsius + */ + public int getTemperatureAInTenthOfDegreeCelsius() { + return temperatureAInTenthOfDegreeCelsius != 0x7FFF ? temperatureAInTenthOfDegreeCelsius : 0; + } + + /** + * @return the currentBInTenthOfAmps + */ + public int getCurrentBInTenthOfAmps() { + return currentBInTenthOfAmps < 3000 ? currentBInTenthOfAmps : 0; + } + + /** + * @return the chargeUsedBInMilliAmpsHours + */ + public int getChargeUsedBInMilliAmpsHours() { + return chargeUsedBInMilliAmpsHours != 0x7FFF ? chargeUsedBInMilliAmpsHours : 0; + } + + /** + * @return the temperatureBInTenthOfDegreeCelsius + */ + public int getTemperatureBInTenthOfDegreeCelsius() { + return temperatureBInTenthOfDegreeCelsius != 0x7FFF ? temperatureBInTenthOfDegreeCelsius : 0; + } + +} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/FrameDataBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/FrameDataBlock.java new file mode 100644 index 0000000..196eb20 --- /dev/null +++ b/src/main/java/com/monstarmike/tlmreader/datablock/FrameDataBlock.java @@ -0,0 +1,19 @@ +package com.monstarmike.tlmreader.datablock; + +public class FrameDataBlock extends DataBlock { + + public FrameDataBlock(byte[] rawData) { + super(rawData); + } + + @Override + public boolean areValuesEquals(DataBlock block) { + return false; + } + + @Override + public String toString() { + return "FrameData: " + getTimestamp() + + ", unknown data structure"; + } +} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/GForceBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/GForceBlock.java index 735f77d..d077df6 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/GForceBlock.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/GForceBlock.java @@ -9,7 +9,7 @@ public class GForceBlock extends DataBlock { * 14,00,xMSB,xLSB,yMSB,zMSB,zLSB,xmaxMSB,xmaxLSB,yma * xMSB,ymaxLSB,zmaxMSB,zmaxLSB,zminMSB,zminLSB MSB/LSB are signed integers, * unit is 0.01g, on the "normal" display the last digit is rounded. maximum - * display value is +-99.90 (actually 99.99, but when it is rounded, it + * display id is +-99.90 (actually 99.99, but when it is rounded, it * overflows to 100 and displays ----) The min/max values are retained in * the sensor, because g-force cah change too quickly for the radio. * Therefore you cannot clear the min/max values on the radio. Alarm can be @@ -27,10 +27,44 @@ public class GForceBlock extends DataBlock { public GForceBlock(byte[] rawData) { super(rawData); decode(rawData); + + measurementNames.add("X GF"); + measurementNames.add("Y GF"); + measurementNames.add("Z GF"); + measurementNames.add("Xmax GF"); + measurementNames.add("Ymax GF"); + measurementNames.add("Zmax GF"); + measurementNames.add("Zmin GF"); + + measurementUnits.add("G"); + measurementUnits.add("G"); + measurementUnits.add("G"); + measurementUnits.add("G"); + measurementUnits.add("G"); + measurementUnits.add("G"); + measurementUnits.add("G"); + + measurementFactors.add(0.01); + measurementFactors.add(0.01); + measurementFactors.add(0.01); + measurementFactors.add(0.01); + measurementFactors.add(0.01); + measurementFactors.add(0.01); + measurementFactors.add(0.01); } @Override public boolean areValuesEquals(DataBlock block) { + if (block instanceof GForceBlock) { + GForceBlock gf = (GForceBlock) block; + return gf.xInHunderthOfG == xInHunderthOfG + && gf.yInHunderthOfG == yInHunderthOfG + && gf.zInHunderthOfG == zInHunderthOfG + && gf.maxXInHunderthOfG == maxXInHunderthOfG + && gf.maxYInHunderthOfG == maxYInHunderthOfG + && gf.maxZInHunderthOfG == maxZInHunderthOfG + && gf.minZInHunderthOfG == minZInHunderthOfG; + } return false; } @@ -70,5 +104,14 @@ private void decode(byte[] rawData) { maxYInHunderthOfG = Shorts.fromBytes(rawData[14], rawData[15]); maxZInHunderthOfG = Shorts.fromBytes(rawData[16], rawData[17]); minZInHunderthOfG = Shorts.fromBytes(rawData[18], rawData[19]); + + measurementValues.add((int)getXInHunderthOfG()); + measurementValues.add((int)getYInHunderthOfG()); + measurementValues.add((int)getZInHunderthOfG()); + measurementValues.add((int)getMaxXInHunderthOfG()); + measurementValues.add((int)getMaxYInHunderthOfG()); + measurementValues.add((int)getMaxZInHunderthOfG()); + measurementValues.add((int)getMinZInHunderthOfG()); } + } diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/GPSCollectorBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/GPSCollectorBlock.java new file mode 100644 index 0000000..868b3b4 --- /dev/null +++ b/src/main/java/com/monstarmike/tlmreader/datablock/GPSCollectorBlock.java @@ -0,0 +1,144 @@ +package com.monstarmike.tlmreader.datablock; + +import java.util.List; + +public class GPSCollectorBlock extends DataBlock implements IBlock { + + private static GPSCollectorBlock instance = null; + private GPSLocationBlock locationData; + private GPSStatusBlock statusData; + private boolean isUpdateLocation = false; + private boolean isUpdateStatus = false; + + + private GPSCollectorBlock() { + super(); + measurementNames.add("Altitude GPS"); + measurementNames.add("Latitude"); + measurementNames.add("Longitude"); + measurementNames.add("Speed GPS"); + measurementNames.add("Satellites GPS"); + measurementNames.add("Course"); + measurementNames.add("HDOP"); + measurementNames.add("GPSFix"); + measurementNames.add("UTC GPS"); + + measurementUnits.add("m"); + measurementUnits.add("° '"); + measurementUnits.add("° '"); + measurementUnits.add("km/h"); + measurementUnits.add("#"); + measurementUnits.add("°"); + measurementUnits.add(""); + measurementUnits.add(""); + measurementUnits.add(""); + + measurementFactors.add(0.1); //altitude + measurementFactors.add(1.0); //latitude + measurementFactors.add(1.0); //longitude + measurementFactors.add(0.1852); //speed knots -> km/h + measurementFactors.add(1.0); //numSats + measurementFactors.add(0.1); //course + measurementFactors.add(0.1); //HDOP + measurementFactors.add(1.0); //GPSFix + measurementFactors.add(1.0); //UTC + } + + public static GPSCollectorBlock getInstance() { + if (instance == null) + return instance = new GPSCollectorBlock(); + return instance; + } + + /** + * update the GPS location information + * @param block the GPS location data + */ + public void updateLocation(GPSLocationBlock block) { + locationData = new GPSLocationBlock(block); + timestamp = locationData.getTimestamp(); + sequence = locationData.getSequence(); + isUpdateLocation = true; + } + + /** + * update the GPS status information + * @param block the GPS status data + */ + public void updateStatus(GPSStatusBlock block) { + statusData = new GPSStatusBlock(block); + timestamp = statusData.getTimestamp(); + sequence = statusData.getSequence(); + isUpdateStatus = true; + } + + /** + * @return true is both GPS data blocks are updated + */ + public boolean isUpdated() { + return (locationData != null && statusData != null) && (isUpdateLocation || isUpdateStatus); + } + + /** + * legacy interface method + */ + @Override + public int getSize() { + return 0; + } + + /** + * method probably unused since GPSLocationBlock and GPSStatusBlock has such method to filter duplicates + * @param block byte array + * @return true|false if some value has been changed related to last collection + */ + @Override + public boolean areValuesEquals(DataBlock block) { + if (locationData != null && statusData != null) { + if (block instanceof GPSLocationBlock) { + return locationData.areValuesEquals(block); + } + else if (block instanceof GPSStatusBlock) { + return statusData.areValuesEquals(block); + } + } + return false; + } + + /** + * @return list of measurement names of the dedicated sensor block + */ + @Override + public List getMeasurementNames() { + return measurementNames; + } + + @Override + public List getMeasurementUnits() { + return measurementUnits; + } + + @Override + public List getMeasurementFactors() { + return measurementFactors; + } + + @Override + public List getMeasurementValues() { + measurementValues.clear(); + int altitudeInTenthOfMeter = statusData.getAltitudeHightInMeter() * 10000 + locationData.getAltitudeLowInTenthOfMeter(); + measurementValues.add((int)altitudeInTenthOfMeter); + measurementValues.add(locationData.getLatitude()); + measurementValues.add(((locationData.getFlags() & 0x04) == 0x04) ? 1000000000 + locationData.getLongitude() : locationData.getLongitude()); + measurementValues.add((int)statusData.getSpeedInTenthOfKnots()); + measurementValues.add((int)statusData.getNumSats()); + measurementValues.add((int)locationData.getCourseInTenthOfDegree()); + measurementValues.add((int)locationData.getHDOPInTenth()); + measurementValues.add((int)locationData.getGPSFix()); + measurementValues.add((int)statusData.getUTC()); + return measurementValues; + } + + + +} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/GPSLocationBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/GPSLocationBlock.java index 43451e4..e9f9a29 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/GPSLocationBlock.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/GPSLocationBlock.java @@ -1,16 +1,199 @@ package com.monstarmike.tlmreader.datablock; +import com.monstarmike.tlmreader.util.StringUtils; + public class GPSLocationBlock extends DataBlock { + +// typedef struct +// { +// UINT8 identifier; // Source device = 0x16 +// UINT8 sID; // Secondary ID +// UINT16 altitudeLow; // BCD, meters, format 3.1 (Low order of altitude) +// UINT32 latitude; // BCD, format 4.4, Degrees * 100 + minutes, less than 100 degrees +// UINT32 longitude; // BCD, format 4.4 , Degrees * 100 + minutes, flag indicates > 99 degrees +// UINT16 course; // BCD, 3.1 +// UINT8 HDOP; // BCD, format 1.1 +// UINT8 GPSflags; // see definitions below +// } STRU_TELE_GPS_LOC; + +// GPS flags definitions: +//#define GPS_INFO_FLAGS_IS_NORTH_BIT (0) +//#define GPS_INFO_FLAGS_IS_NORTH (1 << GPS_INFO_FLAGS_IS_NORTH_BIT) +//#define GPS_INFO_FLAGS_IS_EAST_BIT (1) +//#define GPS_INFO_FLAGS_IS_EAST (1 << GPS_INFO_FLAGS_IS_EAST_BIT) +//#define GPS_INFO_FLAGS_LONGITUDE_GREATER_99_BIT (2) +//#define GPS_INFO_FLAGS_LONGITUDE_GREATER_99 (1 << GPS_INFO_FLAGS_LONGITUDE_GREATER_99_BIT) +//#define GPS_INFO_FLAGS_GPS_FIX_VALID_BIT (3) +//#define GPS_INFO_FLAGS_GPS_FIX_VALID (1 << GPS_INFO_FLAGS_GPS_FIX_VALID_BIT) +//#define GPS_INFO_FLAGS_GPS_DATA_RECEIVED_BIT (4) +//#define GPS_INFO_FLAGS_GPS_DATA_RECEIVED (1 << GPS_INFO_FLAGS_GPS_DATA_RECEIVED_BIT) +//#define GPS_INFO_FLAGS_3D_FIX_BIT (5) +//#define GPS_INFO_FLAGS_3D_FIX (1 << GPS_INFO_FLAGS_3D_FIX_BIT) +//#define GPS_INFO_FLAGS_NEGATIVE_ALT_BIT (7) +//#define GPS_INFO_FLAGS_NEGATIVE_ALT (1 << GPS_INFO_FLAGS_NEGATIVE_ALT_BIT) + + private int altitudeLowInTenthOfMeter; + private int latitude; + private int longitude; + private short courseInTenthOfDegree; + private byte HDOPInTenth; + private byte flags; + public GPSLocationBlock(byte[] rawData) { super(rawData); - // TODO Auto-generated constructor stub + decode(rawData); + + measurementNames.add("Altitude low"); + measurementNames.add("Latitude"); + measurementNames.add("Longitude"); + measurementNames.add("Course"); + measurementNames.add("HDOPInTenth"); + measurementNames.add("GPSFix"); + + measurementUnits.add("m"); + measurementUnits.add("° '"); + measurementUnits.add("° '"); + measurementUnits.add("°"); + measurementUnits.add(""); + measurementUnits.add(""); + + measurementFactors.add(0.1); + measurementFactors.add(1.0); + measurementFactors.add(1.0); + measurementFactors.add(0.1); + measurementFactors.add(0.1); + measurementFactors.add(1.0); + } + + public GPSLocationBlock(GPSLocationBlock that) { + super(that); + this.altitudeLowInTenthOfMeter = that.altitudeLowInTenthOfMeter; + this.latitude = that.latitude; + this.longitude = that.longitude; + this.courseInTenthOfDegree = that.courseInTenthOfDegree; + this.HDOPInTenth = that.HDOPInTenth; + this.flags = that.flags; + } + + /** + * @return the altitudeLowInMeter + */ + public int getAltitudeLowInTenthOfMeter() { + return altitudeLowInTenthOfMeter; + } + + /** + * @return the latitude + */ + public int getLatitude() { + return latitude; + } + + /** + * @return the latitude converted in decimals + */ + public float getLatitudeInDecimals() { + int grad = latitude / 1000000; + float minuten = (latitude - (grad * 1000000)) / 10000.0f; + return grad + minuten / 60.0f; + } + + /** + * @return the longitude converted in decimals + */ + public float getLongitudeInDecimals() { + int grad = longitude / 1000000; + float minuten = (longitude - (grad * 1000000)) / 10000.0f; + return grad + minuten / 60.0f; + } + + /** + * @return the longitude + */ + public int getLongitude() { + return longitude; + } + + /** + * @return the courseInTenthOfDegree + */ + public short getCourseInTenthOfDegree() { + return courseInTenthOfDegree; + } + + /** + * @return the HDOPInTenth + */ + public byte getHDOPInTenth() { + return HDOPInTenth; + } + + /** + * @return the flags + */ + public byte getFlags() { + return flags; + } + + /** + * @return the GPS fix, 2 for 2D, 3 for 3D fix + */ + public int getGPSFix() { + if (((flags & 0x08) == 0x08) && ((flags & 0x20) == 0x20)) + return 3; + else if ((flags & 0x08) == 0x08) + return 2; + return 0; + //return ((flags & 0x20) == 0x20) ? 3 : ((flags & 0x08) == 0x08) ? 2 : 0; + } + + private void decode(final byte[] rawData) { + altitudeLowInTenthOfMeter = Integer.parseInt(StringUtils.bcdEncodeInverted(rawData, 6, 2)); + latitude = Integer.parseInt(StringUtils.bcdEncodeInverted(rawData, 8, 4)); + longitude = Integer.parseInt(StringUtils.bcdEncodeInverted(rawData, 12, 4)); + courseInTenthOfDegree = Short.parseShort(StringUtils.bcdEncodeInverted(rawData, 16, 2)); + HDOPInTenth = Byte.parseByte(StringUtils.bcdEncodeInverted(rawData, 18, 1)); + flags = rawData[19]; + + measurementValues.add(((getFlags() & 0x80) == 0x80) ? -1 * getAltitudeLowInTenthOfMeter() : getAltitudeLowInTenthOfMeter()); + measurementValues.add(getLatitude()); + measurementValues.add(((getFlags() & 0x04) == 0x04) ? 1000000000 + getLongitude() : getLongitude()); + measurementValues.add((int)getCourseInTenthOfDegree()); + measurementValues.add((int)getHDOPInTenth()); + measurementValues.add(getGPSFix()); } @Override public boolean areValuesEquals(DataBlock block) { - // TODO Auto-generated method stub + if (block instanceof GPSLocationBlock) { + GPSLocationBlock gpsLoc = (GPSLocationBlock) block; + return gpsLoc.altitudeLowInTenthOfMeter == altitudeLowInTenthOfMeter + && gpsLoc.latitude == latitude + && gpsLoc.longitude == longitude + && gpsLoc.courseInTenthOfDegree == courseInTenthOfDegree + && gpsLoc.HDOPInTenth == HDOPInTenth + && gpsLoc.flags == flags; + } return false; } + @Override + public String toString() { + return "GPSLocationData: " + getTimestamp() + + " - Altitude low = " + (((getFlags() & 0x80) == 0x80) ? -1 * getAltitudeLowInTenthOfMeter() : getAltitudeLowInTenthOfMeter()) / 10.0 + + ", Latitude = " + getLatitudeInDecimals() + + ", Longitude = " + getLongitudeInDecimals() + + ", Course = " + getCourseInTenthOfDegree() / 10.0 + + ", HDOP = " + (getHDOPInTenth() & 0xFF) / 10.0 + + ", GPSFix = " + getGPSFix() + + ", IS_NORTH = " + ((getFlags() & 0x01) == 0x01) + + ", IS_EAST = " + ((getFlags() & 0x02) == 0x02) + + ", LONGITUDE_GREATER_99 = " + ((getFlags() & 0x04) == 0x04) + //+ ", GPS fix = " + ((getFlags() & 0x08) == 0x08) + //+ ", GPS_DATA_RECEIVED = " + ((getFlags() & 0x10) == 0x10) + //+ ", GPS 3D fix = " + ((getFlags() & 0x20) == 0x20) + //+ ", NEGATIVE_ALT = " + ((getFlags() & 0x80) == 0x80) + ; + } } diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/GPSStatusBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/GPSStatusBlock.java index f2369f3..adaff8c 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/GPSStatusBlock.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/GPSStatusBlock.java @@ -1,16 +1,120 @@ package com.monstarmike.tlmreader.datablock; +import java.util.Locale; + +import com.monstarmike.tlmreader.util.StringUtils; + public class GPSStatusBlock extends DataBlock { +// typedef struct +// { +// UINT8 identifier; // Source device = 0x17 +// UINT8 sID; // Secondary ID +// UINT16 speed; // BCD, knots, format 3.1 +// UINT32 UTC; // BCD, format HH:MM:SS.S, format 6.1 +// UINT8 numSats; // BCD, 0-99 +// UINT8 altitudeHigh; // BCD, meters, format 2.0 (High order of altitude) +// } STRU_TELE_GPS_STAT; + private short speedInKnots; + private int UTC; + private byte numSats; + private short altitudeHightInMeter; + public GPSStatusBlock(byte[] rawData) { super(rawData); - // TODO Auto-generated constructor stub + decode(rawData); + + measurementNames.add("Speed GPS"); + measurementNames.add("UTC GPS"); + measurementNames.add("Satellites GPS"); + measurementNames.add("Altitude GPShigh"); + + measurementUnits.add("Knots"); + measurementUnits.add(""); + measurementUnits.add("#"); + measurementUnits.add("m"); + + measurementFactors.add(0.1); + measurementFactors.add(1.0); + measurementFactors.add(1.0); + measurementFactors.add(1.0); + } + + public GPSStatusBlock(GPSStatusBlock that) { + super(that); + this.speedInKnots = that.speedInKnots; + this.UTC = that.UTC; + this.numSats = that.numSats; + this.altitudeHightInMeter = that.altitudeHightInMeter; + } + + private void decode(final byte[] rawData) { + speedInKnots = Short.parseShort(StringUtils.bcdEncodeInverted(rawData, 6, 2)); + UTC = Integer.parseInt(StringUtils.bcdEncodeInverted(rawData, 8, 4)); + numSats = Byte.parseByte(StringUtils.bcdEncodeInverted(rawData, 12, 1)); + altitudeHightInMeter = Short.parseShort(StringUtils.bcdEncodeInverted(rawData, 13, 1)); + + measurementValues.add((int)getSpeedInTenthOfKnots()); + measurementValues.add((int)getUTC()); + measurementValues.add((int)getNumSats()); + measurementValues.add((int)getAltitudeHightInMeter()); } @Override public boolean areValuesEquals(DataBlock block) { - // TODO Auto-generated method stub + if (block instanceof GPSStatusBlock) { + GPSStatusBlock gpsStatus = (GPSStatusBlock) block; + return gpsStatus.speedInKnots == speedInKnots + && gpsStatus.UTC == UTC + && gpsStatus.numSats == numSats + && gpsStatus.altitudeHightInMeter == altitudeHightInMeter; + } return false; } + /** + * @return the speedInKnots + */ + public short getSpeedInTenthOfKnots() { + return speedInKnots; + } + + /** + * @return the UTC + */ + public int getUTC() { + return UTC; + } + + /** + * @return the UTC as string representation + */ + public String getUTCString() { + String utc = "" + UTC; + return utc.length() == 8 ? utc.substring(0, 2) + ":" + utc.substring(2, 4) + ":" + utc.substring(4, 6) + "." + utc.substring(6, 8) : "00:00:00.00"; + } + + /** + * @return the numSats + */ + public byte getNumSats() { + return numSats; + } + + /** + * @return the altitudeHightInMeter + */ + public short getAltitudeHightInMeter() { + return altitudeHightInMeter; + } + + @Override + public String toString() { + return "GPSStatusData: " + getTimestamp() + + " - speedInKnots = " + String.format(Locale.ENGLISH, "%.1f", getSpeedInTenthOfKnots() * 0.1) + + ", UTC = " + getUTCString() + + ", numSats = " + getNumSats() + + ", altitudeHightInMeter = " + getAltitudeHightInMeter(); + } + } diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/HeaderBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/HeaderBlock.java index 7bf69cc..66eb52c 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/HeaderBlock.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/HeaderBlock.java @@ -3,7 +3,7 @@ import com.monstarmike.tlmreader.datablock.normalizer.DataNormalizer; import com.monstarmike.tlmreader.datablock.normalizer.NoneNormalizer; -public abstract class HeaderBlock implements Block { +public abstract class HeaderBlock { public static boolean isHeaderBlock(byte[] bytes) { return bytes[0] == bytes[1] && bytes[1] == bytes[2] diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/HeaderNameBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/HeaderNameBlock.java index a92660c..00771f9 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/HeaderNameBlock.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/HeaderNameBlock.java @@ -59,7 +59,7 @@ private void decode(byte[] rawData) { while (offset < 0x24 && rawData[offset] != 0x0) { offset++; } - modelName = new String(Arrays.copyOfRange(rawData, 0x0C, offset)).trim(); + modelName = new String(Arrays.copyOfRange(rawData, 0x0A, offset)).trim(); modelNumber = (byte) (((byte) rawData[0x4]) + 1); } diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/IBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/IBlock.java new file mode 100644 index 0000000..b51024d --- /dev/null +++ b/src/main/java/com/monstarmike/tlmreader/datablock/IBlock.java @@ -0,0 +1,40 @@ +package com.monstarmike.tlmreader.datablock; + +import java.util.List; + +public interface IBlock { + + String toString(); + + /** + * @return data byte array size + */ + int getSize(); + + /** + * @param block byte array + * @return true|false if some value has been changed related to last collection + */ + boolean areValuesEquals(DataBlock block); + + /** + * @return list of measurement names of the dedicated sensor block + */ + List getMeasurementNames(); + + /** + * @return list of measurement units of the dedicated sensor block + */ + List getMeasurementUnits(); + + /** + * @return list of measurement factors of the dedicated sensor block + */ + List getMeasurementFactors(); + + /** + * @return list of measurement raw values of the dedicated sensor block + */ + List getMeasurementValues(); + +} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/JetCat.java b/src/main/java/com/monstarmike/tlmreader/datablock/JetCat.java deleted file mode 100644 index b414247..0000000 --- a/src/main/java/com/monstarmike/tlmreader/datablock/JetCat.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.monstarmike.tlmreader.datablock; - -import com.google.common.primitives.Ints; -import com.google.common.primitives.Shorts; - -public final class JetCat extends DataBlock { - public enum ECUStatus { - - } - - public enum OffStatus { - - } - - private byte rawECUStatus; - private byte throttlePercentage; - private double packVoltage; - private double pumpVoltage; - private int rpm; - private short egt; - private byte rawOffCondition; - - public byte getRawECUStatus() { - return this.rawECUStatus; - } - - public byte getThrottlePercentage() { - return this.throttlePercentage; - } - - public double getPackVoltage() { - return this.packVoltage; - } - - public double getPumpVoltage() { - return this.pumpVoltage; - } - - public int getRPM(){ - return this.rpm; - } - - public short getEGT() { - return this.egt; - } - - public byte getRawOffCondition() { - return this.rawOffCondition; - } - - public JetCat(byte[] rawData) { - super(rawData); - decode(rawData); - } - - private void decode(byte[] rawData) { - rawECUStatus = rawData[6]; - throttlePercentage = rawData[7]; - packVoltage = (rawData[8] * 100D) + (rawData[9] / 100D); - pumpVoltage = (rawData[10] * 100D) + (rawData[11] / 100D); - rpm = Ints.fromBytes(rawData[12], rawData[13], rawData[14], rawData[15]); - egt = Shorts.fromBytes(rawData[16], rawData[17]); - rawOffCondition = rawData[18]; - } - - @Override - public boolean areValuesEquals(DataBlock block) { - // TODO Auto-generated method stub - return false; - } -} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/JetCatBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/JetCatBlock.java new file mode 100644 index 0000000..c18bf96 --- /dev/null +++ b/src/main/java/com/monstarmike/tlmreader/datablock/JetCatBlock.java @@ -0,0 +1,328 @@ +package com.monstarmike.tlmreader.datablock; + +import com.google.common.primitives.Ints; +import com.google.common.primitives.Shorts; +import com.sun.istack.Nullable; + +public final class JetCatBlock extends DataBlock { + +// typedef struct +// { +// UINT8 identifier; // Source device = 0x15 +// UINT8 sID; // Secondary ID +// UINT8 status; // Table below +// UINT8 throttle; // (BCD) xx Percent +// UINT16 packVoltage; // (BCD) xx.yy +// UINT16 pumpVoltage; // (BCD) xx.yy +// UINT32 RPM; // (BCD) +// UINT16 EGT; // (BCD) Temperature, Celsius +// UINT8 offCondition; // Table below +// UINT8 spare; +// } STRU_TELE_JETCAT; + + enum JETCAT_ECU_TURBINE_STATE { // ECU Status definitions + JETCAT_ECU_STATE_OFF(0x00), + JETCAT_ECU_STATE_WAIT_for_RPM(0x01), // (Stby/Start) + JETCAT_ECU_STATE_Ignite(0x02), + JETCAT_ECU_STATE_Accelerate(0x03), + JETCAT_ECU_STATE_Stabilise(0x04), + JETCAT_ECU_STATE_Learn_HI(0x05), + JETCAT_ECU_STATE_Learn_LO(0x06), + JETCAT_ECU_STATE_UNDEFINED(0x07), + JETCAT_ECU_STATE_Slow_Down(0x08), + JETCAT_ECU_STATE_Manual(0x09), + JETCAT_ECU_STATE_AutoOff(0x10), + JETCAT_ECU_STATE_Run(0x11), // (reg.) + JETCAT_ECU_STATE_Accleleration_delay(0x12), + JETCAT_ECU_STATE_SpeedReg(0x13), // (Speed Ctrl) + JETCAT_ECU_STATE_Two_Shaft_Regulate(0x14), // (only for secondary shaft) + JETCAT_ECU_STATE_PreHeat1(0x15), + JETCAT_ECU_STATE_PreHeat2(0x16), + JETCAT_ECU_STATE_MainFStart(0x17), + JETCAT_ECU_STATE_NotUsed(0x18), + JETCAT_ECU_STATE_KeroFullOn(0x19), + // undefined states 0x1A-0x1F + EVOJET_ECU_STATE_off(0x20), + EVOJET_ECU_STATE_ignt(0x21), + EVOJET_ECU_STATE_acce(0x22), + EVOJET_ECU_STATE_run(0x23), + EVOJET_ECU_STATE_cal(0x24), + EVOJET_ECU_STATE_cool(0x25), + EVOJET_ECU_STATE_fire(0x26), + EVOJET_ECU_STATE_glow(0x27), + EVOJET_ECU_STATE_heat(0x28), + EVOJET_ECU_STATE_idle(0x29), + EVOJET_ECU_STATE_lock(0x2A), + EVOJET_ECU_STATE_rel(0x2B), + EVOJET_ECU_STATE_spin(0x2C), + EVOJET_ECU_STATE_stop(0x2D), + // undefined states 0x2E-0x2F + HORNET_ECU_STATE_OFF(0x30), + HORNET_ECU_STATE_SLOWDOWN(0x31), + HORNET_ECU_STATE_COOL_DOWN(0x32), + HORNET_ECU_STATE_AUTO(0x33), + HORNET_ECU_STATE_AUTO_HC(0x34), + HORNET_ECU_STATE_BURNER_ON(0x35), + HORNET_ECU_STATE_CAL_IDLE(0x36), + HORNET_ECU_STATE_CALIBRATE(0x37), + HORNET_ECU_STATE_DEV_DELAY(0x38), + HORNET_ECU_STATE_EMERGENCY(0x39), + HORNET_ECU_STATE_FUEL_HEAT(0x3A), + HORNET_ECU_STATE_FUEL_IGNITE(0x3B), + HORNET_ECU_STATE_GO_IDLE(0x3C), + HORNET_ECU_STATE_PROP_IGNITE(0x3D), + HORNET_ECU_STATE_RAMP_DELAY(0x3E), + HORNET_ECU_STATE_RAMP_UP(0x3F), + HORNET_ECU_STATE_STANDBY(0x40), + HORNET_ECU_STATE_STEADY(0x41), + HORNET_ECU_STATE_WAIT_ACC(0x42), + HORNET_ECU_STATE_ERROR(0x43), + // undefined states 0x44-0x4F + XICOY_ECU_STATE_Temp_High(0x50), + XICOY_ECU_STATE_Trim_Low(0x51), + XICOY_ECU_STATE_Set_Idle(0x52), + XICOY_ECU_STATE_Ready(0x53), + XICOY_ECU_STATE_Ignition(0x54), + XICOY_ECU_STATE_Fuel_Ramp(0x55), + XICOY_ECU_STATE_Glow_Test(0x56), + XICOY_ECU_STATE_Running(0x57), + XICOY_ECU_STATE_Stop(0x58), + XICOY_ECU_STATE_Flameout(0x59), + XICOY_ECU_STATE_Speed_Low(0x5A), + XICOY_ECU_STATE_Cooling(0x5B), + XICOY_ECU_STATE_Igniter_Bad(0x5C), + XICOY_ECU_STATE_Starter_F(0x5D), + XICOY_ECU_STATE_Weak_Fuel(0x5E), + XICOY_ECU_STATE_Start_On(0x5F), + XICOY_ECU_STATE_Pre_Heat(0x60), + XICOY_ECU_STATE_Battery(0x61), + XICOY_ECU_STATE_Time_Out(0x62), + XICOY_ECU_STATE_Overload(0x63), + XICOY_ECU_STATE_Igniter_Fail(0x64), + XICOY_ECU_STATE_Burner_On(0x65), + XICOY_ECU_STATE_Starting(0x66), + XICOY_ECU_STATE_SwitchOver(0x67), + XICOY_ECU_STATE_Cal_Pump(0x68), + XICOY_ECU_STATE_Pump_Limit(0x69), + XICOY_ECU_STATE_No_Engine(0x6A), + XICOY_ECU_STATE_Pwr_Boost(0x6B), + XICOY_ECU_STATE_Run_Idle(0x6C), + XICOY_ECU_STATE_Run_Max(0x6D), + // undefined states 0x6e-0x73 + JETCENT_ECU_STATE_STOP(0x74), + JETCENT_ECU_STATE_GLOW_TEST(0x75), + JETCENT_ECU_STATE_STARTER_TEST(0x76), + JETCENT_ECU_STATE_PRIME_FUEL(0x77), + JETCENT_ECU_STATE_PRIME_BURNER(0x78), + JETCENT_ECU_STATE_MAN_COOL(0x79), + JETCENT_ECU_STATE_AUTO_COOL(0x7A), + JETCENT_ECU_STATE_IGN_HEAT(0x7B), + JETCENT_ECU_STATE_IGNITION(0x7C), + JETCENT_ECU_STATE_PREHEAT(0x7D), + JETCENT_ECU_STATE_SWITCHOVER(0x7E), + JETCENT_ECU_STATE_TO_IDLE(0x7F), + JETCENT_ECU_STATE_RUNNING(0x80), + JETCENT_ECU_STATE_STOP_ERROR(0x81), + // undefined states 0x82-0x8F + SWIWIN_ECU_STATE_STOP(0x90), + SWIWIN_ECU_STATE_READY(0x91), + SWIWIN_ECU_STATE_IGNITION(0x92), + SWIWIN_ECU_STATE_PREHEAT(0x93), + SWIWIN_ECU_STATE_FUEL_RAMP(0x94), + SWIWIN_ECU_STATE_RUNNING(0x95), + SWIWIN_ECU_STATE_COOLING(0x96), + SWIWIN_ECU_STATE_RESTART_SWOVER(0x97), + SWIWIN_ECU_STATE_NOTUSED(0x98), + // undefined states 0x99-0x9F + + TURBINE_ECU_MAX_STATE(0x9F); + + private byte id; + public static final JETCAT_ECU_TURBINE_STATE VALUES[] = values(); // use this to avoid cloning if calling values() + + JETCAT_ECU_TURBINE_STATE(int newId) { + this.id = (byte) newId; + } + + @Nullable + JETCAT_ECU_TURBINE_STATE fromStateByte(int stateByte) { + for (JETCAT_ECU_TURBINE_STATE tmpState : VALUES) { + if (tmpState.id == stateByte) + return tmpState; + } + return null; + } + + }; + + enum JETCAT_ECU_OFF_CONDITIONS { // ECU off conditions. Valid only when the ECUStatus = JETCAT_ECU_STATE_OFF + JETCAT_ECU_OFF_No_Off_Condition_defined, + JETCAT_ECU_OFF_Shut_down_via_RC, + JETCAT_ECU_OFF_Overtemperature, + JETCAT_ECU_OFF_Ignition_timeout, + JETCAT_ECU_OFF_Acceleration_time_out, + JETCAT_ECU_OFF_Acceleration_too_slow, + JETCAT_ECU_OFF_Over_RPM, + JETCAT_ECU_OFF_Low_Rpm_Off, + JETCAT_ECU_OFF_Low_Battery, + JETCAT_ECU_OFF_Auto_Off, + JETCAT_ECU_OFF_Low_temperature_Off, + JETCAT_ECU_OFF_Hi_Temp_Off, + JETCAT_ECU_OFF_Glow_Plug_defective, + JETCAT_ECU_OFF_Watch_Dog_Timer, + JETCAT_ECU_OFF_Fail_Safe_Off, + JETCAT_ECU_OFF_Manual_Off, // (via GSU) + JETCAT_ECU_OFF_Power_fail, // (Battery fail) + JETCAT_ECU_OFF_Temp_Sensor_fail, // (only during startup) + JETCAT_ECU_OFF_Fuel_fail, + JETCAT_ECU_OFF_Prop_fail, + JETCAT_ECU_OFF_2nd_Engine_fail, + JETCAT_ECU_OFF_2nd_Engine_Diff_Too_High, + JETCAT_ECU_OFF_2nd_Engine_No_Comm, + JETCAT_ECU_MAX_OFF_COND, + // Jet Central + JETCENT_ECU_OFF_No_Off_Condition_defined, // ECU off conditions. Valid only when the ECUStatus = JETCENT_ECU_STATE_STOP or JETCENT_ECU_STATE_STOP_ERROR or JETCENT_ECU_STATE_RUNNING + JETCENT_ECU_OFF_IGNITION_ERROR, + JETCENT_ECU_OFF_PREHEAT_ERROR, + JETCENT_ECU_OFF_SWITCHOVER_ERROR, + JETCENT_ECU_OFF_STARTER_MOTOR_ERROR, + JETCENT_ECU_OFF_TO_IDLE_ERROR, + JETCENT_ECU_OFF_ACCELERATION_ERROR, + JETCENT_ECU_OFF_IGNITER_BAD, + JETCENT_ECU_OFF_MIN_PUMP_OK, + JETCENT_ECU_OFF_MAX_PUMP_OK, + JETCENT_ECU_OFF_LOW_RX_BATTERY, + JETCENT_ECU_OFF_LOW_ECU_BATTERY, + JETCENT_ECU_OFF_NO_RX, + JETCENT_ECU_OFF_TRIM_DOWN, + JETCENT_ECU_OFF_TRIM_UP, + JETCENT_ECU_OFF_FAILSAFE, + JETCENT_ECU_OFF_FULL, + JETCENT_ECU_OFF_RX_SETUP_ERROR, + JETCENT_ECU_OFF_TEMP_SENSOR_ERROR, + JETCENT_ECU_OFF_COM_TURBINE_ERROR, + JETCENT_ECU_OFF_MAX_TEMP, + JETCENT_ECU_OFF_MAX_AMPS, + JETCENT_ECU_OFF_LOW_RPM, + JETCENT_ECU_OFF_ERROR_RPM_SENSOR, + JETCENT_ECU_OFF_MAX_PUMP, + JETCENT_ECU_MAX_OFF_COND; + + public static final JETCAT_ECU_OFF_CONDITIONS VALUES[] = values(); // use this to avoid cloning if calling values() + + @Nullable + JETCAT_ECU_OFF_CONDITIONS fromOrdinal(int ordinal) { + if (ordinal >= 0 && ordinal < VALUES.length) + return VALUES[ordinal]; + + return null; + } + } + + public enum ECUStatus { + + } + + public enum OffStatus { + + } + + private byte rawECUStatus; + private byte throttlePercentage; + private double packVoltage; + private double pumpVoltage; + private int rpm; + private short egt; + private byte rawOffCondition; + + public byte getRawECUStatus() { + return this.rawECUStatus; + } + + public byte getThrottlePercentage() { + return this.throttlePercentage; + } + + public double getPackVoltage() { + return this.packVoltage; + } + + public double getPumpVoltage() { + return this.pumpVoltage; + } + + public int getRPM(){ + return this.rpm; + } + + public short getEGT() { + return this.egt; + } + + public byte getRawOffCondition() { + return this.rawOffCondition; + } + + public JetCatBlock(byte[] rawData) { + super(rawData); + decode(rawData); + + measurementNames.add("RawECUStatus JC"); + measurementNames.add("Throttle JC"); + measurementNames.add("PackVoltage JC"); + measurementNames.add("PumpVoltage JC"); + measurementNames.add("RPM JC"); + measurementNames.add("EGT JC"); + measurementNames.add("RawOffCondition JC"); + + measurementUnits.add(""); + measurementUnits.add("%"); + measurementUnits.add("V"); + measurementUnits.add("V"); + measurementUnits.add("1/min"); + measurementUnits.add(""); + measurementUnits.add(""); + + measurementFactors.add(1.0); + measurementFactors.add(1.0); + measurementFactors.add(1.0); + measurementFactors.add(1.0); + measurementFactors.add(1.0); + measurementFactors.add(1.0); + measurementFactors.add(1.0); + } + + private void decode(byte[] rawData) { + rawECUStatus = rawData[6]; + throttlePercentage = rawData[7]; + packVoltage = (rawData[8] * 100D) + (rawData[9] / 100D); + pumpVoltage = (rawData[10] * 100D) + (rawData[11] / 100D); + rpm = Ints.fromBytes(rawData[12], rawData[13], rawData[14], rawData[15]); + egt = Shorts.fromBytes(rawData[16], rawData[17]); + rawOffCondition = rawData[18]; + + measurementValues.add((int)getRawECUStatus()); + measurementValues.add((int)getThrottlePercentage()); + measurementValues.add((int)getPackVoltage()); + measurementValues.add((int)getPumpVoltage()); + measurementValues.add((int)getRPM()); + measurementValues.add((int)getEGT()); + measurementValues.add((int)getRawOffCondition()); + } + + @Override + public boolean areValuesEquals(DataBlock block) { + if (block instanceof JetCatBlock) { + JetCatBlock jcat = (JetCatBlock) block; + return jcat.rawECUStatus == rawECUStatus + && jcat.throttlePercentage == throttlePercentage + && jcat.packVoltage == packVoltage + && jcat.pumpVoltage == pumpVoltage + && jcat.rpm == rpm + && jcat.egt == egt + && jcat.rawOffCondition == rawOffCondition; + } + return false; + } + +} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/PowerBoxBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/PowerBoxBlock.java new file mode 100644 index 0000000..5d3c716 --- /dev/null +++ b/src/main/java/com/monstarmike/tlmreader/datablock/PowerBoxBlock.java @@ -0,0 +1,120 @@ +package com.monstarmike.tlmreader.datablock; + +import com.google.common.primitives.Shorts; + +public class PowerBoxBlock extends DataBlock { + +// typedef struct +// { +// UINT8 identifier; // Source device = 0x0A +// UINT8 sID; // Secondary ID +// UINT16 volt1; // Volts, 0.01v +// UINT16 volt2; // Volts, 0.01v +// UINT16 capacity1; // mAh, 1mAh +// UINT16 capacity2; // mAh, 1mAh +// UINT16 spare16_1; +// UINT16 spare16_2; +// UINT8 spare; +// UINT8 alarms; // Alarm bitmask (see below) +// } STRU_TELE_POWERBOX; +// + /* + * Address 0a: Powerbox. Very useful ! + * + * 0a,00,V1MSB,V1LSB,V2MSB,V2LSB,Cap1MSB,Cap1LSB,Cap2 + * MSB,Cap2LSB,00,00,00,00,00,Alarm You can display 2 voltages and 2 used + * capacities. Voltage scale 1 unit is 0.01V, capacity 1 unit is 1mAh. Alarm + * has to be triggered by the sensor, it is transmitted to the radio with + * the last byte, the first 4 bits. The fist bit is alarm V1, the second V2, + * the third Capacity 1, the 4th capacity 2. This sensor is nearly perfect + * for a used capacity sensor, with the drawback that the alarm id must + * be set in the sensor . You can enable or disable an alarm for each id, + * but not set the id. + */ + + //private static byte TELE_PBOX_ALARM_VOLTAGE_1 = 0x01; + //private static byte TELE_PBOX_ALARM_VOLTAGE_2 = 0x02; + //private static byte TELE_PBOX_ALARM_CAPACITY_1 = 0x04; + //private static byte TELE_PBOX_ALARM_CAPACITY_2 = 0x08; + //private static byte TELE_PBOX_ALARM_RPM = 0x10; + //private static byte TELE_PBOX_ALARM_TEMPERATURE = 0x20; + //private static byte TELE_PBOX_ALARM_RESERVED_1 = 0x40; + //private static byte TELE_PBOX_ALARM_RESERVED_2 = 0x80; + + private short voltageOneInHunderthOfVolts; + private short voltageTwoInHunderthOfVolts; + private short capacityOneInmAh; + private short capacityTwoInmAh; + private byte alarms; + + public PowerBoxBlock(byte[] rawData) { + super(rawData); + decode(rawData); + + measurementNames.add("Voltage PB1"); + measurementNames.add("Capacity PB1"); + measurementNames.add("Voltage PB2"); + measurementNames.add("Capacity PB2"); + measurementNames.add("Alarms PB"); + + measurementUnits.add("V"); + measurementUnits.add("mAh"); + measurementUnits.add("V"); + measurementUnits.add("mAh"); + measurementUnits.add(""); + + measurementFactors.add(0.01); + measurementFactors.add(1.0); + measurementFactors.add(0.01); + measurementFactors.add(1.0); + measurementFactors.add(1.0); + } + + @Override + public boolean areValuesEquals(DataBlock block) { + if (block instanceof PowerBoxBlock) { + PowerBoxBlock powerbox = (PowerBoxBlock) block; + return powerbox.voltageOneInHunderthOfVolts == voltageOneInHunderthOfVolts + && powerbox.voltageTwoInHunderthOfVolts == voltageTwoInHunderthOfVolts + && powerbox.capacityOneInmAh == capacityOneInmAh + && powerbox.capacityTwoInmAh == capacityTwoInmAh + && powerbox.getAlarms() == (short)(alarms & 0xFF); + } + return false; + } + + public short getVoltageOneInHunderthOfVolts() { + return voltageOneInHunderthOfVolts; + } + + public short getVoltageTwoInHunderthOfVolts() { + return voltageTwoInHunderthOfVolts; + } + + public short getCapacityOneInmAh() { + return capacityOneInmAh; + } + + public short getCapacityTwoInmAh() { + return capacityTwoInmAh; + } + + public short getAlarms() { + return (short) (alarms & 0xFF); + } + + private void decode(byte[] rawData) { + voltageOneInHunderthOfVolts = Shorts.fromBytes(rawData[6], rawData[7]); + voltageTwoInHunderthOfVolts = Shorts.fromBytes(rawData[8], rawData[9]); + capacityOneInmAh = Shorts.fromBytes(rawData[10], rawData[11]); + capacityTwoInmAh = Shorts.fromBytes(rawData[12], rawData[13]); + alarms = rawData[15]; + + measurementValues.add((int)getVoltageOneInHunderthOfVolts()); + measurementValues.add((int)getCapacityOneInmAh()); + measurementValues.add((int)getVoltageTwoInHunderthOfVolts()); + measurementValues.add((int)getCapacityTwoInmAh()); + measurementValues.add((int)getAlarms()); + } + +} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/PowerboxBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/PowerboxBlock.java deleted file mode 100644 index ab787e9..0000000 --- a/src/main/java/com/monstarmike/tlmreader/datablock/PowerboxBlock.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.monstarmike.tlmreader.datablock; - -import com.google.common.primitives.Shorts; - -public class PowerboxBlock extends DataBlock { - - /* - * Address 0a: Powerbox. Very useful ! - * - * 0a,00,V1MSB,V1LSB,V2MSB,V2LSB,Cap1MSB,Cap1LSB,Cap2 - * MSB,Cap2LSB,00,00,00,00,00,Alarm You can display 2 voltages and 2 used - * capacities. Voltage scale 1 unit is 0.01V, capacity 1 unit is 1mAh. Alarm - * has to be triggered by the sensor, it is transmitted to the radio with - * the last byte, the first 4 bits. The fist bit is alarm V1, the second V2, - * the third Capacity 1, the 4th capacity 2. This sensor is nearly perfect - * for a used capacity sensor, with the drawback that the alarm value must - * be set in the sensor . You can enable or disable an alarm for each value, - * but not set the value. - */ - - private short voltageOneInHunderthOfVolts; - private short voltageTwoInHunderthOfVolts; - private short capacityOneInmAh; - private short capacityTwoInmAh; - - public PowerboxBlock(byte[] rawData) { - super(rawData); - decode(rawData); - } - - @Override - public boolean areValuesEquals(DataBlock block) { - if (block instanceof PowerboxBlock) { - PowerboxBlock powerbox = (PowerboxBlock) block; - if (powerbox.getVoltageOneInHunderthOfVolts() != voltageOneInHunderthOfVolts) { - return false; - } - if (powerbox.getVoltageOneInHunderthOfVolts() != voltageTwoInHunderthOfVolts) { - return false; - } - if (powerbox.getCapacityOneInmAh() != capacityOneInmAh) { - return false; - } - if (powerbox.getCapacityTwoInmAh() != capacityTwoInmAh) { - return false; - } - return true; - } - return false; - } - - public short getVoltageOneInHunderthOfVolts() { - return voltageOneInHunderthOfVolts; - } - - public short getVoltageTwoInHunderthOfVolts() { - return voltageTwoInHunderthOfVolts; - } - - public short getCapacityOneInmAh() { - return capacityOneInmAh; - } - - public short getCapacityTwoInmAh() { - return capacityTwoInmAh; - } - - private void decode(byte[] rawData) { - voltageOneInHunderthOfVolts = Shorts.fromBytes(rawData[6], rawData[7]); - voltageTwoInHunderthOfVolts = Shorts.fromBytes(rawData[8], rawData[9]); - capacityOneInmAh = Shorts.fromBytes(rawData[10], rawData[11]); - capacityTwoInmAh = Shorts.fromBytes(rawData[12], rawData[13]); - } - - @Override - public String toString() { - return super.toString() + " - V1: " + getVoltageOneInHunderthOfVolts() + " Capacity 1: " + getCapacityOneInmAh() + " - V2: " - + getVoltageTwoInHunderthOfVolts() + " Capacity 2: " + getCapacityTwoInmAh(); - } -} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/RXBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/RXBlock.java deleted file mode 100644 index 3af7d35..0000000 --- a/src/main/java/com/monstarmike/tlmreader/datablock/RXBlock.java +++ /dev/null @@ -1,185 +0,0 @@ -package com.monstarmike.tlmreader.datablock; - -import com.google.common.primitives.Shorts; - -/** - *

Spectrum DSM2/DSMX Telemetry System - Data interpretation

The Values - * of a, b, l ,r are number packetLoss of the each receiver.
- * It looks like, that Spectrum uses unsigned short data types, because the - * 0xffff (unsigned shortMaxValue) seems to be the value if no receiver is - * installed. I assume, that always the highest value of the datatype is the - * value for 'no data'. - * - *

Lemon DSM2/DSMX Telemetry Systen - Data interpretation

However the - * Lemon unit does use the “A” display for a Signal Indicator value. This is - * calculated from the number of packets lost in transmission. A reading of 100 - * means that no packets have been lost in transmission, while smaller numbers - * indicate losses.
- * The value is based on the number of packets received about every half second. - *
- * Quote from 'docs/InstructionsTelemetry A4.pdf' , page 6, section - * "Accuracy and Limitations" subsection "Signal Indicator"
- *
- * The values b,l,r,frameloss,holds are not used.
- * The not used values are 32768 (0x8000) == Short.MIN_VALUE.
- * It gives me the appearance, that Lemon is using signed short, with - * Short.MIN_VALUE for invalid values. Some DataBlocks contains negativ values, - * I consider them as invalid too. - */ - -public class RXBlock extends DataBlock { - - private short lostPacketsReceiverA; - private short lostPacketsReceiverB; - private short lostPacketsReceiverL; - private short lostPacketsReceiverR; - private short frameLoss; - private short holds; - private short voltageInHunderthOfVolts; - - public RXBlock(final byte[] rawData) { - super(rawData); - decode(rawData); - } - - @Override - public boolean areValuesEquals(DataBlock block) { - if (block instanceof RXBlock) { - RXBlock rx = (RXBlock) block; - if (rx.getLostPacketsReceiverA() != getLostPacketsReceiverA()) { - return false; - } - if (rx.getLostPacketsReceiverB() != getLostPacketsReceiverB()) { - return false; - } - if (rx.getLostPacketsReceiverL() != getLostPacketsReceiverL()) { - return false; - } - if (rx.getLostPacketsReceiverR() != getLostPacketsReceiverR()) { - return false; - } - if (rx.getFrameLoss() != getFrameLoss()) { - return false; - } - if (rx.getHolds() != getHolds()) { - return false; - } - if (rx.getVoltageInHunderthOfVolts() != getVoltageInHunderthOfVolts() ) { - return false; - } - return true; - } - return false; - } - - private void decode(final byte[] rawData) { - lostPacketsReceiverA = Shorts.fromBytes(rawData[0x06], rawData[0x07]); - lostPacketsReceiverB = Shorts.fromBytes(rawData[0x08], rawData[0x09]); - lostPacketsReceiverL = Shorts.fromBytes(rawData[0x0A], rawData[0x0B]); - lostPacketsReceiverR = Shorts.fromBytes(rawData[0x0C], rawData[0x0D]); - frameLoss = Shorts.fromBytes(rawData[0x0E], rawData[0x0F]); - holds = Shorts.fromBytes(rawData[0x10], rawData[0x11]); - voltageInHunderthOfVolts = Shorts.fromBytes(rawData[0x12], rawData[0x13]); - } - - private boolean isValidData(short value) { - return value >= 0; - } - - public boolean hasValidDataLostPacketsReceiverA() { - return isValidData(getLostPacketsReceiverA()); - } - - /** - * @return If Spectrum Telemetry System is used, the value shows - * LostDataPackets on the receiver.
- * If Lemon Telemetry System is used, the value is 100 if all is ok, - * less if packets are lost. - */ - public short getLostPacketsReceiverA() { - return lostPacketsReceiverA; - } - - public boolean hasValidDataLostPacketsReceiverB() { - return isValidData(getLostPacketsReceiverB()); - } - - /** - * @return If Spectrum Telemetry System is used, the value shows - * LostDataPackets on the receiver.
- * If Lemon Telemetry System is used, the value is not used - */ - public short getLostPacketsReceiverB() { - return lostPacketsReceiverB; - } - - public boolean hasValidDataLostPacketsReceiverL() { - return isValidData(getLostPacketsReceiverL()); - } - - /** - * @return If Spectrum Telemetry System is used, the value shows - * LostDataPackets on the receiver.
- * If Lemon Telemetry System is used, the value is not used - */ - public short getLostPacketsReceiverL() { - return lostPacketsReceiverL; - } - - public boolean hasValidDataLostPacketsReceiverR() { - return isValidData(getLostPacketsReceiverR()); - } - - /** - * @return If Spectrum Telemetry System is used, the value shows - * LostDataPackets on the receiver.
- * If Lemon Telemetry System is used, the value is not used - */ - public short getLostPacketsReceiverR() { - return lostPacketsReceiverR; - } - - public boolean hasValidFrameLosssData() { - return isValidData(getFrameLoss()); - } - - /** - * @return If Spectrum Telemetry System is used, the value shows lost - * frames.
- * If Lemon Telemetry System is used, the value is not used. - */ - public short getFrameLoss() { - return frameLoss; - } - - public boolean hasValidHoldsData() { - return isValidData(getHolds()); - } - - /** - * @return If Spectrum Telemetry System is used, the value shows holds.
- * If Lemon Telemetry System is used, the value is not used. - */ - public short getHolds() { - return holds; - } - - /** - * @return Returns the voltage in hunderth of Volt of the receiver. - */ - public short getVoltageInHunderthOfVolts() { - return voltageInHunderthOfVolts; - } - - @Override - public String toString() { - return "RxData: " + getTimestamp() + ", LostPacketsReceiver A: " + getLostPacketsReceiverA() + " (" - + hasValidDataLostPacketsReceiverA() + "), B: " + getLostPacketsReceiverB() + " (" - + hasValidDataLostPacketsReceiverB() + "), L: " + getLostPacketsReceiverL() + " (" - + hasValidDataLostPacketsReceiverL() + "), R: " + getLostPacketsReceiverR() + " (" - + hasValidDataLostPacketsReceiverR() + "), FrameLoss: " + getFrameLoss() + "(" - + hasValidFrameLosssData() + ") , Holds: " + getHolds() + "(" + hasValidHoldsData() + "), Volts: " - + getVoltageInHunderthOfVolts(); - } - -} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/RtcBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/RtcBlock.java new file mode 100644 index 0000000..2d64851 --- /dev/null +++ b/src/main/java/com/monstarmike/tlmreader/datablock/RtcBlock.java @@ -0,0 +1,27 @@ +package com.monstarmike.tlmreader.datablock; + +public class RtcBlock extends DataBlock { + +// typedef struct +// { +// UINT8 identifier; // Source device = 0x7C +// UINT8 sID; // Secondary ID +// UINT8 spare[6]; +// UINT64 UTC64; // Linux 64-bit time_t for post-2038 date compatibility +// } STRU_TELE_RTC; + + public RtcBlock(byte[] rawData) { + super(rawData); + } + + @Override + public boolean areValuesEquals(DataBlock block) { + return false; + } + + @Override + public String toString() { + return "RtcData: " + getTimestamp() + + ", not used data structure"; + } +} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/RxBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/RxBlock.java new file mode 100644 index 0000000..cd629bb --- /dev/null +++ b/src/main/java/com/monstarmike/tlmreader/datablock/RxBlock.java @@ -0,0 +1,204 @@ +package com.monstarmike.tlmreader.datablock; + +import com.google.common.primitives.Shorts; + +/** + *

Spectrum DSM2/DSMX Telemetry System - Data interpretation

The Values + * of a, b, l ,r are number packetLoss of the each receiver.
+ * It looks like, that Spectrum uses unsigned short data types, because the + * 0xffff (unsigned shortMaxValue) seems to be the id if no receiver is + * installed. I assume, that always the highest id of the datatype is the + * id for 'no data'. + * + *

Lemon DSM2/DSMX Telemetry Systen - Data interpretation

However the + * Lemon unit does use the “A” display for a Signal Indicator id. This is + * calculated from the number of packets lost in transmission. A reading of 100 + * means that no packets have been lost in transmission, while smaller numbers + * indicate losses.
+ * The id is based on the number of packets received about every half second. + *
+ * Quote from 'docs/InstructionsTelemetry A4.pdf' , page 6, section + * "Accuracy and Limitations" subsection "Signal Indicator"
+ *
+ * The values b,l,r,frameloss,holds are not used.
+ * The not used values are 32768 (0x8000) == Short.MIN_VALUE.
+ * It gives me the appearance, that Lemon is using signed short, with + * Short.MIN_VALUE for invalid values. Some DataBlocks contains negativ values, + * I consider them as invalid too. + */ + +public class RxBlock extends DataBlock { + +// typedef struct +// { +// UINT8 identifier; // Source device = 0x7F +// UINT8 sID; // Secondary ID +// UINT16 A; // Internal/base receiver fades. 0xFFFF = "No data" +// UINT16 B; // Remote receiver fades. 0xFFFF = "No data" +// UINT16 L; // Third receiver fades. 0xFFFF = "No data" +// UINT16 R; // Fourth receiver fades. 0xFFFF = "No data" +// UINT16 F; // Frame losses. 0xFFFF = "No data" +// UINT16 H; // Holds. 0xFFFF = "No data" +// UINT16 rxVoltage; // Volts, .01V increment. 0xFFFF = "No data" +// } STRU_TELE_QOS; + + private short lostPacketsReceiverA; + private short lostPacketsReceiverB; + private short lostPacketsReceiverL; + private short lostPacketsReceiverR; + private short frameLoss; + private short holds; + private short voltageInHunderthOfVolts; + + public RxBlock(final byte[] rawData) { + super(rawData); + decode(rawData); + + measurementNames.add("LostPacketsReceiver A"); + measurementNames.add("LostPacketsReceiver B"); + measurementNames.add("LostPacketsReceiver L"); + measurementNames.add("LostPacketsReceiver R"); + measurementNames.add("FrameLoss"); + measurementNames.add("Holds"); + measurementNames.add("VoltageRx"); + + measurementUnits.add(""); + measurementUnits.add(""); + measurementUnits.add(""); + measurementUnits.add(""); + measurementUnits.add(""); + measurementUnits.add(""); + measurementUnits.add("V"); + + measurementFactors.add(1.0); + measurementFactors.add(1.0); + measurementFactors.add(1.0); + measurementFactors.add(1.0); + measurementFactors.add(1.0); + measurementFactors.add(1.0); + measurementFactors.add(0.01); + } + + @Override + public boolean areValuesEquals(DataBlock block) { + if (block instanceof RxBlock) { + RxBlock rx = (RxBlock) block; + return rx.voltageInHunderthOfVolts == getVoltageInHunderthOfVolts() + && rx.lostPacketsReceiverA == getLostPacketsReceiverA() + && rx.lostPacketsReceiverB == getLostPacketsReceiverB() + && rx.lostPacketsReceiverL == getLostPacketsReceiverL() + && rx.lostPacketsReceiverR == getLostPacketsReceiverR() + && rx.frameLoss == getFrameLoss() + && rx.holds == getHolds(); + } + return false; + } + + private void decode(final byte[] rawData) { + lostPacketsReceiverA = Shorts.fromBytes(rawData[0x06], rawData[0x07]); + lostPacketsReceiverB = Shorts.fromBytes(rawData[0x08], rawData[0x09]); + lostPacketsReceiverL = Shorts.fromBytes(rawData[0x0A], rawData[0x0B]); + lostPacketsReceiverR = Shorts.fromBytes(rawData[0x0C], rawData[0x0D]); + frameLoss = Shorts.fromBytes(rawData[0x0E], rawData[0x0F]); + holds = Shorts.fromBytes(rawData[0x10], rawData[0x11]); + voltageInHunderthOfVolts = Shorts.fromBytes(rawData[0x12], rawData[0x13]); + + measurementValues.add((int)getLostPacketsReceiverA()); + measurementValues.add((int)getLostPacketsReceiverB()); + measurementValues.add((int)getLostPacketsReceiverL()); + measurementValues.add((int)getLostPacketsReceiverR()); + measurementValues.add((int)getFrameLoss()); + measurementValues.add((int)getHolds()); + measurementValues.add((int)getVoltageInHunderthOfVolts()); + } + + private boolean isValidData(short value) { + return value >= 0; + } + + public boolean hasValidDataLostPacketsReceiverA() { + return isValidData(lostPacketsReceiverA); + } + + /** + * @return If Spectrum Telemetry System is used, the id shows + * LostDataPackets on the receiver.
+ * If Lemon Telemetry System is used, the id is 100 if all is ok, + * less if packets are lost. + */ + public short getLostPacketsReceiverA() { + return (lostPacketsReceiverA & 0xF000) < 1 ? lostPacketsReceiverA : 0; + } + + public boolean hasValidDataLostPacketsReceiverB() { + return isValidData(lostPacketsReceiverB); + } + + /** + * @return If Spectrum Telemetry System is used, the id shows + * LostDataPackets on the receiver.
+ * If Lemon Telemetry System is used, the id is not used + */ + public short getLostPacketsReceiverB() { + return (lostPacketsReceiverB & 0xF000) < 1 ? lostPacketsReceiverB : 0; + } + + public boolean hasValidDataLostPacketsReceiverL() { + return isValidData(lostPacketsReceiverL); + } + + /** + * @return If Spectrum Telemetry System is used, the id shows + * LostDataPackets on the receiver.
+ * If Lemon Telemetry System is used, the id is not used + */ + public short getLostPacketsReceiverL() { + return (lostPacketsReceiverL & 0xF000) < 1 ? lostPacketsReceiverL : 0; + } + + public boolean hasValidDataLostPacketsReceiverR() { + return isValidData(lostPacketsReceiverR); + } + + /** + * @return If Spectrum Telemetry System is used, the id shows + * LostDataPackets on the receiver.
+ * If Lemon Telemetry System is used, the id is not used + */ + public short getLostPacketsReceiverR() { + return (lostPacketsReceiverR & 0xF000) < 1 ? lostPacketsReceiverR : 0; + } + + public boolean hasValidFrameLosssData() { + return isValidData(frameLoss); + } + + /** + * @return If Spectrum Telemetry System is used, the id shows lost + * frames.
+ * If Lemon Telemetry System is used, the id is not used. + */ + public short getFrameLoss() { + return (frameLoss & 0xF000) < 1 ? frameLoss : 0; + } + + public boolean hasValidHoldsData() { + return isValidData(holds); + } + + /** + * @return If Spectrum Telemetry System is used, the id shows holds.
+ * If Lemon Telemetry System is used, the id is not used. + */ + public short getHolds() { + return (holds & 0xF000) < 1 ? holds : 0; + } + + /** + * @return Returns the voltage in hunderth of Volt of the receiver. + */ + public short getVoltageInHunderthOfVolts() { + return voltageInHunderthOfVolts; + } + +} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/RxPackCapacityBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/RxPackCapacityBlock.java new file mode 100644 index 0000000..9e325fd --- /dev/null +++ b/src/main/java/com/monstarmike/tlmreader/datablock/RxPackCapacityBlock.java @@ -0,0 +1,19 @@ +package com.monstarmike.tlmreader.datablock; + +public class RxPackCapacityBlock extends DataBlock { + + public RxPackCapacityBlock(byte[] rawData) { + super(rawData); + } + + @Override + public boolean areValuesEquals(DataBlock block) { + return false; + } + + @Override + public String toString() { + return "RtcData: " + getTimestamp() + + ", unknown data structure"; + } +} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/ServoDataBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/ServoDataBlock.java index 3051d26..6bbe14c 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/ServoDataBlock.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/ServoDataBlock.java @@ -32,7 +32,7 @@ *
  • Bit 0 (most significant bit): meaning not clear. Perhaps used for the * rotated 9 Bit Channels?** *
  • Bit 0x1-0x4: The channelnumber
  • - *
  • Bit 0x5-0xF: The value of the channel (11 Bit, 2048 steps, middle + *
  • Bit 0x5-0xF: The id of the channel (11 Bit, 2048 steps, middle * position 1024 = 0%, range +-150%)
  • * * @@ -42,7 +42,7 @@ *
  • Bit 0x1-0x4: The channelnumber
  • *
  • Bit 0x5-0x6: The subChannelnumber, these bits are rotating in each * datablock.**
  • - *
  • Bit 0x7-0xF: The value of the channel (9 Bit, 512 steps, middle position + *
  • Bit 0x7-0xF: The id of the channel (9 Bit, 512 steps, middle position * 256 = 0%, range +-150%)
  • * * * With this rotation, we can only decode 16 channel. The first Bit of the @@ -53,6 +53,7 @@ public class ServoDataBlock extends DataBlock { private static final int MAX_NUMBER_OF_CHANNELS = 20; + public static final short[] CHANNELVALUES = new short[MAX_NUMBER_OF_CHANNELS]; private short[] channelValues; private int availableChannelWithDataBitArray = 0; @@ -60,6 +61,18 @@ public class ServoDataBlock extends DataBlock { public ServoDataBlock(byte[] rawData) { super(rawData); decode(rawData); + + for (int i = 0; i < MAX_NUMBER_OF_CHANNELS; i++) { + measurementNames.add("Ch " + (i+1)); + } + + for (int i = 0; i < MAX_NUMBER_OF_CHANNELS; i++) { + measurementUnits.add("%"); + } + + for (int i = 0; i < MAX_NUMBER_OF_CHANNELS; i++) { + measurementFactors.add(1.0); + } } @Override @@ -67,7 +80,7 @@ public boolean areValuesEquals(DataBlock block) { if (block instanceof ServoDataBlock) { ServoDataBlock servo = (ServoDataBlock) block; for (int i=0; i0 = % range) -- (legacy)antenna A in dBm +// dBm_B; // Avg RSSI in % (<-1 = dBm, 0 = no data, >0 = % range) -- (legacy)antenna B in dBm +// // Note: Legacy use as antenna A/B dBm values is still supported. If only 1 antenna, set B = A. +// // The "no data" id is 0, but -1 (0xFF) is treated the same for backwards compatibility +// UINT16 spare[2]; +//} STRU_TELE_RPM; private float rpm; private short voltageInHunderthOfVolts; - private short tempInGradFahrenheit; + private short tempInDegreeFahrenheit; private short ratioInHunderth = 100; private byte poles = 1; private int rawRpmData; + private int dbm_A; + private int dbm_B; public StandardBlock(final byte[] rawData, final HeaderRpmBlock rpmHeader) { super(rawData); @@ -19,22 +35,35 @@ public StandardBlock(final byte[] rawData, final HeaderRpmBlock rpmHeader) { poles = rpmHeader.getPoles(); } decode(rawData); + + measurementNames.add("RPM St"); + measurementNames.add("Volt St"); + measurementNames.add("Temperature St"); + measurementNames.add("dbm_A"); + measurementNames.add("dbm_B"); + + measurementUnits.add("1/min"); + measurementUnits.add("V"); + measurementUnits.add("°C"); + measurementUnits.add("dBm"); + measurementUnits.add("dBm"); + + measurementFactors.add(1.0); + measurementFactors.add(0.01); + measurementFactors.add(0.1); + measurementFactors.add(1.0); + measurementFactors.add(1.0); } @Override public boolean areValuesEquals(DataBlock block) { if (block instanceof StandardBlock) { - StandardBlock std = (StandardBlock) block; - if (std.getRpm() != rpm) { - return false; - } - if (std.getVoltageInHunderthOfVolts() != voltageInHunderthOfVolts) { - return false; - } - if (std.getTemperatureInGradFahrenheit() != tempInGradFahrenheit) { - return false; - } - return true; + StandardBlock rpm = (StandardBlock) block; + return rpm.rawRpmData == rawRpmData + && rpm.voltageInHunderthOfVolts == voltageInHunderthOfVolts + && rpm.tempInDegreeFahrenheit == tempInDegreeFahrenheit + && rpm.dbm_A == dbm_A + && rpm.dbm_B == dbm_B; } return false; } @@ -44,7 +73,7 @@ public boolean hasValidRpmData() { } public float getRpm() { - return rpm; + return hasValidRpmData() ? rpm : 0.0f; } public boolean hasValidVoltageData() { @@ -56,15 +85,29 @@ public short getVoltageInHunderthOfVolts() { } public boolean hasValidTemperatureData() { - return tempInGradFahrenheit != Short.MIN_VALUE && tempInGradFahrenheit != 0x0000; + return tempInDegreeFahrenheit != 0x7FFF && tempInDegreeFahrenheit != Short.MIN_VALUE && tempInDegreeFahrenheit != 0 && (tempInDegreeFahrenheit & 0xFC00) == 0; + } + + public short getTemperatureInDegreeFahrenheit() { + return tempInDegreeFahrenheit; } - public short getTemperatureInGradFahrenheit() { - return tempInGradFahrenheit; + public float getTemperatureInThenthOfDegreeCelsius() { + return hasValidTemperatureData() ? (tempInDegreeFahrenheit - 32) / 1.8f * 10 : 0.0f; } - public float getTemperatureInGradCelsius() { - return (tempInGradFahrenheit - 32) / 1.8f; + /** + * @return the dbm_A + */ + public int getDbm_A() { + return dbm_A; + } + + /** + * @return the dbm_B + */ + public int getDbm_B() { + return dbm_B; } private void decode(final byte[] rawData) { @@ -75,14 +118,15 @@ private void decode(final byte[] rawData) { rpm = (1.0f / rawRpmData * 120000000.0f) / ratioInHunderth * 100 / poles; } voltageInHunderthOfVolts = Shorts.fromBytes(rawData[8], rawData[9]); - tempInGradFahrenheit = Shorts.fromBytes(rawData[10], rawData[11]); + tempInDegreeFahrenheit = Shorts.fromBytes(rawData[10], rawData[11]); + dbm_A = rawData[12]; + dbm_B = rawData[13]; + + measurementValues.add((int)getRpm()); + measurementValues.add((int)getVoltageInHunderthOfVolts()); + measurementValues.add((int)getTemperatureInThenthOfDegreeCelsius()); + measurementValues.add((int)getDbm_A()); + measurementValues.add((int)getDbm_B()); } - @Override - public String toString() { - return "StandardData; RPM: " + getRpm() + " (" + hasValidRpmData() + ") , Volt: " - + getVoltageInHunderthOfVolts() / 100.0 + "(" + hasValidVoltageData() + ") , Temperature (in °F): " - + getTemperatureInGradFahrenheit() + "(" + hasValidTemperatureData() + ") , Temperature (in °C): " - + getTemperatureInGradCelsius() + "(" + hasValidTemperatureData() + ")"; - } } diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/TemperatureBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/TemperatureBlock.java new file mode 100644 index 0000000..751434e --- /dev/null +++ b/src/main/java/com/monstarmike/tlmreader/datablock/TemperatureBlock.java @@ -0,0 +1,54 @@ +package com.monstarmike.tlmreader.datablock; + +import com.google.common.primitives.Shorts; + +public class TemperatureBlock extends DataBlock { + +// typedef struct +// { +// UINT8 identifier; // Source device = 0x02 +// UINT8 sID; // Secondary ID +// INT16 temperature; // Temperature in degrees Fahrenheit +// } STRU_TELE_TEMP; + + private short temperatureInFahrenheit; + + public TemperatureBlock(byte[] rawData) { + super(rawData); + decode(rawData); + + measurementNames.add("Temperature T"); + measurementUnits.add("°C"); + measurementFactors.add(0.1); + } + + @Override + public boolean areValuesEquals(DataBlock block) { + if (block instanceof TemperatureBlock) { + TemperatureBlock temp = (TemperatureBlock) block; + return temp.temperatureInFahrenheit == temperatureInFahrenheit; + } + return false; + } + + /** + * @return the temperatureInFahrenheit + */ + public short getTemperatureInFahrenheit() { + return temperatureInFahrenheit; + } + + /** + * @return the temperatureInFahrenheit + */ + public short getTemperatureInThenthGradCelsius() { + return (short) ((temperatureInFahrenheit - 32) / 1.8f * 10); + } + + private void decode(byte[] rawData) { + temperatureInFahrenheit = Shorts.fromBytes(rawData[6], rawData[7]); + + measurementValues.add((int)getTemperatureInThenthGradCelsius()); + } + +} diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/VarioBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/VarioBlock.java index e221770..5558657 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/VarioBlock.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/VarioBlock.java @@ -4,6 +4,19 @@ public class VarioBlock extends DataBlock { +// typedef struct +// { +// UINT8 identifier; // Source device = 0x40 +// UINT8 sID; // Secondary ID +// INT16 altitude; // .1m increments +// INT16 delta_0250ms, // change in altitude last 250ms, 0.1m/s increments +// delta_0500ms, // change in altitude last 500ms, 0.1m/s increments +// delta_1000ms, // change in altitude last 1.0 seconds, 0.1m/s increments +// delta_1500ms, // change in altitude last 1.5 seconds, 0.1m/s increments +// delta_2000ms, // change in altitude last 2.0 seconds, 0.1m/s increments +// delta_3000ms; // change in altitude last 3.0 seconds, 0.1m/s increments +// } STRU_TELE_VARIO_S; + private short altitudeInTenthOfMeter; private short deltaInIntervalOf250MsInTenthOfMeter; private short deltaInIntervalOf500MsInTenthOfMeter; @@ -14,31 +27,27 @@ public class VarioBlock extends DataBlock { public VarioBlock(byte[] rawData) { super(rawData); decode(rawData); + + measurementNames.add("Altitude V"); + measurementNames.add("Climb V"); + + measurementUnits.add("m"); + measurementUnits.add("m/s"); + + measurementFactors.add(0.1); + measurementFactors.add(0.1); } @Override public boolean areValuesEquals(DataBlock block) { if (block instanceof VarioBlock) { - VarioBlock std = (VarioBlock) block; - if (std.getAltitudeInTenthOfMeter() != altitudeInTenthOfMeter) { - return false; - } - if (std.getDeltaInIntervalOf250MsInTenthOfMeter() != deltaInIntervalOf250MsInTenthOfMeter) { - return false; - } - if (std.getDeltaInIntervalOf500MsInTenthOfMeter() != deltaInIntervalOf500MsInTenthOfMeter) { - return false; - } - if (std.getDeltaInIntervalOf1000MsInTenthOfMeter() != deltaInIntervalOf1000MsInTenthOfMeter) { - return false; - } - if (std.getDeltaInIntervalOf2000MsInTenthOfMeter() != deltaInIntervalOf2000MsInTenthOfMeter) { - return false; - } - if (std.getDeltaInIntervalOf3000MsInTenthOfMeter() != deltaInIntervalOf3000MsInTenthOfMeter) { - return false; - } - return true; + VarioBlock vario = (VarioBlock) block; + return vario.altitudeInTenthOfMeter != altitudeInTenthOfMeter + && vario.deltaInIntervalOf250MsInTenthOfMeter != deltaInIntervalOf250MsInTenthOfMeter + && vario.deltaInIntervalOf500MsInTenthOfMeter != deltaInIntervalOf500MsInTenthOfMeter + && vario.deltaInIntervalOf1000MsInTenthOfMeter != deltaInIntervalOf1000MsInTenthOfMeter + && vario.deltaInIntervalOf2000MsInTenthOfMeter != deltaInIntervalOf2000MsInTenthOfMeter + && vario.deltaInIntervalOf3000MsInTenthOfMeter != deltaInIntervalOf3000MsInTenthOfMeter; } return false; } @@ -68,21 +77,15 @@ public short getDeltaInIntervalOf3000MsInTenthOfMeter() { } private void decode(byte[] rawData) { - altitudeInTenthOfMeter = Shorts.fromBytes(rawData[0x06], rawData[0x07]); - deltaInIntervalOf250MsInTenthOfMeter = Shorts.fromBytes(rawData[0x08], rawData[0x09]); - deltaInIntervalOf500MsInTenthOfMeter = Shorts.fromBytes(rawData[0x0A], rawData[0x0B]); - deltaInIntervalOf1000MsInTenthOfMeter = Shorts.fromBytes(rawData[0x0C], rawData[0x0D]); - deltaInIntervalOf2000MsInTenthOfMeter = Shorts.fromBytes(rawData[0x0E], rawData[0x0F]); - deltaInIntervalOf3000MsInTenthOfMeter = Shorts.fromBytes(rawData[0x10], rawData[0x11]); + altitudeInTenthOfMeter = Shorts.fromBytes(rawData[6], rawData[7]); + deltaInIntervalOf250MsInTenthOfMeter = Shorts.fromBytes(rawData[8], rawData[9]); + deltaInIntervalOf500MsInTenthOfMeter = Shorts.fromBytes(rawData[10], rawData[11]); + deltaInIntervalOf1000MsInTenthOfMeter = Shorts.fromBytes(rawData[12], rawData[13]); + deltaInIntervalOf2000MsInTenthOfMeter = Shorts.fromBytes(rawData[14], rawData[15]); + deltaInIntervalOf3000MsInTenthOfMeter = Shorts.fromBytes(rawData[16], rawData[17]); + + measurementValues.add((int)getAltitudeInTenthOfMeter()); + measurementValues.add((int)getDeltaInIntervalOf250MsInTenthOfMeter()); } - @Override - public String toString() { - return super.toString() + " - altitude: " + getAltitudeInTenthOfMeter() + " - 250 delta: " - + getDeltaInIntervalOf250MsInTenthOfMeter() + " - 500 delta: " - + getDeltaInIntervalOf500MsInTenthOfMeter() + " - 1000 delta: " - + getDeltaInIntervalOf1000MsInTenthOfMeter() + " - 2000 delta: " - + getDeltaInIntervalOf2000MsInTenthOfMeter() + " - 3000 delta: " - + getDeltaInIntervalOf3000MsInTenthOfMeter(); - } } diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/VoltageBlock.java b/src/main/java/com/monstarmike/tlmreader/datablock/VoltageBlock.java index dd2eb49..7a80096 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/VoltageBlock.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/VoltageBlock.java @@ -1,12 +1,46 @@ package com.monstarmike.tlmreader.datablock; +import com.google.common.primitives.Shorts; + public class VoltageBlock extends DataBlock { + +// typedef struct +// { +// UINT8 identifier; // Source device = 0x01 +// UINT8 sID; // Secondary ID +// UINT16 volts; // 0.01V increments +// } STRU_TELE_HV; + private short voltsInTenthOfVolt; + public VoltageBlock(byte[] rawData) { super(rawData); + decode(rawData); + + measurementNames.add("Voltage V"); + measurementUnits.add("V"); + measurementFactors.add(0.1); + } + + private void decode(byte[] rawData) { + voltsInTenthOfVolt = Shorts.fromBytes(rawData[6], rawData[7]); + + measurementValues.add((int)getVoltsInTenthOfVolt()); } + @Override public boolean areValuesEquals(DataBlock block) { + if (block instanceof VoltageBlock) { + VoltageBlock voltage = (VoltageBlock) block; + return voltage.voltsInTenthOfVolt == getVoltsInTenthOfVolt(); + } return false; } + + /** + * @return the voltsInTenthOfVolt + */ + public short getVoltsInTenthOfVolt() { + return voltsInTenthOfVolt; + } } diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/SignalNormalizer.java b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/SignalNormalizer.java index 2608025..12135cb 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/SignalNormalizer.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/SignalNormalizer.java @@ -4,7 +4,7 @@ import com.monstarmike.tlmreader.datablock.DataBlock; import com.monstarmike.tlmreader.datablock.HeaderRxBlock; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; import com.monstarmike.tlmreader.datablock.normalizer.processor.DebugOutputProcessor; import com.monstarmike.tlmreader.datablock.normalizer.processor.DiscountinuousBlocksProcessor; import com.monstarmike.tlmreader.datablock.normalizer.processor.InvalidCountsProcessor; @@ -21,7 +21,7 @@ public SignalNormalizer(final HeaderRxBlock headerRxBlock) { } public void normalize(final List dataBlocks) { - ProcessorEvaluator evaluator = new ProcessorEvaluator<>(); + ProcessorEvaluator evaluator = new ProcessorEvaluator<>(); evaluator.registerProcessor(new DebugOutputProcessor()); evaluator.registerProcessor(new InvalidDataBlocksProcessor()); evaluator.registerProcessor(new DiscountinuousBlocksProcessor()); diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/DebugOutputProcessor.java b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/DebugOutputProcessor.java index 14ee8f8..2fc74fa 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/DebugOutputProcessor.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/DebugOutputProcessor.java @@ -1,12 +1,12 @@ package com.monstarmike.tlmreader.datablock.normalizer.processor; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; -public class DebugOutputProcessor extends AbstractProcessor { +public class DebugOutputProcessor extends AbstractProcessor { - RXBlock lastBlock = null; + RxBlock lastBlock = null; - public void preprocess(RXBlock rxBlock) { + public void preprocess(RxBlock rxBlock) { if (rxBlock.hasValidDataLostPacketsReceiverA() && rxBlock.getLostPacketsReceiverA() > 200) { if (lastBlock != null) { System.out.println("LAST: " + lastBlock.getTimestamp() + " " + lastBlock.getLostPacketsReceiverA()); @@ -14,7 +14,7 @@ public void preprocess(RXBlock rxBlock) { } } - public Class getClassOfDataBlock() { - return RXBlock.class; + public Class getClassOfDataBlock() { + return RxBlock.class; } } \ No newline at end of file diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/DiscountinuousBlocksProcessor.java b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/DiscountinuousBlocksProcessor.java index 57ce0af..72d6c6c 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/DiscountinuousBlocksProcessor.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/DiscountinuousBlocksProcessor.java @@ -5,18 +5,18 @@ import java.util.List; import java.util.Set; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; -public class DiscountinuousBlocksProcessor extends AbstractProcessor { +public class DiscountinuousBlocksProcessor extends AbstractProcessor { private static final int MAX_CHANGE_IN_ONE_HUNDERTH = 10; - private Set unclassifiedBlocks = new HashSet<>(); + private Set unclassifiedBlocks = new HashSet<>(); private DataState dataState = DataState.UNKNOWN; - private RXBlock lastBlock = null; - private List badBlocks = new ArrayList<>(); + private RxBlock lastBlock = null; + private List badBlocks = new ArrayList<>(); - public boolean isBad(RXBlock block) { + public boolean isBad(RxBlock block) { return badBlocks.contains(block); } @@ -26,7 +26,7 @@ public void preprocessFinished() { } } - public void preprocess(RXBlock currentBlock) { + public void preprocess(RxBlock currentBlock) { if (currentBlock.hasValidDataLostPacketsReceiverA()) { if (lastBlock != null) { ChangeState currentChangeState = isContinuous(lastBlock, currentBlock); @@ -56,11 +56,11 @@ public void preprocess(RXBlock currentBlock) { } } - public Class getClassOfDataBlock() { - return RXBlock.class; + public Class getClassOfDataBlock() { + return RxBlock.class; } - private ChangeState isContinuous(RXBlock last, RXBlock current) { + private ChangeState isContinuous(RxBlock last, RxBlock current) { int timeDiff = current.getTimestamp() - last.getTimestamp(); int valueDiff = current.getLostPacketsReceiverA() - last.getLostPacketsReceiverA(); double change = (double) valueDiff / timeDiff; diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidCountsProcessor.java b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidCountsProcessor.java index cdad22e..699406c 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidCountsProcessor.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidCountsProcessor.java @@ -1,8 +1,8 @@ package com.monstarmike.tlmreader.datablock.normalizer.processor; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; -public class InvalidCountsProcessor extends AbstractProcessor { +public class InvalidCountsProcessor extends AbstractProcessor { private double lessThan10Percent = 0.1; private int countA = 0; private int countB = 0; @@ -10,7 +10,7 @@ public class InvalidCountsProcessor extends AbstractProcessor { private int countR = 0; private int totalCount = 0; - public void preprocess(RXBlock rxBlock) { + public void preprocess(RxBlock rxBlock) { if (rxBlock.hasValidDataLostPacketsReceiverA()) { countA++; } @@ -26,7 +26,7 @@ public void preprocess(RXBlock rxBlock) { totalCount++; } - public boolean isBad(RXBlock rxBlock) { + public boolean isBad(RxBlock rxBlock) { boolean remove = false; boolean badBlock = true; if (rxBlock.hasValidDataLostPacketsReceiverA()) { @@ -59,8 +59,8 @@ public boolean isBad(RXBlock rxBlock) { return false; } - public Class getClassOfDataBlock() { - return RXBlock.class; + public Class getClassOfDataBlock() { + return RxBlock.class; } private double calculatePercent(int count) { diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidDataBlocksProcessor.java b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidDataBlocksProcessor.java index 51912d6..37f8189 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidDataBlocksProcessor.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidDataBlocksProcessor.java @@ -1,14 +1,14 @@ package com.monstarmike.tlmreader.datablock.normalizer.processor; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; -public class InvalidDataBlocksProcessor extends AbstractProcessor { +public class InvalidDataBlocksProcessor extends AbstractProcessor { - public boolean isBad(RXBlock block) { + public boolean isBad(RxBlock block) { return !block.hasValidDataLostPacketsReceiverA(); } - public Class getClassOfDataBlock() { - return RXBlock.class; + public Class getClassOfDataBlock() { + return RxBlock.class; } } \ No newline at end of file diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/RedundantDataBlocksProcessor.java b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/RedundantDataBlocksProcessor.java index c20e0a6..a6443d3 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/RedundantDataBlocksProcessor.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/RedundantDataBlocksProcessor.java @@ -9,7 +9,8 @@ import com.monstarmike.tlmreader.datablock.DataBlock; public class RedundantDataBlocksProcessor extends AbstractProcessor { - + + private final static boolean DEBUG = false; //drive debug output while processing private Map typeMap = new HashMap<>(); @Override @@ -93,7 +94,8 @@ void preprocessFinished() { } private void printRedundantBlocks(String type, int totalBlocks, int redundantBlocks) { - System.out.println("[" + type + "] redundant Blocks: " + redundantBlocks + ", total Blocks: " + totalBlocks + if (DEBUG) + System.out.println("[" + type + "] redundant Blocks: " + redundantBlocks + ", total Blocks: " + totalBlocks + ", redundant Blocks in percent: " + (double) redundantBlocks / totalBlocks * 100 + "%"); } diff --git a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/SpectrumTelemetryDetector.java b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/SpectrumTelemetryDetector.java index b27b459..1feef3a 100644 --- a/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/SpectrumTelemetryDetector.java +++ b/src/main/java/com/monstarmike/tlmreader/datablock/normalizer/processor/SpectrumTelemetryDetector.java @@ -1,9 +1,9 @@ package com.monstarmike.tlmreader.datablock.normalizer.processor; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; import com.monstarmike.tlmreader.datablock.normalizer.util.MyFrequency; -public class SpectrumTelemetryDetector extends AbstractProcessor { +public class SpectrumTelemetryDetector extends AbstractProcessor { final MyFrequency frequencyA = new MyFrequency(); public boolean isSpectrumTelemetry() { @@ -16,13 +16,13 @@ public boolean isSpectrumTelemetry() { return belowOrEquals50 > between50And100; } - public void preprocess(RXBlock dataBlock) { + public void preprocess(RxBlock dataBlock) { if (dataBlock.hasValidDataLostPacketsReceiverA()) { frequencyA.addValue(dataBlock.getLostPacketsReceiverA()); } } - public Class getClassOfDataBlock() { - return RXBlock.class; + public Class getClassOfDataBlock() { + return RxBlock.class; } } diff --git a/src/main/java/com/monstarmike/tlmreader/util/StringUtils.java b/src/main/java/com/monstarmike/tlmreader/util/StringUtils.java index bf9d5d7..66265ba 100644 --- a/src/main/java/com/monstarmike/tlmreader/util/StringUtils.java +++ b/src/main/java/com/monstarmike/tlmreader/util/StringUtils.java @@ -1,5 +1,7 @@ package com.monstarmike.tlmreader.util; +import java.util.regex.Pattern; + public class StringUtils { final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); @@ -20,6 +22,27 @@ public static String bytesToDec(byte[] bytes) { decParts[i * 2] = new Integer(bytes[i] & 0xff).toString(); decParts[i * 2 + 1] = " "; } - return org.apache.commons.lang.StringUtils.join(decParts); + return String.join(", ",decParts); + } + + + /** + * convert a byte array inverted into BCD character string representation + * @param bytes array of bytes + * @param start start position (start + size - 1) + * @param size iteration length + * @return string with converted characters + */ + public static String bcdEncodeInverted(byte[] bytes, int start, int size) { + StringBuffer sb = new StringBuffer(); + for (int i = start+size-1; i >= start; --i) { + sb.append(String.format("%02X", bytes[i])); //$NON-NLS-1$ + } + if (Pattern.compile(".*[ABCDEF]").matcher(sb.toString()).find()) { + System.err.println("invalid input " + sb); + return "0"; + } + return sb.toString(); } + } diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/AltitudeBlockTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/AltitudeBlockTest.java new file mode 100644 index 0000000..98f9fc5 --- /dev/null +++ b/src/test/java/com/monstarmike/tlmreader/datablock/AltitudeBlockTest.java @@ -0,0 +1,19 @@ +package com.monstarmike.tlmreader.datablock; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import com.monstarmike.tlmreader.DataBlockBuilder; + +public class AltitudeBlockTest { + + private static final short ALTITUDE_DATABLOCK_MAKER = (short) 0x1200; + + @Test + public void testGetAltitude() { + byte[] testBlock = new DataBlockBuilder(0, ALTITUDE_DATABLOCK_MAKER).setValue(315, 0x6).get(); + AltitudeBlock block = (AltitudeBlock) DataBlock.createDataBlock(testBlock, null); + assertEquals(315 * 0.1 , block.getAltitudeInTenthOfMeter() * block.getMeasurementFactors().get(0), 0.1); + } +} diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/AltitudeZeroBlockTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/AltitudeZeroBlockTest.java new file mode 100644 index 0000000..4b5a325 --- /dev/null +++ b/src/test/java/com/monstarmike/tlmreader/datablock/AltitudeZeroBlockTest.java @@ -0,0 +1,19 @@ +package com.monstarmike.tlmreader.datablock; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import com.monstarmike.tlmreader.DataBlockBuilder; + +public class AltitudeZeroBlockTest { + + private static final short ALTITUDE_ZERO_DATABLOCK_MAKER = (short) 0x7B00; + + @Test + public void testGetAltitudeOffset() { + byte[] testBlock = new DataBlockBuilder(0, ALTITUDE_ZERO_DATABLOCK_MAKER).setValue(5, 0x9).get(); + AltitudeZeroBlock block = (AltitudeZeroBlock) DataBlock.createDataBlock(testBlock, null); + assertEquals(128 , block.getAltOffset() * block.getMeasurementFactors().get(0), 0); + } +} diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/CurrentBlockTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/CurrentBlockTest.java index 352a503..3bacd28 100644 --- a/src/test/java/com/monstarmike/tlmreader/datablock/CurrentBlockTest.java +++ b/src/test/java/com/monstarmike/tlmreader/datablock/CurrentBlockTest.java @@ -14,6 +14,6 @@ public class CurrentBlockTest { public void testGetCurrent() { byte[] testBlock = new DataBlockBuilder(0, CURRENT_DATABLOCK_MAKER).setValue(2973, 0x6).get(); CurrentBlock currentBlock = (CurrentBlock) DataBlock.createDataBlock(testBlock, null); - assertEquals(2973.0 * 0.1967 , currentBlock.getCurrent(), 0.0001); + assertEquals(2973.0 * 0.1967 , currentBlock.getCurrent() * currentBlock.getMeasurementFactors().get(0), 0.0001); } } diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/EscBlockTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/EscBlockTest.java new file mode 100644 index 0000000..c3ca620 --- /dev/null +++ b/src/test/java/com/monstarmike/tlmreader/datablock/EscBlockTest.java @@ -0,0 +1,28 @@ +package com.monstarmike.tlmreader.datablock; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import com.monstarmike.tlmreader.DataBlockBuilder; + +public class EscBlockTest { + + private static final short ESC_DATABLOCK_MAKER = (short) 0x2000; + private static final byte[] ESC_BLOCK_DATA = new byte[] { (byte)0x8A, (byte)0x9E, (byte)0x0B, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x88, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x13, (byte)0x7F, (byte)0xFF, (byte)0x00, (byte)0x6E, (byte)0xFF, (byte)0x52}; + + @Test + public void testGetCurrentBEC() { + byte[] testBlock = new DataBlockBuilder(0, ESC_DATABLOCK_MAKER).setValue(22, 15).get(); + EscBlock block = (EscBlock) DataBlock.createDataBlock(testBlock, null); + assertEquals(22 * 0.1 , block.getCurrentBECInTenthOfAmps() * block.getMeasurementFactors().get(4), 0.1); + } + + @Test + public void testToString() { + EscBlock block = new EscBlock(ESC_BLOCK_DATA); + assertEquals("EscBlock 761482 - RPM ESC = 0.0 1/min; Voltage ESC = 11.6 V; TempFET ESC = 0.0 °C; Current ESC = 0.2 A; CurrentBEC ESC = 0.0 A; VoltsBEC ESC = 5.5 V; Throttle ESC = 0.0 %; PowerOut ESC = 41.0 %; PowerIn ESC = 2.2 W;", + block.toString().trim() + ); + } +} diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/FlightPackBlockTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/FlightPackBlockTest.java new file mode 100644 index 0000000..03655f2 --- /dev/null +++ b/src/test/java/com/monstarmike/tlmreader/datablock/FlightPackBlockTest.java @@ -0,0 +1,29 @@ +package com.monstarmike.tlmreader.datablock; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import com.monstarmike.tlmreader.DataBlockBuilder; + +public class FlightPackBlockTest { + + private static final short DATABLOCK_MAKER = (short) 0x3400; + private static final byte[] BLOCK_DATA = new byte[] { (byte)0x71, (byte)0x9E, (byte)0x0B, (byte)0x00, (byte)0x34, (byte)0x00, (byte)0x02, (byte)0x00, (byte)0x52, (byte)0x03, (byte)0xAF, (byte)0x00, (byte)0xFF, (byte)0x7F, (byte)0xFF, (byte)0x7F, (byte)0xFF, (byte)0x7F, (byte)0x00, (byte)0x00} +; + + @Test + public void testGetCurrentB() { + byte[] testBlock = new DataBlockBuilder(0, DATABLOCK_MAKER).setValue(22, 11).get(); + FlightPackBlock block = (FlightPackBlock) DataBlock.createDataBlock(testBlock, null); + assertEquals(22 * 0.1 , block.getCurrentBInTenthOfAmps() * block.getMeasurementFactors().get(3), 0.1); + } + + @Test + public void testToString() { + FlightPackBlock block = new FlightPackBlock(BLOCK_DATA); + assertEquals("FlightPackBlock 761457 - Current FPA = 0.2 A; Capacity FPA = 850 mAh; Temperature FPA = 17.5 °C; Current FPB = 0.0 A; Capacity FPB = 0 mAh; Temperature FPB = 0.0 °C;", + block.toString().trim() + ); + } +} diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/GpsCollectorBlockTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/GpsCollectorBlockTest.java new file mode 100644 index 0000000..6a08c90 --- /dev/null +++ b/src/test/java/com/monstarmike/tlmreader/datablock/GpsCollectorBlockTest.java @@ -0,0 +1,23 @@ +package com.monstarmike.tlmreader.datablock; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class GpsCollectorBlockTest { + + private static final byte[] LOC_BLOCK_DATA = new byte[] { (byte)0x0A, (byte)0xD5, (byte)0x09, (byte)0x00, (byte)0x16, (byte)0x00, (byte)0x01, (byte)0x04, (byte)0x76, (byte)0x28, (byte)0x38, (byte)0x48, (byte)0x04, (byte)0x95, (byte)0x58, (byte)0x08, (byte)0x49, (byte)0x32, (byte)0x05, (byte)0x3B}; + private static final byte[] STAT_BLOCK_DATA = new byte[] { (byte)0x11, (byte)0xD5, (byte)0x09, (byte)0x00, (byte)0x17, (byte)0x00, (byte)0x64, (byte)0x01, (byte)0x00, (byte)0x34, (byte)0x38, (byte)0x14, (byte)0x12, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00}; + + + @Test + public void testToString() { + GPSLocationBlock locBlock = new GPSLocationBlock(LOC_BLOCK_DATA); + GPSCollectorBlock.getInstance().updateLocation(locBlock); + GPSStatusBlock statBlock = new GPSStatusBlock(STAT_BLOCK_DATA); + GPSCollectorBlock.getInstance().updateStatus(statBlock); + assertEquals("GPSCollectorBlock 644369 - Altitude GPS = 40.1 m; Latitude = 48382876 ° '; Longitude = 8589504 ° '; Speed GPS = 30.4 km/h; Satellites GPS = 12 #; Course = 324.9 °; HDOP = 0.5 ; GPSFix = 3 ; UTC GPS = 14383400 ;", + GPSCollectorBlock.getInstance().toString().trim() + ); + } +} diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/GpsLocationBlockTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/GpsLocationBlockTest.java new file mode 100644 index 0000000..91e7a2c --- /dev/null +++ b/src/test/java/com/monstarmike/tlmreader/datablock/GpsLocationBlockTest.java @@ -0,0 +1,24 @@ +package com.monstarmike.tlmreader.datablock; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class GpsLocationBlockTest { + + private static final byte[] GPS_BLOCK_DATA = new byte[] { (byte)0x0A, (byte)0xD5, (byte)0x09, (byte)0x00, (byte)0x16, (byte)0x00, (byte)0x01, (byte)0x04, (byte)0x76, (byte)0x28, (byte)0x38, (byte)0x48, (byte)0x04, (byte)0x95, (byte)0x58, (byte)0x08, (byte)0x49, (byte)0x32, (byte)0x05, (byte)0x3B}; + + @Test + public void testGetAltitude() { + GPSLocationBlock block = new GPSLocationBlock(GPS_BLOCK_DATA); + assertEquals(401*0.1 , block.getAltitudeLowInTenthOfMeter() * block.getMeasurementFactors().get(0), 0.01); + } + + @Test + public void testToString() { + GPSLocationBlock block = new GPSLocationBlock(GPS_BLOCK_DATA); + assertEquals("GPSLocationData: 644362 - Altitude low = 40.1, Latitude = 48.638126, Longitude = 8.982507, Course = 324.9, HDOP = 0.5, GPSFix = 3, IS_NORTH = true, IS_EAST = true, LONGITUDE_GREATER_99 = false", + block.toString().trim() + ); + } +} diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/GpsStatusBlockTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/GpsStatusBlockTest.java new file mode 100644 index 0000000..61b61bb --- /dev/null +++ b/src/test/java/com/monstarmike/tlmreader/datablock/GpsStatusBlockTest.java @@ -0,0 +1,28 @@ +package com.monstarmike.tlmreader.datablock; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import com.monstarmike.tlmreader.DataBlockBuilder; + +public class GpsStatusBlockTest { + + private static final short GPS_DATABLOCK_MAKER = (short) 0x1700; + private static final byte[] GPS_BLOCK_DATA = new byte[] { (byte)0x11, (byte)0xD5, (byte)0x09, (byte)0x00, (byte)0x17, (byte)0x00, (byte)0x64, (byte)0x01, (byte)0x00, (byte)0x34, (byte)0x38, (byte)0x14, (byte)0x12, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00}; + + @Test + public void testGetAltitude() { + byte[] testBlock = new DataBlockBuilder(0, GPS_DATABLOCK_MAKER).setValue(2, 12).get(); + GPSStatusBlock block = (GPSStatusBlock) DataBlock.createDataBlock(testBlock, null); + assertEquals(2, block.getAltitudeHightInMeter() * block.getMeasurementFactors().get(3), 0); + } + + @Test + public void testToString() { + GPSStatusBlock block = new GPSStatusBlock(GPS_BLOCK_DATA); + assertEquals("GPSStatusData: 644369 - speedInKnots = 16.4, UTC = 14:38:34.00, numSats = 12, altitudeHightInMeter = 0", + block.toString().trim() + ); + } +} diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/PowerboxBlockTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/PowerBoxBlockTest.java similarity index 83% rename from src/test/java/com/monstarmike/tlmreader/datablock/PowerboxBlockTest.java rename to src/test/java/com/monstarmike/tlmreader/datablock/PowerBoxBlockTest.java index d914fd5..fe72e03 100644 --- a/src/test/java/com/monstarmike/tlmreader/datablock/PowerboxBlockTest.java +++ b/src/test/java/com/monstarmike/tlmreader/datablock/PowerBoxBlockTest.java @@ -6,7 +6,7 @@ import com.monstarmike.tlmreader.DataBlockBuilder; -public class PowerboxBlockTest { +public class PowerBoxBlockTest { private static final short POWERBOX_DATABLOCK_MAKER = (short) 0x0a00; @@ -14,14 +14,14 @@ public class PowerboxBlockTest { public void testGetVoltageOne() { short valueInHunderthOfVolt = 473; // = 4.73 Volt byte[] testBlock = new DataBlockBuilder(0, POWERBOX_DATABLOCK_MAKER).setValue(valueInHunderthOfVolt, 0x06).get(); - PowerboxBlock powerBoxBlock = (PowerboxBlock) DataBlock.createDataBlock(testBlock, null); + PowerBoxBlock powerBoxBlock = (PowerBoxBlock) DataBlock.createDataBlock(testBlock, null); assertEquals(valueInHunderthOfVolt , powerBoxBlock.getVoltageOneInHunderthOfVolts()); } @Test public void testGetVoltageTwo() { short valueInHunderthOfVolt = 1620; // = 16.20 Volt byte[] testBlock = new DataBlockBuilder(0, POWERBOX_DATABLOCK_MAKER).setValue(valueInHunderthOfVolt, 0x08).get(); - PowerboxBlock powerBoxBlock = (PowerboxBlock) DataBlock.createDataBlock(testBlock, null); + PowerBoxBlock powerBoxBlock = (PowerBoxBlock) DataBlock.createDataBlock(testBlock, null); assertEquals(valueInHunderthOfVolt, powerBoxBlock.getVoltageTwoInHunderthOfVolts()); } @@ -29,7 +29,7 @@ public void testGetVoltageTwo() { public void testGetCapacityOne() { short valueIn_mAh = 15; byte[] testBlock = new DataBlockBuilder(0, POWERBOX_DATABLOCK_MAKER).setValue(valueIn_mAh, 0x0A).get(); - PowerboxBlock powerBoxBlock = (PowerboxBlock) DataBlock.createDataBlock(testBlock, null); + PowerBoxBlock powerBoxBlock = (PowerBoxBlock) DataBlock.createDataBlock(testBlock, null); assertEquals(valueIn_mAh, (short) powerBoxBlock.getCapacityOneInmAh()); } @@ -37,7 +37,7 @@ public void testGetCapacityOne() { public void testGetCapacityTwo() { short valueIn_mAh = 763; byte[] testBlock = new DataBlockBuilder(0, POWERBOX_DATABLOCK_MAKER).setValue(valueIn_mAh, 0x0C).get(); - PowerboxBlock powerBoxBlock = (PowerboxBlock) DataBlock.createDataBlock(testBlock, null); + PowerBoxBlock powerBoxBlock = (PowerBoxBlock) DataBlock.createDataBlock(testBlock, null); assertEquals(valueIn_mAh, (short) powerBoxBlock.getCapacityTwoInmAh()); } diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/RXBlockTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/RxBlockTest.java similarity index 81% rename from src/test/java/com/monstarmike/tlmreader/datablock/RXBlockTest.java rename to src/test/java/com/monstarmike/tlmreader/datablock/RxBlockTest.java index 97db42f..b781e88 100644 --- a/src/test/java/com/monstarmike/tlmreader/datablock/RXBlockTest.java +++ b/src/test/java/com/monstarmike/tlmreader/datablock/RxBlockTest.java @@ -8,14 +8,14 @@ import com.monstarmike.tlmreader.DataBlockBuilder; -public class RXBlockTest { +public class RxBlockTest { private static final short RX_DATABLOCK_MAKER = (short) 0x7F00; @Test public void testGetLostPacketsReceiverA() { byte[] testBlock = new DataBlockBuilder(0, RX_DATABLOCK_MAKER).setValue(123, 0x06).get(); - RXBlock rxBlock = (RXBlock) DataBlock.createDataBlock(testBlock, null); + RxBlock rxBlock = (RxBlock) DataBlock.createDataBlock(testBlock, null); assertEquals(123, (short) rxBlock.getLostPacketsReceiverA()); } @@ -23,7 +23,7 @@ public void testGetLostPacketsReceiverA() { public void testHasValidDataLostPacketsReceiverAUnsignedShortMax() { int unsignedShortMax = 0xFFFF; byte[] testBlock = new DataBlockBuilder(0, RX_DATABLOCK_MAKER).setValue(unsignedShortMax, 0x06).get(); - RXBlock rxBlock = (RXBlock) DataBlock.createDataBlock(testBlock, null); + RxBlock rxBlock = (RxBlock) DataBlock.createDataBlock(testBlock, null); assertFalse(rxBlock.hasValidDataLostPacketsReceiverA()); } @@ -31,7 +31,7 @@ public void testHasValidDataLostPacketsReceiverAUnsignedShortMax() { public void testHasValidDataLostPacketsReceiverASignedShortMax() { int signedShortMax = Short.MAX_VALUE+1; byte[] testBlock = new DataBlockBuilder(0, RX_DATABLOCK_MAKER).setValue(signedShortMax, 0x06).get(); - RXBlock rxBlock = (RXBlock) DataBlock.createDataBlock(testBlock, null); + RxBlock rxBlock = (RxBlock) DataBlock.createDataBlock(testBlock, null); assertFalse(rxBlock.hasValidDataLostPacketsReceiverA()); } @@ -39,14 +39,14 @@ public void testHasValidDataLostPacketsReceiverASignedShortMax() { public void testHasValidDataLostPacketsReceiverAOk() { int signedShortMax = 0; byte[] testBlock = new DataBlockBuilder(0, RX_DATABLOCK_MAKER).setValue(signedShortMax, 0x06).get(); - RXBlock rxBlock = (RXBlock) DataBlock.createDataBlock(testBlock, null); + RxBlock rxBlock = (RxBlock) DataBlock.createDataBlock(testBlock, null); assertTrue(rxBlock.hasValidDataLostPacketsReceiverA()); } @Test public void testGetLostPacketsReceiverB() { byte[] testBlock = new DataBlockBuilder(0, RX_DATABLOCK_MAKER).setValue(739, 0x08).get(); - RXBlock rxBlock = (RXBlock) DataBlock.createDataBlock(testBlock, null); + RxBlock rxBlock = (RxBlock) DataBlock.createDataBlock(testBlock, null); assertTrue(rxBlock.hasValidDataLostPacketsReceiverB()); assertEquals(739, (short) rxBlock.getLostPacketsReceiverB()); } @@ -54,7 +54,7 @@ public void testGetLostPacketsReceiverB() { @Test public void testGetLostPacketsReceiverL() { byte[] testBlock = new DataBlockBuilder(0, RX_DATABLOCK_MAKER).setValue(999, 0x0A).get(); - RXBlock rxBlock = (RXBlock) DataBlock.createDataBlock(testBlock, null); + RxBlock rxBlock = (RxBlock) DataBlock.createDataBlock(testBlock, null); assertTrue(rxBlock.hasValidDataLostPacketsReceiverL()); assertEquals(999, (short) rxBlock.getLostPacketsReceiverL()); } @@ -62,7 +62,7 @@ public void testGetLostPacketsReceiverL() { @Test public void testGetLostPacketsReceiverR() { byte[] testBlock = new DataBlockBuilder(0, RX_DATABLOCK_MAKER).setValue(302, 0x0C).get(); - RXBlock rxBlock = (RXBlock) DataBlock.createDataBlock(testBlock, null); + RxBlock rxBlock = (RxBlock) DataBlock.createDataBlock(testBlock, null); assertTrue(rxBlock.hasValidDataLostPacketsReceiverR()); assertEquals(302, (short) rxBlock.getLostPacketsReceiverR()); } @@ -70,7 +70,7 @@ public void testGetLostPacketsReceiverR() { @Test public void testGetFrameLoss() { byte[] testBlock = new DataBlockBuilder(0, RX_DATABLOCK_MAKER).setValue(3, 0x0E).get(); - RXBlock rxBlock = (RXBlock) DataBlock.createDataBlock(testBlock, null); + RxBlock rxBlock = (RxBlock) DataBlock.createDataBlock(testBlock, null); assertTrue(rxBlock.hasValidFrameLosssData()); assertEquals(3, (short) rxBlock.getFrameLoss()); } @@ -78,7 +78,7 @@ public void testGetFrameLoss() { @Test public void testGetHolds() { byte[] testBlock = new DataBlockBuilder(0, RX_DATABLOCK_MAKER).setValue(15, 0x10).get(); - RXBlock rxBlock = (RXBlock) DataBlock.createDataBlock(testBlock, null); + RxBlock rxBlock = (RxBlock) DataBlock.createDataBlock(testBlock, null); assertTrue(rxBlock.hasValidHoldsData()); assertEquals(15, (short) rxBlock.getHolds()); } @@ -87,7 +87,7 @@ public void testGetHolds() { public void testVolts() { int valueInHunderthOfVolt = 603; byte[] testBlock = new DataBlockBuilder(0, RX_DATABLOCK_MAKER).setValue(valueInHunderthOfVolt, 0x12).get(); - RXBlock rxBlock = (RXBlock) DataBlock.createDataBlock(testBlock, null); + RxBlock rxBlock = (RxBlock) DataBlock.createDataBlock(testBlock, null); assertEquals(valueInHunderthOfVolt, rxBlock.getVoltageInHunderthOfVolts()); } } diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/StandardBlockTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/StandardBlockTest.java index 1ce7b8e..c5c182c 100644 --- a/src/test/java/com/monstarmike/tlmreader/datablock/StandardBlockTest.java +++ b/src/test/java/com/monstarmike/tlmreader/datablock/StandardBlockTest.java @@ -55,7 +55,7 @@ public void testGetRpm0x00FF() { int testValue = 0x00FF; byte[] testBlock = new DataBlockBuilder(0, STD_DATABLOCK_MAKER).setValue(testValue, 0x6).get(); StandardBlock standardBlock = (StandardBlock) DataBlock.createDataBlock(testBlock, null); - Assert.assertEquals(reverseEngineeredRpmValueFunction(testValue), standardBlock.getRpm(), 0.02); + Assert.assertEquals(reverseEngineeredRpmValueFunction(testValue), standardBlock.getRpm(), 0.04); } @Test @@ -73,7 +73,7 @@ public void testGetRpmWithRationAndPoles() { HeaderRpmBlock rpmHeaderMock = Mockito.mock(HeaderRpmBlock.class); Mockito.when(rpmHeaderMock.getPoles()).thenReturn(poles); Mockito.when(rpmHeaderMock.getRatioInHunderth()).thenReturn(ratioInHunderth); - int testValue = 0xFFFF; + int testValue = 0x0FFF; byte[] testBlock = new DataBlockBuilder(0, STD_DATABLOCK_MAKER).setValue(testValue, 0x06).get(); StandardBlock standardBlock = (StandardBlock) DataBlock.createDataBlock(testBlock, rpmHeaderMock); Assert.assertEquals(reverseEngineeredRpmValueFunction(testValue) / poles / ratioInHunderth * 100, @@ -93,7 +93,7 @@ public void testGetTemperatureInGradFahrenheit() { short testValue = (short) 87; byte[] testBlock = new DataBlockBuilder(0, STD_DATABLOCK_MAKER).setValue(testValue, 0x0A).get(); StandardBlock standardBlock = (StandardBlock) DataBlock.createDataBlock(testBlock, null); - Assert.assertEquals(87, standardBlock.getTemperatureInGradFahrenheit()); + Assert.assertEquals(87, standardBlock.getTemperatureInDegreeFahrenheit()); } @Test @@ -101,7 +101,7 @@ public void testGetTemperatureInGradCelcius() { short testValue = (short) 87; byte[] testBlock = new DataBlockBuilder(0, STD_DATABLOCK_MAKER).setValue(testValue, 0x0A).get(); StandardBlock standardBlock = (StandardBlock) DataBlock.createDataBlock(testBlock, null); - Assert.assertEquals((87 - 32) / 1.8, standardBlock.getTemperatureInGradCelsius(), 0.001); + Assert.assertEquals((87 - 32) / 1.8f * 10, standardBlock.getTemperatureInThenthOfDegreeCelsius(), 0.01); } @Test @@ -114,7 +114,7 @@ public void testHasValidTemperatureData0x0000() { @Test public void testHasValidTemperatureDataShortMIN() { - short testValue = (short) Short.MIN_VALUE; + short testValue = (short) 0x7FFF; byte[] testBlock = new DataBlockBuilder(0, STD_DATABLOCK_MAKER).setValue(testValue, 0x0A).get(); StandardBlock standardBlock = (StandardBlock) DataBlock.createDataBlock(testBlock, null); Assert.assertFalse(standardBlock.hasValidTemperatureData()); @@ -161,13 +161,11 @@ public void testToString() { .setValue(testTempValue, 0x0A).setValue(testRpmValue, 0x06).get(); StandardBlock standardBlock = (StandardBlock) DataBlock.createDataBlock(testBlock, null); Assert.assertEquals( - "StandardData; RPM: 2958.5798 (true) , Volt: 18.27(true) , " - + "Temperature (in °F): 87(true) , Temperature (in °C): 30.555557(true)", + "StandardBlock 0 - RPM St = 2958 1/min; Volt St = 18.3 V; Temperature St = 30.5 °C; dbm_A = 0 dBm; dbm_B = 0 dBm; ", standardBlock.toString()); } - private double reverseEngineeredRpmValueFunction(final int rawShortValue) { - double rpmValue = (rawShortValue == 0) ? 0.0 : 1.0 / rawShortValue * 120000000.0; - return rpmValue; + private float reverseEngineeredRpmValueFunction(final int rawShortValue) { + return (rawShortValue == 0) ? 0.0f : 1.0f / rawShortValue * 120000000.0f; } } diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/TemperatureBlockTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/TemperatureBlockTest.java new file mode 100644 index 0000000..56dc9bd --- /dev/null +++ b/src/test/java/com/monstarmike/tlmreader/datablock/TemperatureBlockTest.java @@ -0,0 +1,26 @@ +package com.monstarmike.tlmreader.datablock; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import com.monstarmike.tlmreader.DataBlockBuilder; + +public class TemperatureBlockTest { + + private static final short TEMPERATURE_DATABLOCK_MAKER = (short) 0x0200; + + @Test + public void testGetTemperatureInFahrenheit() { + byte[] testBlock = new DataBlockBuilder(0, TEMPERATURE_DATABLOCK_MAKER).setValue(87, 0x6).get(); + TemperatureBlock block = (TemperatureBlock) DataBlock.createDataBlock(testBlock, null); + assertEquals(87 , block.getTemperatureInFahrenheit()); + } + + @Test + public void testGetTemperatureInCelsius() { + byte[] testBlock = new DataBlockBuilder(0, TEMPERATURE_DATABLOCK_MAKER).setValue(87, 0x6).get(); + TemperatureBlock block = (TemperatureBlock) DataBlock.createDataBlock(testBlock, null); + assertEquals(((87 - 32) / 1.8f) , block.getTemperatureInThenthGradCelsius() * block.getMeasurementFactors().get(0), 0.1); + } +} diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/VoltageBlockTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/VoltageBlockTest.java new file mode 100644 index 0000000..04db62b --- /dev/null +++ b/src/test/java/com/monstarmike/tlmreader/datablock/VoltageBlockTest.java @@ -0,0 +1,19 @@ +package com.monstarmike.tlmreader.datablock; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import com.monstarmike.tlmreader.DataBlockBuilder; + +public class VoltageBlockTest { + + private static final short VOLTAGE_DATABLOCK_MAKER = (short) 0x0100; + + @Test + public void testGetVoltage() { + byte[] testBlock = new DataBlockBuilder(0, VOLTAGE_DATABLOCK_MAKER).setValue(45, 0x6).get(); + VoltageBlock block = (VoltageBlock) DataBlock.createDataBlock(testBlock, null); + assertEquals(45 * 0.1 , block.getVoltsInTenthOfVolt() * block.getMeasurementFactors().get(0), 0.1); + } +} diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/SignalNormalizerTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/SignalNormalizerTest.java index d268838..4c4ecd7 100644 --- a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/SignalNormalizerTest.java +++ b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/SignalNormalizerTest.java @@ -12,7 +12,7 @@ import com.monstarmike.tlmreader.DataBlockBuilder; import com.monstarmike.tlmreader.datablock.DataBlock; import com.monstarmike.tlmreader.datablock.HeaderRxBlock; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; public class SignalNormalizerTest { @@ -43,7 +43,7 @@ private List createBlocks(final int... values) { private DataBlock createRx(int timestamp, int a) { final byte[] testBlock = new DataBlockBuilder(timestamp, 0).setValue(a, POS_A).get(); - return new RXBlock(testBlock); + return new RxBlock(testBlock); } } diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/DiscountinuousBlocksProcessorTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/DiscountinuousBlocksProcessorTest.java index 17950bc..988ef05 100644 --- a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/DiscountinuousBlocksProcessorTest.java +++ b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/DiscountinuousBlocksProcessorTest.java @@ -8,13 +8,13 @@ import org.junit.Test; import org.mockito.Mockito; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; public class DiscountinuousBlocksProcessorTest { @Test public void testShortHighJumpDown() { - final List blocks = createBlocks(5000, 234); + final List blocks = createBlocks(5000, 234); final List expectedBad = Arrays.asList(true, false); List actualBad = process(new DiscountinuousBlocksProcessor(), blocks); Assert.assertEquals(expectedBad, actualBad); @@ -22,7 +22,7 @@ public void testShortHighJumpDown() { @Test public void testLongHighJumpDown() { - final List blocks = createBlocks(5000, 5000, 234); + final List blocks = createBlocks(5000, 5000, 234); final List expectedBad = Arrays.asList(true, true, false); List actualBad = process(new DiscountinuousBlocksProcessor(), blocks); Assert.assertEquals(expectedBad, actualBad); @@ -30,7 +30,7 @@ public void testLongHighJumpDown() { @Test public void testJumpUpShortHigh() { - final List blocks = createBlocks(234, 5000); + final List blocks = createBlocks(234, 5000); final List expectedBad = Arrays.asList(false, true); List actualBad = process(new DiscountinuousBlocksProcessor(), blocks); Assert.assertEquals(expectedBad, actualBad); @@ -38,7 +38,7 @@ public void testJumpUpShortHigh() { @Test public void testJumpUpLongHigh() { - final List blocks = createBlocks(234, 5000, 5000); + final List blocks = createBlocks(234, 5000, 5000); final List expectedBad = Arrays.asList(false, true, true); List actualBad = process(new DiscountinuousBlocksProcessor(), blocks); Assert.assertEquals(expectedBad, actualBad); @@ -46,7 +46,7 @@ public void testJumpUpLongHigh() { @Test public void testJumpUpShortHighJumpDown() { - final List blocks = createBlocks(234, 5000, 235); + final List blocks = createBlocks(234, 5000, 235); final List expectedBad = Arrays.asList(false, true, false); List actualBad = process(new DiscountinuousBlocksProcessor(), blocks); Assert.assertEquals(expectedBad, actualBad); @@ -55,7 +55,7 @@ public void testJumpUpShortHighJumpDown() { @Test public void testJumpUpLongHighJumpDown() { - final List blocks = createBlocks(234, 5000, 5000, 235); + final List blocks = createBlocks(234, 5000, 5000, 235); final List expectedBad = Arrays.asList(false, true, true, false); List actualBad = process(new DiscountinuousBlocksProcessor(), blocks); Assert.assertEquals(expectedBad, actualBad); @@ -63,7 +63,7 @@ public void testJumpUpLongHighJumpDown() { @Test public void testShortHighJumpDownJumpUpJumpDown() { - final List blocks = createBlocks(5000, 236, 5000, 237); + final List blocks = createBlocks(5000, 236, 5000, 237); final List expectedBad = Arrays.asList(true, false, true, false); List actualBad = process(new DiscountinuousBlocksProcessor(), blocks); Assert.assertEquals(expectedBad, actualBad); @@ -71,7 +71,7 @@ public void testShortHighJumpDownJumpUpJumpDown() { @Test public void testJumpUpJumpDown() { - final List blocks = createBlocks(236, 5000, 5000, 5000, 5000, 237, 238, 5000, 5000); + final List blocks = createBlocks(236, 5000, 5000, 5000, 5000, 237, 238, 5000, 5000); final List expectedBad = Arrays.asList(false, true, true, true, true, false, false, true, true); List actualBad = process(new DiscountinuousBlocksProcessor(), blocks); Assert.assertEquals(expectedBad, actualBad); @@ -79,7 +79,7 @@ public void testJumpUpJumpDown() { @Test public void testJumpUpJumpUpJumpDownJumpDown() { - final List blocks = createBlocks(236, 5000, 10000, 5000, 237, 238); + final List blocks = createBlocks(236, 5000, 10000, 5000, 237, 238); final List expectedBad = Arrays.asList(false, true, true, true, false, false); List actualBad = process(new DiscountinuousBlocksProcessor(), blocks); Assert.assertEquals(expectedBad, actualBad); @@ -87,7 +87,7 @@ public void testJumpUpJumpUpJumpDownJumpDown() { @Test public void testJumpUpJumpUpJumpDownOk() { - final List blocks = createBlocks(236, 5000, 10000, 237, 5000); + final List blocks = createBlocks(236, 5000, 10000, 237, 5000); final List expectedBad = Arrays.asList(false, true, true, false, true); List actualBad = process(new DiscountinuousBlocksProcessor(), blocks); Assert.assertEquals(expectedBad, actualBad); @@ -95,7 +95,7 @@ public void testJumpUpJumpUpJumpDownOk() { @Test public void testIgnoreInvalidData() { - final List blocks = createBlocks(236, 65535, 237); + final List blocks = createBlocks(236, 65535, 237); Mockito.when(blocks.get(1).hasValidDataLostPacketsReceiverA()).thenReturn(Boolean.FALSE); final List expectedBad = Arrays.asList(false, false, false); List actualBad = process(new DiscountinuousBlocksProcessor(), blocks); @@ -104,23 +104,23 @@ public void testIgnoreInvalidData() { @Test public void testGetClassOfDataBlock() { - Assert.assertEquals(RXBlock.class, new DiscountinuousBlocksProcessor().getClassOfDataBlock()); + Assert.assertEquals(RxBlock.class, new DiscountinuousBlocksProcessor().getClassOfDataBlock()); } - private List process(final AbstractProcessor processor, final List blocks) { - for (RXBlock block : blocks) { + private List process(final AbstractProcessor processor, final List blocks) { + for (RxBlock block : blocks) { processor.preprocess(block); } processor.preprocessFinished(); List actual = new ArrayList(); - for (RXBlock block : blocks) { + for (RxBlock block : blocks) { actual.add(processor.isBad(block)); } return actual; } - private List createBlocks(final int... values) { - final List blocks = new ArrayList(); + private List createBlocks(final int... values) { + final List blocks = new ArrayList(); int timestamp = 0; for (final int value : values) { blocks.add(createRxMock(timestamp++, value)); @@ -128,8 +128,8 @@ private List createBlocks(final int... values) { return blocks; } - private RXBlock createRxMock(final int timestamp, final int value) { - final RXBlock mock = Mockito.mock(RXBlock.class); + private RxBlock createRxMock(final int timestamp, final int value) { + final RxBlock mock = Mockito.mock(RxBlock.class); Mockito.when(mock.hasValidDataLostPacketsReceiverA()).thenReturn(Boolean.TRUE); Mockito.when(mock.getLostPacketsReceiverA()).thenReturn((short) value); Mockito.when(mock.getTimestamp()).thenReturn(timestamp); diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidCountsProcessorTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidCountsProcessorTest.java index a47186a..82ac3ee 100644 --- a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidCountsProcessorTest.java +++ b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidCountsProcessorTest.java @@ -8,7 +8,7 @@ import org.junit.Test; import org.mockito.Mockito; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; public class InvalidCountsProcessorTest { @@ -16,7 +16,7 @@ public class InvalidCountsProcessorTest { public void testSpikeLessThanTenPercentBLR() { boolean[] normal = new boolean[] { true, false, false, false }; boolean[] spike = new boolean[] { true, true, true, true }; - final List blocks = createBlocks(normal, normal, normal, normal, normal, normal, normal, spike, normal, + final List blocks = createBlocks(normal, normal, normal, normal, normal, normal, normal, spike, normal, normal, normal); final List expectedBad = Arrays.asList(false, false, false, false, false, false, false, true, false, false, false); @@ -28,7 +28,7 @@ public void testSpikeLessThanTenPercentBLR() { public void testSpikeLessThanTenPercentA() { boolean[] normal = new boolean[] { false, true,true,true }; boolean[] spike = new boolean[] { true, true, true, true }; - final List blocks = createBlocks(normal, normal, normal, normal, normal, normal, normal, spike, normal, + final List blocks = createBlocks(normal, normal, normal, normal, normal, normal, normal, spike, normal, normal, normal); final List expectedBad = Arrays.asList(false, false, false, false, false, false, false, true, false, false, false); @@ -40,7 +40,7 @@ public void testSpikeLessThanTenPercentA() { public void testSpikesMoreThanTenPercent() { boolean[] normal = new boolean[] { true, false, false, false }; boolean[] spike = new boolean[] { true, true, true, true }; - final List blocks = createBlocks(normal, normal, normal, normal, normal, normal, normal, spike); + final List blocks = createBlocks(normal, normal, normal, normal, normal, normal, normal, spike); final List expectedBad = Arrays.asList(false, false, false, false, false, false, false, false); List actualBad = process(new InvalidCountsProcessor(), blocks); Assert.assertEquals(expectedBad, actualBad); @@ -50,7 +50,7 @@ public void testSpikesMoreThanTenPercent() { public void testIgnoreInvalidData() { boolean[] normal = new boolean[] { true, false, false, false }; boolean[] invalid = new boolean[] { false, false, false, false }; - final List blocks = createBlocks(normal, normal, invalid, normal); + final List blocks = createBlocks(normal, normal, invalid, normal); final List expectedBad = Arrays.asList(false, false, true, false); List actualBad = process(new InvalidCountsProcessor(), blocks); Assert.assertEquals(expectedBad, actualBad); @@ -58,23 +58,23 @@ public void testIgnoreInvalidData() { @Test public void testGetClassOfDataBlock() { - Assert.assertEquals(RXBlock.class, new InvalidCountsProcessor().getClassOfDataBlock()); + Assert.assertEquals(RxBlock.class, new InvalidCountsProcessor().getClassOfDataBlock()); } - private List process(final AbstractProcessor processor, final List blocks) { - for (RXBlock block : blocks) { + private List process(final AbstractProcessor processor, final List blocks) { + for (RxBlock block : blocks) { processor.preprocess(block); } processor.preprocessFinished(); List actual = new ArrayList(); - for (RXBlock block : blocks) { + for (RxBlock block : blocks) { actual.add(processor.isBad(block)); } return actual; } - private List createBlocks(final boolean[]... hasValidDataList) { - final List blocks = new ArrayList(); + private List createBlocks(final boolean[]... hasValidDataList) { + final List blocks = new ArrayList(); int timestamp = 0; for (final boolean[] hasValidDatas : hasValidDataList) { blocks.add(createRxMock(timestamp++, hasValidDatas)); @@ -82,8 +82,8 @@ private List createBlocks(final boolean[]... hasValidDataList) { return blocks; } - private RXBlock createRxMock(final int timestamp, final boolean[] hasValidDatas) { - final RXBlock mock = Mockito.mock(RXBlock.class); + private RxBlock createRxMock(final int timestamp, final boolean[] hasValidDatas) { + final RxBlock mock = Mockito.mock(RxBlock.class); Mockito.when(mock.hasValidDataLostPacketsReceiverA()).thenReturn(hasValidDatas[0]); Mockito.when(mock.hasValidDataLostPacketsReceiverB()).thenReturn(hasValidDatas[1]); Mockito.when(mock.hasValidDataLostPacketsReceiverL()).thenReturn(hasValidDatas[2]); diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidDataBlocksProcessorTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidDataBlocksProcessorTest.java index 31ab9b1..e9770e5 100644 --- a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidDataBlocksProcessorTest.java +++ b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/InvalidDataBlocksProcessorTest.java @@ -8,15 +8,15 @@ import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; @RunWith(MockitoJUnitRunner.class) public class InvalidDataBlocksProcessorTest { @Mock - private RXBlock validRxBlock; + private RxBlock validRxBlock; @Mock - private RXBlock invalidRxBlock; + private RxBlock invalidRxBlock; @Before public void setup() { @@ -40,7 +40,7 @@ public void testGetClassOfDataBlock() { InvalidDataBlocksProcessor processor = new InvalidDataBlocksProcessor(); processor.preprocess(null); processor.preprocessFinished(); - Assert.assertEquals(RXBlock.class, processor.getClassOfDataBlock()); + Assert.assertEquals(RxBlock.class, processor.getClassOfDataBlock()); } } diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/ProcessorEvaluatorTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/ProcessorEvaluatorTest.java index 4c175ba..bbcf795 100644 --- a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/ProcessorEvaluatorTest.java +++ b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/ProcessorEvaluatorTest.java @@ -14,7 +14,7 @@ import com.monstarmike.tlmreader.DataBlockBuilder; import com.monstarmike.tlmreader.datablock.DataBlock; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; import com.monstarmike.tlmreader.datablock.VoltageBlock; @RunWith(MockitoJUnitRunner.class) @@ -23,69 +23,69 @@ public class ProcessorEvaluatorTest { private static final int POS_A = 0x06; @Mock - AbstractProcessor processorMock; + AbstractProcessor processorMock; @Test public void testProcessWithRxTypeDataBlocks() { - Mockito.when(processorMock.getClassOfDataBlock()).thenAnswer(new Answer>() { + Mockito.when(processorMock.getClassOfDataBlock()).thenAnswer(new Answer>() { - public Class answer(InvocationOnMock invocation) throws Throwable { - return RXBlock.class; + public Class answer(InvocationOnMock invocation) throws Throwable { + return RxBlock.class; } });; List dataBlocks = new ArrayList(); dataBlocks.add(createRx(0, 65535)); dataBlocks.add(createRx(1, 234)); - ProcessorEvaluator genericProcessor = new ProcessorEvaluator(); + ProcessorEvaluator genericProcessor = new ProcessorEvaluator(); genericProcessor.registerProcessor(processorMock); genericProcessor.process(dataBlocks); - Mockito.verify(processorMock, Mockito.times(2)).preprocess(Mockito.any(RXBlock.class));; - Mockito.verify(processorMock, Mockito.times(2)).isBad(Mockito.any(RXBlock.class));; + Mockito.verify(processorMock, Mockito.times(2)).preprocess(Mockito.any(RxBlock.class));; + Mockito.verify(processorMock, Mockito.times(2)).isBad(Mockito.any(RxBlock.class));; Mockito.verify(processorMock, Mockito.times(1)).preprocessFinished(); } @Test public void testProcessWithMixedTypeDataBlocks() { - Mockito.when(processorMock.getClassOfDataBlock()).thenAnswer(new Answer>() { + Mockito.when(processorMock.getClassOfDataBlock()).thenAnswer(new Answer>() { - public Class answer(InvocationOnMock invocation) throws Throwable { - return RXBlock.class; + public Class answer(InvocationOnMock invocation) throws Throwable { + return RxBlock.class; } });; List dataBlocks = new ArrayList(); dataBlocks.add(createRx(0, 65535)); dataBlocks.add(createVoltage(1)); - ProcessorEvaluator genericProcessor = new ProcessorEvaluator(); + ProcessorEvaluator genericProcessor = new ProcessorEvaluator(); genericProcessor.registerProcessor(processorMock); genericProcessor.process(dataBlocks); - Mockito.verify(processorMock, Mockito.times(1)).preprocess(Mockito.any(RXBlock.class));; - Mockito.verify(processorMock, Mockito.times(1)).isBad(Mockito.any(RXBlock.class));; + Mockito.verify(processorMock, Mockito.times(1)).preprocess(Mockito.any(RxBlock.class));; + Mockito.verify(processorMock, Mockito.times(1)).isBad(Mockito.any(RxBlock.class));; Mockito.verify(processorMock, Mockito.times(1)).preprocessFinished(); } @Test public void testProcessCheckIsBad() { - Mockito.when(processorMock.getClassOfDataBlock()).thenAnswer(new Answer>() { + Mockito.when(processorMock.getClassOfDataBlock()).thenAnswer(new Answer>() { - public Class answer(InvocationOnMock invocation) throws Throwable { - return RXBlock.class; + public Class answer(InvocationOnMock invocation) throws Throwable { + return RxBlock.class; } });; - Mockito.when(processorMock.isBad(Mockito.any(RXBlock.class))).thenReturn(Boolean.TRUE); + Mockito.when(processorMock.isBad(Mockito.any(RxBlock.class))).thenReturn(Boolean.TRUE); List dataBlocks = new ArrayList(); dataBlocks.add(createRx(0, 65535)); - ProcessorEvaluator genericProcessor = new ProcessorEvaluator(); + ProcessorEvaluator genericProcessor = new ProcessorEvaluator(); genericProcessor.registerProcessor(processorMock); genericProcessor.process(dataBlocks); - Mockito.verify(processorMock, Mockito.times(1)).preprocess(Mockito.any(RXBlock.class));; - Mockito.verify(processorMock, Mockito.times(1)).isBad(Mockito.any(RXBlock.class));; + Mockito.verify(processorMock, Mockito.times(1)).preprocess(Mockito.any(RxBlock.class));; + Mockito.verify(processorMock, Mockito.times(1)).isBad(Mockito.any(RxBlock.class));; Mockito.verify(processorMock, Mockito.times(1)).preprocessFinished(); Assert.assertTrue(dataBlocks.isEmpty()); } private DataBlock createRx(int timestamp, int a) { final byte[] testBlock = new DataBlockBuilder(timestamp, 0).setValue(a, POS_A).get(); - return new RXBlock(testBlock); + return new RxBlock(testBlock); } private DataBlock createVoltage(int timestamp) { diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/RedundantDataBlocksProcessorTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/RedundantDataBlocksProcessorTest.java index 4b87820..ef43581 100644 --- a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/RedundantDataBlocksProcessorTest.java +++ b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/RedundantDataBlocksProcessorTest.java @@ -9,7 +9,7 @@ import org.mockito.Mockito; import com.monstarmike.tlmreader.datablock.DataBlock; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; import com.monstarmike.tlmreader.datablock.StandardBlock; public class RedundantDataBlocksProcessorTest { @@ -59,7 +59,7 @@ private List createBlocks(final boolean... equalsToLastList) { } private DataBlock createRxMock(final int timestamp, final boolean equalsToLast) { - final DataBlock mock = Mockito.mock(RXBlock.class); + final DataBlock mock = Mockito.mock(RxBlock.class); Mockito.when(mock.areValuesEquals(Mockito.any(DataBlock.class))).thenReturn(equalsToLast); Mockito.when(mock.getTimestamp()).thenReturn(timestamp); Mockito.when(mock.getSequence()).thenReturn(timestamp); diff --git a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/SpectrumTelemetryDetectorTest.java b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/SpectrumTelemetryDetectorTest.java index ddb8f99..04862cb 100644 --- a/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/SpectrumTelemetryDetectorTest.java +++ b/src/test/java/com/monstarmike/tlmreader/datablock/normalizer/processor/SpectrumTelemetryDetectorTest.java @@ -7,13 +7,13 @@ import org.junit.Test; import org.mockito.Mockito; -import com.monstarmike.tlmreader.datablock.RXBlock; +import com.monstarmike.tlmreader.datablock.RxBlock; public class SpectrumTelemetryDetectorTest { @Test public void testIsSpectrumTelemetry() { - final List blocks = createBlocks(0, 1, 1, 7, 10, 500, 10); + final List blocks = createBlocks(0, 1, 1, 7, 10, 500, 10); SpectrumTelemetryDetector processor = new SpectrumTelemetryDetector(); process(processor, blocks); Assert.assertTrue(processor.isSpectrumTelemetry()); @@ -21,7 +21,7 @@ public void testIsSpectrumTelemetry() { @Test public void testIsNotSpectrumTelemetry() { - final List blocks = createBlocks(100,100,95,90,100,95,40,30,90,100); + final List blocks = createBlocks(100,100,95,90,100,95,40,30,90,100); SpectrumTelemetryDetector processor = new SpectrumTelemetryDetector(); process(processor, blocks); Assert.assertFalse(processor.isSpectrumTelemetry()); @@ -29,7 +29,7 @@ public void testIsNotSpectrumTelemetry() { @Test public void testIsNotSpectrumTelemetryIgnoreInvalid() { - final List blocks = createBlocks(-1,-1,-1,-1,-1,-1,100,70,90,100); + final List blocks = createBlocks(-1,-1,-1,-1,-1,-1,100,70,90,100); Mockito.when(blocks.get(0).hasValidDataLostPacketsReceiverA()).thenReturn(Boolean.FALSE); Mockito.when(blocks.get(1).hasValidDataLostPacketsReceiverA()).thenReturn(Boolean.FALSE); Mockito.when(blocks.get(2).hasValidDataLostPacketsReceiverA()).thenReturn(Boolean.FALSE); @@ -43,23 +43,23 @@ public void testIsNotSpectrumTelemetryIgnoreInvalid() { @Test public void testGetClassOfDataBlock() { - Assert.assertEquals(RXBlock.class, new SpectrumTelemetryDetector().getClassOfDataBlock()); + Assert.assertEquals(RxBlock.class, new SpectrumTelemetryDetector().getClassOfDataBlock()); } - private List process(final AbstractProcessor processor, final List blocks) { - for (RXBlock block : blocks) { + private List process(final AbstractProcessor processor, final List blocks) { + for (RxBlock block : blocks) { processor.preprocess(block); } processor.preprocessFinished(); List actual = new ArrayList(); - for (RXBlock block : blocks) { + for (RxBlock block : blocks) { actual.add(processor.isBad(block)); } return actual; } - private List createBlocks(final int... values) { - final List blocks = new ArrayList(); + private List createBlocks(final int... values) { + final List blocks = new ArrayList(); int timestamp = 0; for (final int value : values) { blocks.add(createRxMock(timestamp++, value)); @@ -67,8 +67,8 @@ private List createBlocks(final int... values) { return blocks; } - private RXBlock createRxMock(final int timestamp, final int value) { - final RXBlock mock = Mockito.mock(RXBlock.class); + private RxBlock createRxMock(final int timestamp, final int value) { + final RxBlock mock = Mockito.mock(RxBlock.class); Mockito.when(mock.hasValidDataLostPacketsReceiverA()).thenReturn(Boolean.TRUE); Mockito.when(mock.getLostPacketsReceiverA()).thenReturn((short) value); Mockito.when(mock.getTimestamp()).thenReturn(timestamp);