/*
* ShareNav - Copyright (c) 2007 Harald Mueller james22 at users dot sourceforge dot net
* See file COPYING.
*/
package net.sharenav.gps.location;
import net.sharenav.gps.Satellite;
import net.sharenav.sharenav.data.Position;
import net.sharenav.util.Logger;
public class SirfMessage {
public byte[] readBuffer = new byte[1023];
Position pold;
public int length = 0;
private final LocationMsgReceiver receiver;
//#debug
private final static Logger logger = Logger.getInstance(SirfInput.class,Logger.DEBUG);
public SirfMessage(LocationMsgReceiver receiver) {
this.receiver = receiver;
}
public SirfMessage(byte[] readBuffer,LocationMsgReceiver receiver) {
this.receiver=receiver;
this.readBuffer = readBuffer;
length = readBuffer.length;
}
public int getByte(int i) {
int buf = readBuffer[i];
if (buf < 0) {
buf = (buf + 256);
}
return buf;
}
public int getMessageId() {
return readBuffer[0];
}
// public short get2Byte(int i) {
// return (short) ((readBuffer[i] << 8) | readBuffer[i+1]);
// return (short) (getByte(i) <<8 | getByte(i + 1));
// }
// public int get2ByteUnsigned(int i) {
//// return (getByte(i) * 256 + getByte(i + 1));
// return((getByte(i) << 8) | getByte(i+1));
// }
public int get2ByteUnsigned(int i) {
return ((((readBuffer[i]+256)&0xff) << 8)
| ((readBuffer[i+1]+256)&0xff));
}
public short get2Byte(int i) {
return (short)((((readBuffer[i]+256)&0xff) << 8)
| ((readBuffer[i+1]+256)&0xff));
}
// public int get4Byte(int i) {
// return (getByte(i) * 16777216 + getByte(i + 1) * 65536 + getByte(i + 2) * 256 + getByte(i + 3));
// return ((getByte(i) << 24) | (getByte(i + 1) << 16) | (getByte(i + 2) << 8) | getByte(i + 3));
// }
public int get4Byte(int i) {
return ((((readBuffer[i]+256)&0xff) << 24)
| (((readBuffer[i+1]+256)&0xff) << 16)
| (((readBuffer[i+2]+256)&0xff) << 8)
| ((readBuffer[i+3]+256)&0xff));
}
public String decodeMsg(SirfMessage smsg) {
int type = smsg.getMessageId();
//#debug debug
logger.debug("Sirf:" + type);
switch (type) {
case 2:
return decodeMeasureNavigation();
case 4:
return decodeMeasuredTrackerDataOut();
// case 6:
// return decodeSoftwareVersion();
// case 9:
// return decodeThroughput();
// case 11:
// return decodeCommandAck();
// case 12:
// return decodeCommandNack();
case 41:
return decodeGeodeticNavigationData();
}
// return message("msg " + type + " not implemented");
return null;
}
private String decodeMeasuredTrackerDataOut() {
int anz = getByte(7);
Satellite sats[] = new Satellite[anz];
for (int l = 0; l < anz; l++) {
sats[l] = decode1sMeasuredTrackerDataOut(8 + l * 15);
}
// pcs.firePropertyChange("SatelitData",null,s);
receiver.receiveSatellites(sats);
return null;
}
private Satellite decode1sMeasuredTrackerDataOut(int i) {
Satellite s = new Satellite();
s.id = getByte(i++);
s.azimut = getByte(i++)*1.5f;
s.elev = getByte(i++)/2f;
s.state = get2ByteUnsigned(i);
i += 2;
// take only the first of the signal to noise ratio
s.snr = getByte(i++);
return s;
}
private String decodeThroughput() {
return null;
// return "Throughput SegStatMax:"+(1d*get2ByteUnsigned(1)/186d)+" last ms: "+(1d*get2ByteUnsigned(7)/186d);
}
private String decodeSoftwareVersion() {
return message(new String(readBuffer));
}
private String decodeCommandNack() {
return message("Not OK for Message " + getByte(1));
}
private String decodeCommandAck() {
return message("OK for Message " + getByte(1));
}
private String decodeGeodeticNavigationData() {
short valid = get2Byte(1);
// short type = get2Byte(3);
// short eWeekNr = get2Byte(5);
// int two = get4Byte(7);
short year = get2Byte(11);
short month = (short) getByte(13);
short day = (short) getByte(14);
short hour = (short) getByte(15);
short min = (short) getByte(16);
double second = 1d * get2ByteUnsigned(17) / 1000d;
// int satIdList = get4Byte(19);
double lat = getDeg(23);
double lon = getDeg(27);
// double altEl = getMeter(31);
double altMSL = getMeter(35);
// short mapDatum = getByte(39);
double sog = 0.01d * get2ByteUnsigned(40);
double course = 0.01d * get2ByteUnsigned(42);
// Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
// cal.set(Calendar.YEAR, year);
// cal.set(Calendar.MONTH, month - 1);
// cal.set(Calendar.DAY_OF_MONTH, day);
// cal.set(Calendar.HOUR_OF_DAY, hour);
// cal.set(Calendar.MINUTE, min);
// cal.set(Calendar.SECOND, (int) second);
// TODO: Is HDOP available here as well?
Position p = new Position((float) lat, (float) lon, (float) altMSL, (float) sog,
(float) course, valid, System.currentTimeMillis());
receiver.receivePosition(p);
pold = p;
return null;
// return message("" + day + "." + month + "." + year + " " + hour + ":" + min + ":" + second + " Lat=" + lat + " lon=" + lon + " h=" + altMSL + " sog=" + sog);
}
private double getMeter(int i) {
return (0.01d * get4Byte(i));
}
private double getDeg(int i) {
// return (get4Byte(i) * 1.0d / 10000000d);
return (get4Byte(i) * .0000001d );
}
private String decodeMeasureNavigation() {
byte status = LocationMsgReceiver.STATUS_NOFIX;
short byte1 = (short)getByte(20);
switch (byte1 & 0x7) {
case 0:
case 1:
case 2:
status = LocationMsgReceiver.STATUS_NOFIX;
break;
case 3: // 3 sat solution
case 5: // 2D point solution
status = LocationMsgReceiver.STATUS_2D;
break;
case 4: // >3 sat solution
case 6: // 3D point solution
status = LocationMsgReceiver.STATUS_3D;
break;
case 7:
// Dead reckoning means there is currently no fix
status = LocationMsgReceiver.STATUS_NOFIX;
break;
}
if ((byte1 & 0x80) > 0){
status = LocationMsgReceiver.STATUS_DGPS;
}
receiver.receiveStatus(status, getByte(28));
return null;
}
private String message(String msg) {
receiver.receiveMessage(msg);
return msg;
}
}