Adapt Traccar Client to GPSgate format

Michael Travis5 years ago

Good Morning,

I have been working on getting the Traccar Client to utilize the GPS TrackerOne protocol. and am currently stuck. I'm assuming it's my own ignorance of SQL or Android, but the app does not update the positions as it should. I would like to run a single piece of software for both of my servers, I have some clients on Traccar as a host it yourself solution and some on GPSgate for a fully flushed and service software integration solution. The program will update and give a full report on SOS send, but not on regular sending.

The Changes I have made to the code are focused on three java files, the Position.java, the DatabaseHelper.java and the ProtocolFormatter.java.

Position.java got some extra dummy variables in order to get the proper date time format and the proper degree minute format.

 public Position(String deviceId, Location location, double battery) {
        this.deviceId = deviceId;
        // Changes to make the Tracker one Format Time
        Date date = new Date(location.getTime());
        time = date;
        DateFormat dateFormat = new SimpleDateFormat("ddMMYY,HHmmss.SS");
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        String preGPSgate = dateFormat.format(date);
        GPSgateTime = preGPSgate;

        //Latitude and Longitude
        //change to get DDMM.mmm format
        double getsLatitude = (location.getLatitude());
        latitude = getsLatitude;
        String preLatitude = location.convert(getsLatitude, location.FORMAT_MINUTES);
        String preLatitude2 = preLatitude.replace(":","");
        double preLatitude3 = Double.parseDouble(preLatitude2);
        GPSgateLatitude = abs(preLatitude3);
        //Repeat change for Longitude
        double getsLongitude = (location.getLongitude());
        longitude = getsLongitude;
        String preLongitude = location.convert(getsLongitude, location.FORMAT_MINUTES);
        String preLongitude2 = preLongitude.replace(":","");
        double preLongitude3 = Double.parseDouble(preLongitude2);
        GPSgateLongitude = abs(preLongitude3);
        //end of changes to traccar variables
        altitude = location.getAltitude();
        speed = location.getSpeed() * 1.943844; // speed in knots
        course = location.getBearing();
        if (location.getProvider() != null && !location.getProvider().equals(LocationManager.GPS_PROVIDER)) {
            accuracy = location.getAccuracy();
        }
        this.battery = battery;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            this.mock = location.isFromMockProvider();
        }
        //Start of additions to the traccar code.
        //get the North South Hemisphere.
        if (getsLatitude < 0) {
            this.NsHem = "S";
        }else {
            this.NsHem = "N";
        }
        //doing the same with East West
        if (getsLongitude < 0){
            this.EwHem = "W";
        }else {
            this.EwHem = "E";
        }
    }

I then added the declaration, set and get methods for the new additions

    //North and south Hemisphere
    private String NsHem;
    public String getNsHem() {
        return NsHem;
    }
    public void setNsHem(String NsHem) {
        this.NsHem = NsHem;
    }
    //East and West Hemisphere
    private String EwHem;
    public String getEwHem() {
        return EwHem;
    }
    public void setEwHem(String EwHem){
        this.EwHem = EwHem;
    }
    private String GPSgateTime;
    public String getGPSgateTime(){
        return GPSgateTime;
    }
    public void setGPSgateTime(String GPSgateTime){
        this.GPSgateTime =GPSgateTime;
    }
    private double GPSgateLatitude;
    public double getGPSgateLatitude() {
        return GPSgateLatitude;
    }
    public void setGPSgateLatitude(double GPSgateLatitude) {
        this.GPSgateLatitude = GPSgateLatitude;
    }
    private double GPSgateLongitude;
    public double getGPSgateLongitude(){
        return GPSgateLongitude;
    }
    public void setGPSgateLongitude(double GPSgateLongitude) {
        this.GPSgateLongitude = GPSgateLongitude;
    }

Next came the Database Helper, Here is where I think I made my mistakes, but I can't find them

I added my fields to the SQLite database creator

    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE position (" +
                "id INTEGER PRIMARY KEY AUTOINCREMENT," +
                "deviceId TEXT," +
                "time INTEGER," +
                "GPSgateTime TEXT," +
                "latitude REAL," +
                "GPSgateLatitude, REAL" +
                "NsHem TEXT," +
                "longitude REAL," +
                "GPSgateLongitude, REAL" +
                "EwHem TEXT," +
                "altitude REAL," +
                "speed REAL," +
                "course REAL," +
                "accuracy REAL," +
                "battery REAL," +
                "mock INTEGER)");
    }

