diff --git a/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java b/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java index a1de832d14..3f2fcd40f5 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java @@ -20,10 +20,12 @@ import com.google.firebase.messaging.MessagingErrorCode; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.notification.FirebaseService; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; +import org.thingsboard.server.common.data.notification.info.NotificationInfo; import org.thingsboard.server.common.data.notification.settings.MobileAppNotificationDeliveryMethodConfig; import org.thingsboard.server.common.data.notification.settings.NotificationSettings; import org.thingsboard.server.common.data.notification.template.MobileAppDeliveryMethodNotificationTemplate; @@ -31,7 +33,10 @@ import org.thingsboard.server.dao.notification.NotificationSettingsService; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.service.notification.NotificationProcessingContext; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; +import java.util.Optional; import java.util.Set; @Component @@ -53,9 +58,20 @@ public class MobileAppNotificationChannel implements NotificationChannel validTokens = new HashSet<>(mobileSessions.keySet()); + + String subject = processedTemplate.getSubject(); + String body = processedTemplate.getBody(); + Map data = Optional.ofNullable(processedTemplate.getAdditionalConfig()) + .map(JacksonUtil::toFlatMap).orElseGet(HashMap::new); + Optional.ofNullable(ctx.getRequest().getInfo()) + .map(NotificationInfo::getStateEntityId) + .ifPresent(stateEntityId -> { + data.put("stateEntityId", stateEntityId.getId().toString()); + data.put("stateEntityType", stateEntityId.getEntityType().name()); + }); for (String token : mobileSessions.keySet()) { try { - firebaseService.sendMessage(ctx.getTenantId(), credentials, token, processedTemplate.getSubject(), processedTemplate.getBody()); + firebaseService.sendMessage(ctx.getTenantId(), credentials, token, subject, body, data); } catch (FirebaseMessagingException e) { MessagingErrorCode errorCode = e.getMessagingErrorCode(); if (errorCode == MessagingErrorCode.UNREGISTERED || errorCode == MessagingErrorCode.INVALID_ARGUMENT) { diff --git a/application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java b/application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java index b85d567c3b..a1a02d52f1 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java @@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.id.TenantId; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.Map; import java.util.concurrent.TimeUnit; @Service @@ -51,7 +52,7 @@ public class DefaultFirebaseService implements FirebaseService { .build(); @Override - public void sendMessage(TenantId tenantId, String credentials, String fcmToken, String title, String body) throws FirebaseMessagingException { + public void sendMessage(TenantId tenantId, String credentials, String fcmToken, String title, String body, Map data) throws FirebaseMessagingException { FirebaseContext firebaseContext = contexts.asMap().compute(tenantId.toString(), (key, context) -> { if (context == null) { return new FirebaseContext(key, credentials); @@ -62,6 +63,7 @@ public class DefaultFirebaseService implements FirebaseService { }); Message message = Message.builder() + .setToken(fcmToken) .setNotification(Notification.builder() .setTitle(title) .setBody(body) @@ -69,7 +71,7 @@ public class DefaultFirebaseService implements FirebaseService { .setAndroidConfig(AndroidConfig.builder() .setPriority(AndroidConfig.Priority.HIGH) .build()) - .setToken(fcmToken) + .putAllData(data) .build(); firebaseContext.getMessaging().send(message); log.trace("[{}] Sent message for FCM token {}", tenantId, fcmToken); diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java index d5a089dc82..2d93573a25 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java @@ -27,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.web.servlet.ResultActions; import org.springframework.web.client.RestTemplate; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.NotificationCenter; import org.thingsboard.rule.engine.api.notification.FirebaseService; import org.thingsboard.server.common.data.EntityType; @@ -66,6 +67,7 @@ import org.thingsboard.server.common.data.notification.template.DeliveryMethodNo import org.thingsboard.server.common.data.notification.template.EmailDeliveryMethodNotificationTemplate; import org.thingsboard.server.common.data.notification.template.MicrosoftTeamsDeliveryMethodNotificationTemplate; import org.thingsboard.server.common.data.notification.template.MicrosoftTeamsDeliveryMethodNotificationTemplate.Button.LinkType; +import org.thingsboard.server.common.data.notification.template.MobileAppDeliveryMethodNotificationTemplate; import org.thingsboard.server.common.data.notification.template.NotificationTemplate; import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig; import org.thingsboard.server.common.data.notification.template.SlackDeliveryMethodNotificationTemplate; @@ -76,7 +78,6 @@ import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.notification.DefaultNotifications; import org.thingsboard.server.dao.notification.NotificationDao; import org.thingsboard.server.dao.service.DaoSqlTest; -import org.thingsboard.server.service.executors.DbCallbackExecutorService; import org.thingsboard.server.service.notification.channels.MicrosoftTeamsNotificationChannel; import org.thingsboard.server.service.ws.notification.cmd.UnreadNotificationsUpdate; @@ -92,6 +93,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.InstanceOfAssertFactories.type; import static org.awaitility.Awaitility.await; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doThrow; @@ -739,6 +742,9 @@ public class NotificationApiTest extends AbstractNotificationApiTest { loginTenantAdmin(); NotificationTarget target = createNotificationTarget(new AllUsersFilter()); NotificationTemplate template = createNotificationTemplate(NotificationType.GENERAL, "Title", "Message", NotificationDeliveryMethod.MOBILE_APP); + ((MobileAppDeliveryMethodNotificationTemplate) template.getConfiguration().getDeliveryMethodsTemplates().get(NotificationDeliveryMethod.MOBILE_APP)) + .setAdditionalConfig(JacksonUtil.newObjectNode().set("test", JacksonUtil.newObjectNode().put("test", "test"))); + saveNotificationTemplate(template); NotificationRequest request = submitNotificationRequest(List.of(target.getId()), template.getId(), 0); NotificationRequestStats stats = awaitNotificationRequest(request.getId()); @@ -747,11 +753,11 @@ public class NotificationApiTest extends AbstractNotificationApiTest { .contains("doesn't use the mobile app"); verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), - eq("tenantFcmToken1"), eq("Title"), eq("Message")); + eq("tenantFcmToken1"), eq("Title"), eq("Message"), argThat(data -> "test".equals(data.get("test.test")))); verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), - eq("tenantFcmToken2"), eq("Title"), eq("Message")); + eq("tenantFcmToken2"), eq("Title"), eq("Message"), argThat(data -> "test".equals(data.get("test.test")))); verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), - eq("customerFcmToken"), eq("Title"), eq("Message")); + eq("customerFcmToken"), eq("Title"), eq("Message"), argThat(data -> "test".equals(data.get("test.test")))); verifyNoMoreInteractions(firebaseService); clearInvocations(firebaseService); @@ -759,9 +765,9 @@ public class NotificationApiTest extends AbstractNotificationApiTest { request = submitNotificationRequest(List.of(target.getId()), template.getId(), 0); awaitNotificationRequest(request.getId()); verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), - eq("tenantFcmToken1"), eq("Title"), eq("Message")); + eq("tenantFcmToken1"), eq("Title"), eq("Message"), anyMap()); verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), - eq("customerFcmToken"), eq("Title"), eq("Message")); + eq("customerFcmToken"), eq("Title"), eq("Message"), anyMap()); verifyNoMoreInteractions(firebaseService); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/MobileAppDeliveryMethodNotificationTemplate.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/MobileAppDeliveryMethodNotificationTemplate.java index f621eee832..96e8b80453 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/MobileAppDeliveryMethodNotificationTemplate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/MobileAppDeliveryMethodNotificationTemplate.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.data.notification.template; +import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -32,6 +33,7 @@ public class MobileAppDeliveryMethodNotificationTemplate extends DeliveryMethodN @NotEmpty private String subject; + private JsonNode additionalConfig; private final List templatableValues = List.of( TemplatableValue.of(this::getBody, this::setBody), @@ -41,6 +43,7 @@ public class MobileAppDeliveryMethodNotificationTemplate extends DeliveryMethodN public MobileAppDeliveryMethodNotificationTemplate(MobileAppDeliveryMethodNotificationTemplate other) { super(other); this.subject = other.subject; + this.additionalConfig = other.additionalConfig; } @Override diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/notification/FirebaseService.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/notification/FirebaseService.java index 96128c7410..28aa4c96af 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/notification/FirebaseService.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/notification/FirebaseService.java @@ -17,8 +17,10 @@ package org.thingsboard.rule.engine.api.notification; import org.thingsboard.server.common.data.id.TenantId; +import java.util.Map; + public interface FirebaseService { - void sendMessage(TenantId tenantId, String credentials, String fcmToken, String title, String body) throws Exception; + void sendMessage(TenantId tenantId, String credentials, String fcmToken, String title, String body, Map data) throws Exception; }