Fuel drop/increase notifications

hypoclone6 days ago

Hello wonderful people, I set up notifications for fuel drop/increase, these works fine, except the quantity of drop/increase is not included in the notification, how do I include this please, the setup includes a teltonika FMB with an omnicomm LLS4,

Anton Tananaev6 days ago

Yeah, I don't think we include that information currently. You would probably have to update FuelEventHandler and then templates as well. Feel free to send a pull request if you implement it.

hypoclone5 days ago

Thank you Anton
Please i have no knowledge of java and i don't want to post an embarrassing code in a PR, using chatgpt i was able to generate the below code for FuelEventHandler

/*
 * Copyright 2017 - 2024 Anton Tananaev (anton@traccar.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.traccar.handler.events;

import jakarta.inject.Inject;
import org.traccar.config.Keys;
import org.traccar.helper.model.AttributeUtil;
import org.traccar.helper.model.PositionUtil;
import org.traccar.model.Device;
import org.traccar.model.Event;
import org.traccar.model.Position;
import org.traccar.session.cache.CacheManager;

import java.util.HashMap;
import java.util.Map;

public class FuelEventHandler extends BaseEventHandler {

    private final CacheManager cacheManager;

    @Inject
    public FuelEventHandler(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    @Override
    public void onPosition(Position position, Callback callback) {

        Device device = cacheManager.getObject(Device.class, position.getDeviceId());
        if (device == null) {
            return;
        }
        if (!PositionUtil.isLatest(cacheManager, position)) {
            return;
        }

        if (position.hasAttribute(Position.KEY_FUEL_LEVEL)) {
            Position lastPosition = cacheManager.getPosition(position.getDeviceId());
            if (lastPosition != null && lastPosition.hasAttribute(Position.KEY_FUEL_LEVEL)) {
                double before = lastPosition.getDouble(Position.KEY_FUEL_LEVEL);
                double after = position.getDouble(Position.KEY_FUEL_LEVEL);
                double change = after - before;

                if (change > 0) {
                    double threshold = AttributeUtil.lookup(
                            cacheManager, Keys.EVENT_FUEL_INCREASE_THRESHOLD, position.getDeviceId());
                    if (threshold > 0 && change >= threshold) {
                        // Add before, after, and change to event attributes
                        Map<String, Object> attributes = new HashMap<>();
                        attributes.put("before", before);
                        attributes.put("after", after);
                        attributes.put("change", change);

                        Event event = new Event(Event.TYPE_DEVICE_FUEL_INCREASE, position);
                        event.setAttributes(attributes);
                        callback.eventDetected(event);
                    }
                } else if (change < 0) {
                    double threshold = AttributeUtil.lookup(
                            cacheManager, Keys.EVENT_FUEL_DROP_THRESHOLD, position.getDeviceId());
                    if (threshold > 0 && Math.abs(change) >= threshold) {
                        // Add before, after, and change to event attributes
                        Map<String, Object> attributes = new HashMap<>();
                        attributes.put("before", before);
                        attributes.put("after", after);
                        attributes.put("change", change);

                        Event event = new Event(Event.TYPE_DEVICE_FUEL_DROP, position);
                        event.setAttributes(attributes);
                        callback.eventDetected(event);
                    }
                }
            }
        }
    }

}

my next challenge was how to access the variables "before", "after" and "change" in the template
i made the below changes to the templates/full/deviceFuelDrop.vm file

#set($subject = "$device.name: fuel drop")
<!DOCTYPE html>
<html>
<body>
Device: $device.name<br>
Time: $dateTool.format("YYYY-MM-dd HH:mm:ss", $event.eventTime, $locale, $timezone)<br>
Point: <a href="$webUrl?eventId=$event.id">#{if}($position.address)$position.address#{else}$position.latitude&deg;, $position.longitude&deg;#{end}</a><br>
<br>
Quantity Before: $event.before<br>
Quantity After: $event.after<br>
Quantity Removed: $event.change<br>
<a href="$webUrl/settings/notifications?token=$token">Unsubscribe</a>
</body>
</html>

I am not convinced i am doing the right thing, could you help review these before submitting as PR

Anton Tananaev4 days ago

Seems roughly correct in Java code, but in the template you have to use attributes.

hypoclone4 days ago

Thank you so much anton
Please will this suffice?

#set($subject = "$device.name: fuel drop")
<!DOCTYPE html>
<html>
<body>
Device: $device.name<br>
Time: $dateTool.format("YYYY-MM-dd HH:mm:ss", $event.eventTime, $locale, $timezone)<br>
Point: <a href="$webUrl?eventId=$event.id">#{if}($position.address)$position.address#{else}$position.latitude&deg;, $position.longitude&deg;#{end}</a><br>
<br>
Quantity Before: $!event.attributes.before<br>
Quantity After: $!event.attributes.after<br>
Quantity Removed: $!event.attributes.change<br><br>
<a href="$webUrl/settings/notifications?token=$token">Unsubscribe</a>
</body>
</html>
Anton Tananaev4 days ago

Something like this. Have you tried it?

hypoclone3 days ago

Thank you anton!
I am trying to implement this on a live server, but i keep getting the error below on he notification page

Screenshot 2024-12-19 153126.png

the system is version 6.5 i did a little modification to the web interface but i don't know where the "Description" column came from, all other instance(not version 6.5) don't have that column, traccar demos don't have it also
also all my existing notification disappeared

Screenshot 2024-12-19 153717.png

Anton Tananaev3 days ago

Are you sure you used the 6.5 codebase and not master?

hypoclone3 days ago

oh! so sorry, i was using the master

hypoclone3 days ago

Thanks for the assistance anton, the setup seems to be working, below is a sample notification

Device: TestTruck2
Time: 2024-12-19 18:24:21
Quantity Before: 137.0
Quantity After: 112.0
Quantity Removed: 25.0
Point: address redacted

Unsubscribe

i will send a pull request