/* * BVEParser.java * Copyright (C) 2013 Robert Huitema * * This file is derived from Java Marine API. * <http://ktuukkan.github.io/marine-api/> * * Java Marine API is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * This file is part of FreeBoard. (http://www.42.co.nz/freeboard) * * FreeBoard is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * FreeBoard is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with FreeBoard. If not, see <http://www.gnu.org/licenses/>. * * This implementation of the CruzPro PBVE sentence provided by R T Huitema (www.42.co.nz/FreeBoard) * cos I need it for FreeBoard :-) * * The following CruzPro instruments use the "$PBVE" proprietary NMEA sentences * assigned to BV Engineering (CruzPro Ltd.) by the National Marine Electronics * Association: 4800 BAUD, 8 bits, one start bit, one stop bit, no parity * * FU30/FU60 digital fuel gauge * T30/T60 digital engine temperature gauge * OP30/OP60 digital oil pressure gauge * RH30/RH60/RH110 digital RPM gauge/ Engine hours gauge/alarm * EH60 Engine Hours Gauge * CH30/CH60 Chain Counter * CT30/CT60 Ships Clock/Timer * EH60 Engine Hours Gauge * * The proprietary sentences are used because NMEA has never assigned standard * sentences that fit these type instruments well. * * * FU30/FU60 digital fuel gauge * Sample decoding: * * $PBVE,FCIEADCIAAJJAFFA * * Parse as: * $PBVE, F C IEAD CIAA JJAF FA * * Where: * * F = Product Designator F=FU30/FU60 * C = Software Version # * IEAD = Fuel Use Rate (Units per hour) * CIAA = Fuel used this trip (trip fuel) * JJAF = Fuel Remaining * FA = Checksum * * and A=0, B=1, C=2, ... , O=14, P=15 * * So: * * IEAD decodes to 16*I + E + 4096*A + 256*D * IEAD = 16*8 + 4 + 4096*0 + 256*3 * IEAD = 132 + 768 = 900 = 90.0 units per hour * * CIAA decodes to 16*C + I + 4096*A +256* A * CIAA = 16*2 + 8 + 4096*0 + 256*0 * CIAA = 40+0=4.0 units used for this trip so far * * JJAF decodes to 16*J + J + 4096*A + 256*F * JJAF = 16*9 + 9 + 4096*0 + 256*5 * JJAF = 153 + 1280 = 1433 = 143.3 units of fuel remaining */ package net.sf.marineapi.nmea.parser; import net.sf.marineapi.nmea.sentence.BVESentence; import net.sf.marineapi.nmea.sentence.TalkerId; /** * BVE sentence parser. * * @author Robert Huitema */ public class BVEParser extends SentenceParser implements BVESentence { // types public static final String CHAIN_COUNTER = "A"; public static final String ENGINE = "B"; public static final String SHIPS_CLOCK = "C"; public static final String PRESSURE = "D"; public static final String ENGINE_TEMP = "E"; public static final String FUEL_GUAGE = "F"; // field indexes //private static final int PRODUCT_DESIGNATOR = 0; private static final int FUEL_USE_RATE = 2; private static final int FUEL_USED_TRIP = 6; private static final int FUEL_REMAINING = 10; private static final int TEMP_UNITS_OF_MEASURE = 14;//2 private static final int TEMP_HIGH_ALARM = 22; private static final int TEMP_LOW_ALARM = 18; private static final int TEMP = 28; private static final int VOLTAGE = 32; private static final int PRESSURE_UNITS = 14; private static final int LOW_PRESSURE_ALARM = 18; private static final int HIGH_PRESSURE_ALARM = 22; private static final int CURRENT_PRESSURE=28; private static final int MAX_RPM = 10; private static final int HIGH_RPM_ALARM = 14; private static final int MAINT_COUNTDOWN = 24; private static final int ENGINE_MINUTES = 28; private static final int ENGINE_HOURS = 30; private static final int RPM=42; public String type = null; /** * Constructor. * * @param output * BVE sentence string */ public BVEParser(String nmea) { // has no *checksum super(nmea, "BVE"); type = getStringValue(0).substring(0,1); } /** * Creates BVE parser with empty sentence. * * @param talker * TalkerId to set */ public BVEParser(TalkerId talker) { super(talker, "BVE", 1); } public boolean isFuelGuage(){ if(FUEL_GUAGE.equals(type))return true; return false; } public boolean isTempGuage(){ if(ENGINE_TEMP.equals(type))return true; return false; } public boolean isPressureGuage(){ if(PRESSURE.equals(type))return true; return false; } public boolean isEngineRpm(){ if(ENGINE.equals(type))return true; return false; } public float getFuelUseRateUnitsPerHour() { String rate = getStringValue(0).substring(FUEL_USE_RATE, FUEL_USE_RATE + 4); return getFloatFromCruzPro(rate); } public float getFuelUsedOnTrip() { String used = getStringValue(0).substring(FUEL_USED_TRIP, FUEL_USED_TRIP + 4); return getFloatFromCruzPro(used); } public float getFuelRemaining() { String remains = getStringValue(0).substring(FUEL_REMAINING, FUEL_REMAINING + 4); return getFloatFromCruzPro(remains); } public String getType() { return type; } public int getTempUnitsOfMeasure() { String temp = getStringValue(0).substring(TEMP_UNITS_OF_MEASURE, TEMP_UNITS_OF_MEASURE + 2); return getShortFromCruzPro(temp); } public int getLowTempAlarmValue() { String temp = getStringValue(0).substring(TEMP_LOW_ALARM, TEMP_LOW_ALARM + 4); return getIntFromCruzPro(temp); } public int getHighTempAlarmValue() { String temp = getStringValue(0).substring(TEMP_HIGH_ALARM, TEMP_HIGH_ALARM + 4); return getIntFromCruzPro(temp); } public int getEngineTemp() { String temp = getStringValue(0).substring(TEMP, TEMP + 4); return getIntFromCruzPro(temp); } public float getVoltage() { String volt = getStringValue(0).substring(VOLTAGE, VOLTAGE + 4); float v = getFloatFromCruzPro(volt); if (v == 0) return 0; return v / 10; } public int getPressureUnitsOfMeasure() { String temp = getStringValue(0).substring(PRESSURE_UNITS, PRESSURE_UNITS + 2); return getShortFromCruzPro(temp); } public int getLowPressureAlarmValue() { String temp = getStringValue(0).substring(LOW_PRESSURE_ALARM, LOW_PRESSURE_ALARM + 4); return getIntFromCruzPro(temp); } public int getHighPressureAlarmValue() { String temp = getStringValue(0).substring(HIGH_PRESSURE_ALARM, HIGH_PRESSURE_ALARM + 4); return getIntFromCruzPro(temp); } public int getPressure() { String temp = getStringValue(0).substring(CURRENT_PRESSURE, CURRENT_PRESSURE + 4); return getIntFromCruzPro(temp); } public int getMaximumRpmSinceReset() { String temp = getStringValue(0).substring(MAX_RPM, MAX_RPM + 4); return getIntFromCruzPro(temp); } public int getHighRpmAlarmValue() { String rpm = getStringValue(0).substring(HIGH_RPM_ALARM, HIGH_RPM_ALARM + 4); return getIntFromCruzPro(rpm); } public int getMaintenanceCountdownAlarm() { String alarm = getStringValue(0).substring(MAINT_COUNTDOWN, MAINT_COUNTDOWN + 4); return getIntFromCruzPro(alarm); } public int getEngineHours() { String hrs = getStringValue(0).substring(ENGINE_HOURS, ENGINE_HOURS + 4); return getIntFromCruzPro(hrs); } public int getEngineMinutes() { String min = getStringValue(0).substring(ENGINE_MINUTES, ENGINE_MINUTES + 2); return getShortFromCruzPro(min); } public int getEngineRpm() { String rpm = getStringValue(0).substring(RPM, RPM + 4); return getIntFromCruzPro(rpm); } /** * Cruzpro alpha format: * eg * IEAD decodes to 16*I + E + 4096*A + 256*D * IEAD = 16*8 + 4 + 4096*0 + 256*3 * IEAD = 132 + 768 = 900 = 90.0 units per hour * * @param str * @return */ private float getFloatFromCruzPro(String str) { float result = getIntFromCruzPro(str); if (result == 0) return 0; return result / 10; } /** * Cruzpro alpha format: * eg * IEAD decodes to 16*I + E + 4096*A + 256*D * IEAD = 16*8 + 4 + 4096*0 + 256*3 * IEAD = 132 + 768 = 900 * * @param str * @return */ private int getIntFromCruzPro(String str) { // 'A' is 65 decimal, '0' in cruzpro char[] chars = str.toCharArray(); // first char return ((chars[0] - 65) * 16) + (chars[1] - 65) + ((chars[2] - 65) * 4096) + ((chars[3] - 65) * 256); } private int getShortFromCruzPro(String str) { // 'A' is 65 decimal, '0' in cruzpro char[] chars = str.toCharArray(); // first char return ((chars[0] - 65) * 16) + (chars[1] - 65) ; } }