Geofence Problem

Sumit5 years ago

Hi,
I have configured the "geofence notification" such as only send the notifications to those users who have created them. So it is working fine for all the devices but when I add new device so for this device the old geofences are not working properly like "geofenceEnter" and "geofenceExit". And I have checked that geofence is already linked with the user and device both.

And there is not showing any kind of error in the log file. I am not getting to detect where I am doing wrong thing.
I have added this syntax in the file:
/database>NotificationManager.java>updateEvent(){}> after dataManager.add(event);

CustomUtilities.sendNotification(event.getDeviceId(), event.getType(), position, event);

:/custom>CustomUtilities.java

    
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.traccar.custom;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonReader;
import org.traccar.Context;
import org.traccar.database.NotificationManager;
import org.traccar.model.Alert;
import org.traccar.model.Device;
import org.traccar.model.Event;
import org.traccar.model.FirebaseToken;
import org.traccar.model.Geofence;
import org.traccar.model.Position;

/**
 *
 * @author Sumit
 */
public class CustomUtilities {

    public static final String ALERT = "alert";

    public static void sendNotification(long deviceId, String eventType, Position position, Event event) {
        try {
            Device device = Context.getDataManager().getDevice(deviceId);
            Collection<FirebaseToken> tokens;
            
            if(eventType.equals(Event.TYPE_GEOFENCE_ENTER) || eventType.equals(Event.TYPE_GEOFENCE_EXIT)){
                tokens = Context.getDataManager().selectFirebaseTokenByUserGeofence(event.getGeofenceId());
            }
            else{
                tokens = Context.getDataManager().selectRegisteredClients(device.getId());
            }
            
            if(tokens.size()>0){
            
                String[] gcm_tokens = new String[tokens.size()];
                ArrayList<Long> users = new ArrayList<>();
                if (position != null && (position.getAddress() == null || position.getAddress().isEmpty())) {
                    position.setAddress(GoogleMaps.getAddress(position));
                }
                Iterator<FirebaseToken> iterator = tokens.iterator();
                int index = 0;
                while (iterator.hasNext()) {
                    FirebaseToken token = iterator.next();
                    gcm_tokens[index++] = token.getFirebase_token();
                    if (!users.contains(token.getUser_id())) {
                        users.add(token.getUser_id());
                    }
                }




                Alert alert = new Alert();
                alert.setDevice_id(deviceId);
                alert.setCategory(eventType);
                alert.setPosition(position);
                if (gcm_tokens.length > 0) {

                    Collection<Geofence> matches = null;
                    String time_string = new SimpleDateFormat("hh:mm:ss a dd MMM").format(position.getDeviceTime());
                    switch (eventType) {
                        case Event.TYPE_GEOFENCE_ENTER:
                            matches = Context.getDataManager().selectGeofence(event.getGeofenceId());
                            if (matches.size() > 0) {
                                Geofence geofence = matches.iterator().next();
                                alert.setType(ALERT);
                                alert.setCategory(Position.ALARM_GEOFENCE_ENTER);
                                alert.setText(device.getName() + " entered " + geofence.getName() + " at " + time_string);
                            }
                            break;

                        case Event.TYPE_GEOFENCE_EXIT:
                            matches = Context.getDataManager().selectGeofence(event.getGeofenceId());
                            if (matches.size() > 0) {
                                Geofence geofence = matches.iterator().next();                 
                                alert.setType(ALERT);
                                alert.setCategory(Position.ALARM_GEOFENCE_EXIT);
                                alert.setText(device.getName() + " left " + geofence.getName() + " at " + time_string);
                            }
                            break;
                    }
                    if (alert.getType() != null && !alert.getType().isEmpty()) {

                        // Add Notification to the server
                        for (Long user : users) {
                            alert.setUserId(user);
                            Context.getDataManager().addAlert(alert);
                        }

                        // Send Notification to the mobile devices
                        ServerConnection.sendAlert(alert, gcm_tokens);

                    }

                }
            
            }
        } catch (SQLException | IOException ex) {
            Logger.getLogger(NotificationManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
}

WHERE
a) selectFirebaseTokenByUserGeofence(event.getGeofenceId());

<entry key='database.selectTokensByUserGeofence'>
        SELECT * FROM firebase_token where user_id in ( select userid from user_geofence where geofenceid=:geofenceId )
</entry>

b) selectRegisteredClients(device.getId());

<entry key='database.selectRegisteredClients'>
        SELECT * FROM firebase_token WHERE user_id in (select userId from user_device where deviceId=:deviceId)
</entry>

Please help me to find my error and it is not working only for one device and for the rest of the devices are working

Ernesto Vallejo5 years ago

Is your notification based per device? Did you add the notification to your device?
Is your notification based per group? Is the device in the group?
Double check on those rules of notifications in this link
https://www.traccar.org/documentation/notifications/

Ernesto Vallejo5 years ago

Sorry, I didnt read properly your question. Please dismiss my comments.

Ernesto Vallejo5 years ago

What does your custom notificator does that is not in latest official version?

Sumit5 years ago

Actually, it is based on mobile or web system notification by FCM.

Sumit5 years ago

Ernesto Vallejo, this is just only for my use case.

Sumit5 years ago

Problem is solved now. I just upload the build by two times. First time it did not work but second time it worked.

Sumit5 years ago

Hi Anton,
I have found something in creating Geofence Events. Here is the log-
Geofence Events

A vehicle is entered into the geofence at 2019-03-15 09:03:00(position id: 24127900) with the server receiving time 2019-03-15 09:03:00 which is correct.
But it generates again geofenceEnter at 2019-03-15 10:58:08(position id: 24142379) with the server receiving time 2019-03-15 18:06:03.
And the vehicle is exited from the geofence at 2019-03-15 18:04:19(position id: 24201633) with the server receiving time 2019-03-15 18:04:19.

And rest of the positions data between position ids from 24142379 to 24201581 are invalid.

So I want to know why geofenceEnter event happened again without geofenceExit. And if this is not the problem, then what it can be scenarios for this event.

Actually this same thing was happened with another device too and the case was same. How can I solve this? Please reply.