Skip to content

Commit

Permalink
Implement SMS notifications with help smpp protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
Abyss777 committed Feb 21, 2017
1 parent b6af1e9 commit bd2a8ef
Show file tree
Hide file tree
Showing 31 changed files with 562 additions and 18 deletions.
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@
<artifactId>ical4j</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.fizzed</groupId>
<artifactId>ch-smpp</artifactId>
<version>5.0.9</version>
</dependency>
</dependencies>

<build>
Expand Down
21 changes: 21 additions & 0 deletions schema/changelog-3.11.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd"
logicalFilePath="changelog-3.11">

<changeSet author="author" id="changelog-3.11">

<addColumn tableName="users">
<column name="phone" type="VARCHAR(128)" />
</addColumn>

<addColumn tableName="notifications">
<column name="sms" type="BOOLEAN" defaultValueBoolean="false" />
</addColumn>

</changeSet>

</databaseChangeLog>
1 change: 1 addition & 0 deletions schema/changelog-master.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
<include file="changelog-3.8.xml" relativeToChangelogFile="true" />
<include file="changelog-3.9.xml" relativeToChangelogFile="true" />
<include file="changelog-3.10.xml" relativeToChangelogFile="true" />
<include file="changelog-3.11.xml" relativeToChangelogFile="true" />
</databaseChangeLog>
10 changes: 6 additions & 4 deletions setup/default.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,15 @@
</entry>

<entry key='database.insertUser'>
INSERT INTO users (name, email, hashedPassword, salt, readonly, admin, map, distanceUnit, speedUnit, latitude, longitude, zoom, twelveHourFormat, coordinateFormat, disabled, expirationTime, deviceLimit, userLimit, deviceReadonly, token, attributes)
VALUES (:name, :email, :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, attributes)
VALUES (:name, :email, :phone, :hashedPassword, :salt, :readonly, :admin, :map, :distanceUnit, :speedUnit, :latitude, :longitude, :zoom, :twelveHourFormat, :coordinateFormat, :disabled, :expirationTime, :deviceLimit, :userLimit, :deviceReadonly, :token, :attributes)
</entry>

<entry key='database.updateUser'>
UPDATE users SET
name = :name,
email = :email,
phone = :phone,
readonly = :readonly,
admin = :admin,
map = :map,
Expand Down Expand Up @@ -268,8 +269,8 @@
</entry>

<entry key='database.insertNotification'>
INSERT INTO notifications (userId, type, web, mail, attributes)
VALUES (:userId, :type, :web, :mail, :attributes)
INSERT INTO notifications (userId, type, web, mail, sms, attributes)
VALUES (:userId, :type, :web, :mail, :sms, :attributes)
</entry>

<entry key='database.updateNotification'>
Expand All @@ -278,6 +279,7 @@
type = :type,
web = :web,
mail = :mail,
sms = :sms,
attributes = :attributes
WHERE id = :id
</entry>
Expand Down
15 changes: 13 additions & 2 deletions src/org/traccar/Context.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015 - 2016 Anton Tananaev ([email protected])
* Copyright 2015 - 2017 Anton Tananaev ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -49,6 +49,7 @@
import org.traccar.geolocation.MozillaGeolocationProvider;
import org.traccar.geolocation.OpenCellIdGeolocationProvider;
import org.traccar.notification.EventForwarder;
import org.traccar.smpp.SmppClient;
import org.traccar.web.WebServer;

