diff options
33 files changed, 87 insertions, 29 deletions
@@ -144,6 +144,11 @@ <version>1.7</version> </dependency> <dependency> + <groupId>org.apache.velocity</groupId> + <artifactId>velocity-tools</artifactId> + <version>2.0</version> + </dependency> + <dependency> <groupId>org.mnode.ical4j</groupId> <artifactId>ical4j</artifactId> <version>2.0.0</version> diff --git a/schema/changelog-3.11.xml b/schema/changelog-3.11.xml index c169e1146..1fdaa3f17 100644 --- a/schema/changelog-3.11.xml +++ b/schema/changelog-3.11.xml @@ -11,7 +11,7 @@ <addColumn tableName="users"> <column name="phone" type="VARCHAR(128)" /> </addColumn> - + <addColumn tableName="notifications"> <column name="sms" type="BOOLEAN" defaultValueBoolean="false" /> </addColumn> @@ -20,6 +20,14 @@ <column name="devicereadonly" type="BOOLEAN" defaultValueBoolean="false" /> </addColumn> + <addColumn tableName="server"> + <column name="timezone" type="VARCHAR(128)" /> + </addColumn> + + <addColumn tableName="users"> + <column name="timezone" type="VARCHAR(128)" /> + </addColumn> + </changeSet> </databaseChangeLog> diff --git a/setup/default.xml b/setup/default.xml index 9fe49edbe..90bdc1973 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -51,6 +51,7 @@ longitude = :longitude, zoom = :zoom, twelveHourFormat = :twelveHourFormat, + timezone = :timezone, attributes = :attributes WHERE id = :id </entry> @@ -65,8 +66,8 @@ </entry> <entry key='database.insertUser'> - INSERT INTO users (name, email, phone, hashedPassword, salt, readonly, admin, map, distanceUnit, speedUnit, latitude, longitude, zoom, twelveHourFormat, coordinateFormat, disabled, expirationTime, deviceLimit, userLimit, deviceReadonly, token, attributes) - VALUES (:name, :email, :phone, :hashedPassword, :salt, :readonly, :admin, :map, :distanceUnit, :speedUnit, :latitude, :longitude, :zoom, :twelveHourFormat, :coordinateFormat, :disabled, :expirationTime, :deviceLimit, :userLimit, :deviceReadonly, :token, :attributes) + INSERT INTO users (name, email, phone, hashedPassword, salt, readonly, admin, map, distanceUnit, speedUnit, latitude, longitude, zoom, twelveHourFormat, coordinateFormat, disabled, expirationTime, deviceLimit, userLimit, deviceReadonly, token, timezone, attributes) + VALUES (:name, :email, :phone, :hashedPassword, :salt, :readonly, :admin, :map, :distanceUnit, :speedUnit, :latitude, :longitude, :zoom, :twelveHourFormat, :coordinateFormat, :disabled, :expirationTime, :deviceLimit, :userLimit, :deviceReadonly, :token, :timezone, :attributes) </entry> <entry key='database.updateUser'> @@ -90,6 +91,7 @@ userLimit = :userLimit, deviceReadonly = :deviceReadonly, token = :token, + timezone = :timezone, attributes = :attributes WHERE id = :id </entry> diff --git a/src/org/traccar/model/Server.java b/src/org/traccar/model/Server.java index b588a4de0..db3f021a9 100644 --- a/src/org/traccar/model/Server.java +++ b/src/org/traccar/model/Server.java @@ -15,6 +15,8 @@ */ package org.traccar.model; +import java.util.TimeZone; + import org.traccar.helper.Log; public class Server extends Extensible { @@ -166,4 +168,17 @@ public class Server extends Extensible { this.coordinateFormat = coordinateFormat; } + private String timezone; + + public void setTimezone(String timezone) { + if (timezone != null) { + this.timezone = TimeZone.getTimeZone(timezone).getID(); + } else { + this.timezone = null; + } + } + + public String getTimezone() { + return timezone; + } } diff --git a/src/org/traccar/model/User.java b/src/org/traccar/model/User.java index 274f2b2a2..71bb563a8 100644 --- a/src/org/traccar/model/User.java +++ b/src/org/traccar/model/User.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import org.traccar.helper.Hashing; import java.util.Date; +import java.util.TimeZone; public class User extends Extensible { @@ -265,4 +266,17 @@ public class User extends Extensible { return Hashing.validatePassword(password, hashedPassword, salt); } + private String timezone; + + public void setTimezone(String timezone) { + if (timezone != null) { + this.timezone = TimeZone.getTimeZone(timezone).getID(); + } else { + this.timezone = null; + } + } + + public String getTimezone() { + return timezone; + } } diff --git a/src/org/traccar/notification/NotificationFormatter.java b/src/org/traccar/notification/NotificationFormatter.java index cec238548..eae2681c9 100644 --- a/src/org/traccar/notification/NotificationFormatter.java +++ b/src/org/traccar/notification/NotificationFormatter.java @@ -18,10 +18,12 @@ package org.traccar.notification; import java.io.StringWriter; import java.nio.charset.StandardCharsets; +import java.util.Locale; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.exception.ResourceNotFoundException; +import org.apache.velocity.tools.generic.DateTool; import org.traccar.Context; import org.traccar.helper.Log; import org.traccar.model.Device; @@ -48,6 +50,9 @@ public final class NotificationFormatter { velocityContext.put("geofence", Context.getGeofenceManager().getGeofence(event.getGeofenceId())); } velocityContext.put("webUrl", Context.getVelocityEngine().getProperty("web.url")); + velocityContext.put("dateTool", new DateTool()); + velocityContext.put("timezone", ReportUtils.getTimezone(userId)); + velocityContext.put("locale", Locale.getDefault()); return velocityContext; } diff --git a/src/org/traccar/reports/ReportUtils.java b/src/org/traccar/reports/ReportUtils.java index 1402e10d4..968fb357b 100644 --- a/src/org/traccar/reports/ReportUtils.java +++ b/src/org/traccar/reports/ReportUtils.java @@ -24,6 +24,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.Collection; +import java.util.TimeZone; public final class ReportUtils { @@ -46,6 +47,14 @@ public final class ReportUtils { return unit != null ? unit : "kn"; } + public static TimeZone getTimezone(long userId) { + String timezone = Context.getPermissionsManager().getUser(userId).getTimezone(); + if (timezone == null) { + timezone = Context.getPermissionsManager().getServer().getTimezone(); + } + return timezone != null ? TimeZone.getTimeZone(timezone) : TimeZone.getDefault(); + } + public static Collection<Long> getDeviceList(Collection<Long> deviceIds, Collection<Long> groupIds) { Collection<Long> result = new ArrayList<>(); result.addAll(deviceIds); diff --git a/templates/mail/alarm.vm b/templates/mail/alarm.vm index b64b2126a..253c0b7a3 100644 --- a/templates/mail/alarm.vm +++ b/templates/mail/alarm.vm @@ -4,7 +4,7 @@ <body> Device: $device.name<br> Alarm: $position.getString("alarm")<br> -Time: $event.serverTime<br> +Time: $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone)<br> Point: <a href="$webUrl?eventId=$event.id">#{if}($position.address)$position.address#{else}$position.latitude°, $position.longitude°#{end}</a><br> </body> </html> diff --git a/templates/mail/commandResult.vm b/templates/mail/commandResult.vm index 4c330584d..3d2a7ceb8 100644 --- a/templates/mail/commandResult.vm +++ b/templates/mail/commandResult.vm @@ -4,7 +4,7 @@ <body> Device: $device.name<br> Result: $position.getString("result")<br> -Time: $event.serverTime<br> +Time: $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone)<br> Link: <a href="$webUrl?eventId=$event.id">$webUrl?eventId=$event.id</a> </body> </html> diff --git a/templates/mail/deviceMoving.vm b/templates/mail/deviceMoving.vm index 9ad2d8bdc..a734e59b4 100644 --- a/templates/mail/deviceMoving.vm +++ b/templates/mail/deviceMoving.vm @@ -4,7 +4,7 @@ <body> Device: $device.name<br> Moving<br> -Time: $event.serverTime<br> +Time: $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone)<br> Point: <a href="$webUrl?eventId=$event.id">#{if}($position.address)$position.address#{else}$position.latitude°, $position.longitude°#{end}</a><br> </body> </html> diff --git a/templates/mail/deviceOffline.vm b/templates/mail/deviceOffline.vm index ee7e96f05..d77f4e6a9 100644 --- a/templates/mail/deviceOffline.vm +++ b/templates/mail/deviceOffline.vm @@ -4,7 +4,7 @@ <body> Device: $device.name<br> Offline<br> -Time: $event.serverTime<br> +Time: $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone)<br> Link: <a href="$webUrl?eventId=$event.id">$webUrl?eventId=$event.id</a> </body> </html> diff --git a/templates/mail/deviceOnline.vm b/templates/mail/deviceOnline.vm index 379b5cc80..9ea65c843 100644 --- a/templates/mail/deviceOnline.vm +++ b/templates/mail/deviceOnline.vm @@ -4,7 +4,7 @@ <body> Device: $device.name<br> Online<br> -Time: $event.serverTime<br> +Time: $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone)<br> Link: <a href="$webUrl?eventId=$event.id">$webUrl?eventId=$event.id</a> </body> </html> diff --git a/templates/mail/deviceOverspeed.vm b/templates/mail/deviceOverspeed.vm index a8a58a181..1836dacd5 100644 --- a/templates/mail/deviceOverspeed.vm +++ b/templates/mail/deviceOverspeed.vm @@ -11,7 +11,7 @@ <body> Device: $device.name<br> Exceeds the speed: $speedString<br> -Time: $event.serverTime<br> +Time: $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone)<br> Point: <a href="$webUrl?eventId=$event.id">#{if}($position.address)$position.address#{else}$position.latitude°, $position.longitude°#{end}</a><br> </body> </html> diff --git a/templates/mail/deviceStopped.vm b/templates/mail/deviceStopped.vm index 273e1c988..45f97e463 100644 --- a/templates/mail/deviceStopped.vm +++ b/templates/mail/deviceStopped.vm @@ -4,7 +4,7 @@ <body> Device: $device.name<br> Stopped<br> -Time: $event.serverTime<br> +Time: $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone)<br> Point: <a href="$webUrl?eventId=$event.id">#{if}($position.address)$position.address#{else}$position.latitude°, $position.longitude°#{end}</a><br> </body> </html> diff --git a/templates/mail/deviceUnknown.vm b/templates/mail/deviceUnknown.vm index 40b8fbfa7..73696bc47 100644 --- a/templates/mail/deviceUnknown.vm +++ b/templates/mail/deviceUnknown.vm @@ -4,7 +4,7 @@ <body> Device: $device.name<br> Status is unknown<br> -Time: $event.serverTime<br> +Time: $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone)<br> Link: <a href="$webUrl?eventId=$event.id">$webUrl?eventId=$event.id</a> </body> </html> diff --git a/templates/mail/geofenceEnter.vm b/templates/mail/geofenceEnter.vm index 75d16617f..f0f84fb67 100644 --- a/templates/mail/geofenceEnter.vm +++ b/templates/mail/geofenceEnter.vm @@ -4,7 +4,7 @@ <body> Device: $device.name<br> Has entered geofence: $geofence.name<br> -Time: $event.serverTime<br> +Time: $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone)<br> Point: <a href="$webUrl?eventId=$event.id">#{if}($position.address)$position.address#{else}$position.latitude°, $position.longitude°#{end}</a><br> </body> </html> diff --git a/templates/mail/geofenceExit.vm b/templates/mail/geofenceExit.vm index 6d4d1639d..90e61b618 100644 --- a/templates/mail/geofenceExit.vm +++ b/templates/mail/geofenceExit.vm @@ -4,7 +4,7 @@ <body> Device: $device.name<br> Has exited geofence: $geofence.name<br> -Time: $event.serverTime<br> +Time: $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone)<br> Point: <a href="$webUrl?eventId=$event.id">#{if}($position.address)$position.address#{else}$position.latitude°, $position.longitude°#{end}</a><br> </body> </html> diff --git a/templates/mail/ignitionOff.vm b/templates/mail/ignitionOff.vm index 3a3212b12..407577640 100644 --- a/templates/mail/ignitionOff.vm +++ b/templates/mail/ignitionOff.vm @@ -4,7 +4,7 @@ <body> Device: $device.name<br> Ignition OFF<br> -Time: $event.serverTime<br> +Time: $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone)<br> Point: <a href="$webUrl?eventId=$event.id">#{if}($position.address)$position.address#{else}$position.latitude°, $position.longitude°#{end}</a><br> </body> </html> diff --git a/templates/mail/ignitionOn.vm b/templates/mail/ignitionOn.vm index bbe6c40f6..ad039a849 100644 --- a/templates/mail/ignitionOn.vm +++ b/templates/mail/ignitionOn.vm @@ -4,7 +4,7 @@ <body> Device: $device.name<br> Ignition ON<br> -Time: $event.serverTime<br> +Time: $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone)<br> Point: <a href="$webUrl?eventId=$event.id">#{if}($position.address)$position.address#{else}$position.latitude°, $position.longitude°#{end}</a><br> </body> </html> diff --git a/templates/mail/maintenance.vm b/templates/mail/maintenance.vm index c94c35cc4..2951fdfda 100644 --- a/templates/mail/maintenance.vm +++ b/templates/mail/maintenance.vm @@ -4,7 +4,7 @@ <body> Device: $device.name<br> Maintenance is required<br> -Time: $event.serverTime<br> +Time: $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone)<br> Point: <a href="$webUrl?eventId=$event.id">#{if}($position.address)$position.address#{else}$position.latitude°, $position.longitude°#{end}</a><br> </body> </html> diff --git a/templates/sms/alarm.vm b/templates/sms/alarm.vm index e35a573b3..0277fbddf 100644 --- a/templates/sms/alarm.vm +++ b/templates/sms/alarm.vm @@ -1 +1 @@ -$device.name alarm: $position.getString("alarm") at $event.serverTime +$device.name alarm: $position.getString("alarm") at $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone) diff --git a/templates/sms/commandResult.vm b/templates/sms/commandResult.vm index 38fddcf25..4962eaa36 100644 --- a/templates/sms/commandResult.vm +++ b/templates/sms/commandResult.vm @@ -1 +1 @@ -$device.name command result received: $position.getString("result") at $event.serverTime +$device.name command result received: $position.getString("result") at $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone) diff --git a/templates/sms/deviceMoving.vm b/templates/sms/deviceMoving.vm index febae6331..4f62421b2 100644 --- a/templates/sms/deviceMoving.vm +++ b/templates/sms/deviceMoving.vm @@ -1 +1 @@ -$device.name moving at $event.serverTime +$device.name moving at $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone) diff --git a/templates/sms/deviceOffline.vm b/templates/sms/deviceOffline.vm index 490502946..7df007f81 100644 --- a/templates/sms/deviceOffline.vm +++ b/templates/sms/deviceOffline.vm @@ -1 +1 @@ -$device.name offline at $event.serverTime +$device.name offline at $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone) diff --git a/templates/sms/deviceOnline.vm b/templates/sms/deviceOnline.vm index e8bc0a5bf..48e81ec75 100644 --- a/templates/sms/deviceOnline.vm +++ b/templates/sms/deviceOnline.vm @@ -1 +1 @@ -$device.name online at $event.serverTime +$device.name online at $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone) diff --git a/templates/sms/deviceOverspeed.vm b/templates/sms/deviceOverspeed.vm index 63f967bc3..4e3219a18 100644 --- a/templates/sms/deviceOverspeed.vm +++ b/templates/sms/deviceOverspeed.vm @@ -5,4 +5,4 @@ #else #set($speedString = "$position.speed kn") #end -$device.name exceeds the speed $speedString at $event.serverTime +$device.name exceeds the speed $speedString at $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone) diff --git a/templates/sms/deviceStopped.vm b/templates/sms/deviceStopped.vm index cf9118cac..80e2c085f 100644 --- a/templates/sms/deviceStopped.vm +++ b/templates/sms/deviceStopped.vm @@ -1 +1 @@ -$device.name stopped at $event.serverTime +$device.name stopped at $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone) diff --git a/templates/sms/deviceUnknown.vm b/templates/sms/deviceUnknown.vm index 533219799..150d05df1 100644 --- a/templates/sms/deviceUnknown.vm +++ b/templates/sms/deviceUnknown.vm @@ -1 +1 @@ -$device.name status is unknown at $event.serverTime +$device.name status is unknown at $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone) diff --git a/templates/sms/geofenceEnter.vm b/templates/sms/geofenceEnter.vm index 5a216f361..443b1c0a8 100644 --- a/templates/sms/geofenceEnter.vm +++ b/templates/sms/geofenceEnter.vm @@ -1 +1 @@ -$device.name has entered geofence $geofence.name at $event.serverTime +$device.name has entered geofence $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone) diff --git a/templates/sms/geofenceExit.vm b/templates/sms/geofenceExit.vm index fd8a8409d..1314a7ebc 100644 --- a/templates/sms/geofenceExit.vm +++ b/templates/sms/geofenceExit.vm @@ -1 +1 @@ -$device.name has exited geofence $geofence.name at $event.serverTime +$device.name has exited geofence $geofence.name at $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone) diff --git a/templates/sms/ignitionOff.vm b/templates/sms/ignitionOff.vm index 6f90eb552..2795dc1a5 100644 --- a/templates/sms/ignitionOff.vm +++ b/templates/sms/ignitionOff.vm @@ -1 +1 @@ -$device.name ignition OFF at $event.serverTime +$device.name ignition OFF at $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone) diff --git a/templates/sms/ignitionOn.vm b/templates/sms/ignitionOn.vm index 9c0d79888..76a8fc676 100644 --- a/templates/sms/ignitionOn.vm +++ b/templates/sms/ignitionOn.vm @@ -1 +1 @@ -$device.name ignition ON at $event.serverTime +$device.name ignition ON at $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone) diff --git a/templates/sms/maintenance.vm b/templates/sms/maintenance.vm index f2e6940f6..2375feefb 100644 --- a/templates/sms/maintenance.vm +++ b/templates/sms/maintenance.vm @@ -1 +1 @@ -$device.name maintenance is required at $event.serverTime +$device.name maintenance is required at $dateTool.format("YYYY.MM.dd HH:mm:ss", $event.serverTime, $locale, $timezone) |