Then added the insert

    public void insertPosition(Position position) {
        ContentValues values = new ContentValues();
        values.put("deviceId", position.getDeviceId());
        values.put("time", position.getTime().getTime());
        values.put("GPSgateTime", position.getGPSgateTime());
        values.put("latitude", position.getLatitude());
        values.put("GPSgateLatitude", position.getGPSgateLatitude());
        values.put("NsHem", position.getNsHem());
        values.put("longitude", position.getLongitude());
        values.put("GPSgateLongitude", position.getGPSgateLongitude());
        values.put("EwHem", position.getEwHem());
        values.put("altitude", position.getAltitude());
        values.put("speed", position.getSpeed());
        values.put("course", position.getCourse());
        values.put("accuracy", position.getAccuracy());
        values.put("battery", position.getBattery());
        values.put("mock", position.getMock() ? 1 : 0);

        db.insertOrThrow("position", null, values);
    }

and then added them to the query

   public Position selectPosition() {
        Position position = new Position();

        Cursor cursor = db.rawQuery("SELECT * FROM position ORDER BY id LIMIT 1", null);
        try {
            if (cursor.getCount() > 0) {
// Added GPSgateTime, GPSgateLatitude, NsHem, GPSgateLongitude, EwHem
                cursor.moveToFirst();

                position.setId(cursor.getLong(cursor.getColumnIndex("id")));
                position.setDeviceId(cursor.getString(cursor.getColumnIndex("deviceId")));
                position.setTime(new Date(cursor.getLong(cursor.getColumnIndex("time"))));
                position.setGPSgateTime(cursor.getString(cursor.getColumnIndex("GPSgateTime")));
                position.setLatitude(cursor.getDouble(cursor.getColumnIndex("latitude")));
                position.setGPSgateLatitude(cursor.getDouble(cursor.getColumnIndex("GPSgateLatitude")));
                position.setNsHem(cursor.getString(cursor.getColumnIndex("NsHem")));
                position.setLongitude(cursor.getDouble(cursor.getColumnIndex("longitude")));
                position.setGPSgateLongitude(cursor.getDouble(cursor.getColumnIndex("GPSgateLongitude")));
                position.setEwHem(cursor.getString(cursor.getColumnIndex("EwHem")));
                position.setAltitude(cursor.getDouble(cursor.getColumnIndex("altitude")));
                position.setSpeed(cursor.getDouble(cursor.getColumnIndex("speed")));
                position.setCourse(cursor.getDouble(cursor.getColumnIndex("course")));
                position.setAccuracy(cursor.getDouble(cursor.getColumnIndex("accuracy")));
                position.setBattery(cursor.getDouble(cursor.getColumnIndex("battery")));
                position.setMock(cursor.getInt(cursor.getColumnIndex("mock")) > 0);

            } else {
                return null;
            }
        } finally {
            cursor.close();
        }

        return position;
    }

The last and most messed up thing I did was change the format request entirely, This was some dirty quick programming to get it into the proper GPSgate protocol with commas being the only special character.

    public static String formatRequest(String url, Position position, String alarm) {
        Uri serverUrl = Uri.parse(url);
        Uri.Builder builder = serverUrl.buildUpon()
                .path("GpsGate/")
                .encodedQuery("cmd=$FRCMD"
                        +"," + position.getDeviceId()
                        +"," + "_SendMessage,"
                        +"," + String.valueOf(position.getGPSgateLatitude())
                        +"," + String.valueOf(position.getNsHem())
                        +","+ String.valueOf(position.getGPSgateLongitude())
                        +","+ String.valueOf(position.getEwHem())
                        +"," + String.valueOf(position.getAltitude())
                        +"," + String.valueOf(position.getSpeed())
                        +"," + String.valueOf(position.getCourse())
                        +"," + String.valueOf(position.getGPSgateTime())
                        +"," + "1"
                        +",BatteryLevel=" + String.valueOf(position.getBattery())

        );

It does work some of the time, but I don't know what I've broken. I tried to leave all of the original variables in place for the degree, distance and time triggers. Can I please get some input/correction on where to go from here.

Michael Travis5 years ago

Update,
Now I know the problem is the SQLight, I am getting an error where NsHem is not a column name. I think the section

public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE position (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
"deviceId TEXT," +
"time INTEGER," +
"GPSgateTime TEXT," +
"latitude REAL," +
"GPSgateLatitude, REAL" +
"NsHem TEXT,"

Should create a database with NsHem as a column. I have tried switching it to BLOB and NOT NULL but I get no difference. I have also tried to rename the database just in case it is not being destroyed and recreated with each new instance of the app.