public final class Context {
Expand Down Expand Up @@ -176,6 +177,12 @@ public static StatisticsManager getStatisticsManager() {
return statisticsManager;
}

private static SmppClient smppClient;

public static SmppClient getSmppManager() {
return smppClient;
}

public static void init(String[] arguments) throws Exception {

config = new Config();
Expand Down Expand Up @@ -277,7 +284,7 @@ public static void init(String[] arguments) throws Exception {
notificationManager = new NotificationManager(dataManager);
Properties velocityProperties = new Properties();
velocityProperties.setProperty("file.resource.loader.path",
Context.getConfig().getString("mail.templatesPath", "templates/mail") + "/");
Context.getConfig().getString("templates.rootPath", "templates") + "/");
velocityProperties.setProperty("runtime.log.logsystem.class",
"org.apache.velocity.runtime.log.NullLogChute");

Expand All @@ -301,6 +308,10 @@ public static void init(String[] arguments) throws Exception {

statisticsManager = new StatisticsManager();

if (config.getBoolean("sms.smpp.enable")) {
smppClient = new SmppClient();
}

}

public static void init(IdentityManager testIdentityManager) {
Expand Down
12 changes: 10 additions & 2 deletions src/org/traccar/api/resource/NotificationResource.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016 Anton Tananaev ([email protected])
* Copyright 2016 - 2017 Anton Tananaev ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -33,6 +33,12 @@
import org.traccar.model.Event;
import org.traccar.model.Notification;
import org.traccar.notification.NotificationMail;
import org.traccar.notification.NotificationSms;

import com.cloudhopper.smpp.type.RecoverablePduException;
import com.cloudhopper.smpp.type.SmppChannelException;
import com.cloudhopper.smpp.type.SmppTimeoutException;
import com.cloudhopper.smpp.type.UnrecoverablePduException;

@Path("users/notifications")
@Produces(MediaType.APPLICATION_JSON)
Expand Down Expand Up @@ -62,8 +68,10 @@ public Response update(Notification entity) throws SQLException {

@Path("test")
@POST
public Response testMail() throws MessagingException {
public Response testMessage() throws MessagingException, RecoverablePduException,
UnrecoverablePduException, SmppTimeoutException, SmppChannelException, InterruptedException {
NotificationMail.sendMailSync(getUserId(), new Event("test", 0), null);
NotificationSms.sendSmsSync(getUserId(), new Event("test", 0), null);
return Response.noContent().build();
}

Expand Down
14 changes: 10 additions & 4 deletions src/org/traccar/database/NotificationManager.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016 Anton Tananaev ([email protected])
* Copyright 2016 - 2017 Anton Tananaev ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -32,6 +32,7 @@
import org.traccar.model.Notification;
import org.traccar.model.Position;
import org.traccar.notification.NotificationMail;
import org.traccar.notification.NotificationSms;

public class NotificationManager {

Expand Down Expand Up @@ -65,6 +66,9 @@ public void updateEvent(Event event, Position position) {
if (notification.getMail()) {
NotificationMail.sendMailAsync(userId, event, position);
}
if (notification.getSms()) {
NotificationSms.sendSmsAsync(userId, event, position);
}
}
}
}
Expand Down Expand Up @@ -131,8 +135,9 @@ public void updateNotification(Notification notification) {
Notification cachedNotification = getUserNotificationByType(notification.getUserId(), notification.getType());
if (cachedNotification != null) {
if (cachedNotification.getWeb() != notification.getWeb()
|| cachedNotification.getMail() != notification.getMail()) {
if (!notification.getWeb() && !notification.getMail()) {
|| cachedNotification.getMail() != notification.getMail()
|| cachedNotification.getSms() != notification.getSms()) {
if (!notification.getWeb() && !notification.getMail() && !notification.getSms()) {
try {
dataManager.removeNotification(cachedNotification);
} catch (SQLException error) {
Expand All @@ -149,6 +154,7 @@ public void updateNotification(Notification notification) {
try {
cachedNotification.setWeb(notification.getWeb());
cachedNotification.setMail(notification.getMail());
cachedNotification.setSms(notification.getSms());
cachedNotification.setAttributes(notification.getAttributes());
} finally {
notificationsLock.writeLock().unlock();
Expand All @@ -162,7 +168,7 @@ public void updateNotification(Notification notification) {
} else {
notification.setId(cachedNotification.getId());
}
} else if (notification.getWeb() || notification.getMail()) {
} else if (notification.getWeb() || notification.getMail() || notification.getSms()) {
try {
dataManager.addNotification(notification);
} catch (SQLException error) {
Expand Down
10 changes: 10 additions & 0 deletions src/org/traccar/model/Notification.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,14 @@ public boolean getMail() {
public void setMail(boolean mail) {
this.mail = mail;
}

private boolean sms;

public boolean getSms() {
return sms;
}

public void setSms(boolean sms) {
this.sms = sms;
}
}
10 changes: 10 additions & 0 deletions src/org/traccar/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ public void setEmail(String email) {
this.email = email;
}

private String phone;

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
this.phone = phone;
}

private boolean readonly;

public boolean getReadonly() {
Expand Down
33 changes: 29 additions & 4 deletions src/org/traccar/notification/NotificationFormatter.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright 2016 Anton Tananaev ([email protected])
* Copyright 2016 - 2017 Anton Tananaev ([email protected])
* Copyright 2017 Andrey Kunitsyn ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -33,7 +34,7 @@ public final class NotificationFormatter {
private NotificationFormatter() {
}

public static MailMessage formatMessage(long userId, Event event, Position position) {
private static VelocityContext prepareContext(long userId, Event event, Position position) {
Device device = Context.getIdentityManager().getDeviceById(event.getDeviceId());

VelocityContext velocityContext = new VelocityContext();
Expand All @@ -47,18 +48,42 @@ public static MailMessage formatMessage(long userId, Event event, Position posit
velocityContext.put("geofence", Context.getGeofenceManager().getGeofence(event.getGeofenceId()));
}
velocityContext.put("webUrl", Context.getVelocityEngine().getProperty("web.url"));
return velocityContext;
}

public static MailMessage formatMailMessage(long userId, Event event, Position position) {
VelocityContext velocityContext = prepareContext(userId, event, position);
String mailTemplatesPath = Context.getConfig().getString("mail.templatesPath", "mail") + "/";
Template template = null;
try {
template = Context.getVelocityEngine().getTemplate(event.getType() + ".vm", StandardCharsets.UTF_8.name());
template = Context.getVelocityEngine().getTemplate(mailTemplatesPath + event.getType() + ".vm",
StandardCharsets.UTF_8.name());
} catch (ResourceNotFoundException error) {
Log.warning(error);
template = Context.getVelocityEngine().getTemplate("unknown.vm", StandardCharsets.UTF_8.name());
template = Context.getVelocityEngine().getTemplate(mailTemplatesPath + "unknown.vm",
StandardCharsets.UTF_8.name());
}

StringWriter writer = new StringWriter();
template.merge(velocityContext, writer);
String subject = (String) velocityContext.get("subject");
return new MailMessage(subject, writer.toString());
}

public static String formatSmsMessage(long userId, Event event, Position position) {
VelocityContext velocityContext = prepareContext(userId, event, position);
String smsTemplatesPath = Context.getConfig().getString("sms.templatesPath", "sms") + "/";
Template template = null;
try {
template = Context.getVelocityEngine().getTemplate(smsTemplatesPath + event.getType() + ".vm",
StandardCharsets.UTF_8.name());
} catch (ResourceNotFoundException error) {
Log.warning(error);
template = Context.getVelocityEngine().getTemplate(smsTemplatesPath + "unknown.vm",
StandardCharsets.UTF_8.name());
}
StringWriter writer = new StringWriter();
template.merge(velocityContext, writer);
return writer.toString();
}
}
5 changes: 3 additions & 2 deletions src/org/traccar/notification/NotificationMail.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright 2016 Anton Tananaev ([email protected])
* Copyright 2016 - 2017 Anton Tananaev ([email protected])
* Copyright 2017 Andrey Kunitsyn ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -106,7 +107,7 @@ public static void sendMailSync(long userId, Event event, Position position) thr
}

message.addRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail()));
MailMessage mailMessage = NotificationFormatter.formatMessage(userId, event, position);
MailMessage mailMessage = NotificationFormatter.formatMailMessage(userId, event, position);
message.setSubject(mailMessage.getSubject());
message.setContent(mailMessage.getBody(), "text/html; charset=utf-8");

Expand Down
50 changes: 50 additions & 0 deletions src/org/traccar/notification/NotificationSms.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2017 Anton Tananaev ([email protected])
* Copyright 2017 Andrey Kunitsyn ([email protected])
*
* 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.notification;

import org.traccar.Context;
import org.traccar.model.Event;
import org.traccar.model.Position;
import org.traccar.model.User;

import com.cloudhopper.smpp.type.RecoverablePduException;
import com.cloudhopper.smpp.type.SmppChannelException;
import com.cloudhopper.smpp.type.SmppTimeoutException;
import com.cloudhopper.smpp.type.UnrecoverablePduException;

public final class NotificationSms {

private NotificationSms() {
}

public static void sendSmsAsync(long userId, Event event, Position position) {
User user = Context.getPermissionsManager().getUser(userId);
if (Context.getSmppManager() != null && user.getPhone() != null) {
Context.getSmppManager().sendMessageAsync(user.getPhone(),
NotificationFormatter.formatSmsMessage(userId, event, position));
}
}

public static void sendSmsSync(long userId, Event event, Position position) throws RecoverablePduException,
UnrecoverablePduException, SmppTimeoutException, SmppChannelException, InterruptedException {
User user = Context.getPermissionsManager().getUser(userId);
if (Context.getSmppManager() != null && user.getPhone() != null) {
Context.getSmppManager().sendMessageSync(user.getPhone(),
NotificationFormatter.formatSmsMessage(userId, event, position));
}
}
}
Loading

0 comments on commit bd2a8ef

Please sign in to comment.