committed by
GitHub
64 changed files with 1179 additions and 1032 deletions
@ -0,0 +1,33 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2023 The Thingsboard Authors |
||||
|
* |
||||
|
* 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.thingsboard.server.service.ws; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
|
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@AllArgsConstructor |
||||
|
public class AuthCmd implements WsCmd { |
||||
|
private int cmdId; |
||||
|
private String token; |
||||
|
|
||||
|
@Override |
||||
|
public WsCmdType getType() { |
||||
|
return WsCmdType.AUTH; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2023 The Thingsboard Authors |
||||
|
* |
||||
|
* 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.thingsboard.server.service.ws; |
||||
|
|
||||
|
public enum WsCmdType { |
||||
|
AUTH, |
||||
|
|
||||
|
ATTRIBUTES, |
||||
|
TIMESERIES, |
||||
|
TIMESERIES_HISTORY, |
||||
|
ENTITY_DATA, |
||||
|
ENTITY_COUNT, |
||||
|
ALARM_DATA, |
||||
|
ALARM_COUNT, |
||||
|
|
||||
|
NOTIFICATIONS, |
||||
|
NOTIFICATIONS_COUNT, |
||||
|
MARK_NOTIFICATIONS_AS_READ, |
||||
|
MARK_ALL_NOTIFICATIONS_AS_READ, |
||||
|
|
||||
|
ALARM_DATA_UNSUBSCRIBE, |
||||
|
ALARM_COUNT_UNSUBSCRIBE, |
||||
|
ENTITY_DATA_UNSUBSCRIBE, |
||||
|
ENTITY_COUNT_UNSUBSCRIBE, |
||||
|
NOTIFICATIONS_UNSUBSCRIBE |
||||
|
} |
||||
@ -0,0 +1,71 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2023 The Thingsboard Authors |
||||
|
* |
||||
|
* 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.thingsboard.server.service.ws; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonSubTypes; |
||||
|
import com.fasterxml.jackson.annotation.JsonSubTypes.Type; |
||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo; |
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import org.thingsboard.server.service.ws.notification.cmd.MarkAllNotificationsAsReadCmd; |
||||
|
import org.thingsboard.server.service.ws.notification.cmd.MarkNotificationsAsReadCmd; |
||||
|
import org.thingsboard.server.service.ws.notification.cmd.NotificationsCountSubCmd; |
||||
|
import org.thingsboard.server.service.ws.notification.cmd.NotificationsSubCmd; |
||||
|
import org.thingsboard.server.service.ws.notification.cmd.NotificationsUnsubCmd; |
||||
|
import org.thingsboard.server.service.ws.telemetry.cmd.v1.AttributesSubscriptionCmd; |
||||
|
import org.thingsboard.server.service.ws.telemetry.cmd.v1.GetHistoryCmd; |
||||
|
import org.thingsboard.server.service.ws.telemetry.cmd.v1.TimeseriesSubscriptionCmd; |
||||
|
import org.thingsboard.server.service.ws.telemetry.cmd.v2.AlarmCountCmd; |
||||
|
import org.thingsboard.server.service.ws.telemetry.cmd.v2.AlarmCountUnsubscribeCmd; |
||||
|
import org.thingsboard.server.service.ws.telemetry.cmd.v2.AlarmDataCmd; |
||||
|
import org.thingsboard.server.service.ws.telemetry.cmd.v2.AlarmDataUnsubscribeCmd; |
||||
|
import org.thingsboard.server.service.ws.telemetry.cmd.v2.EntityCountCmd; |
||||
|
import org.thingsboard.server.service.ws.telemetry.cmd.v2.EntityCountUnsubscribeCmd; |
||||
|
import org.thingsboard.server.service.ws.telemetry.cmd.v2.EntityDataCmd; |
||||
|
import org.thingsboard.server.service.ws.telemetry.cmd.v2.EntityDataUnsubscribeCmd; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
@Data |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
public class WsCommandsWrapper { |
||||
|
|
||||
|
private AuthCmd authCmd; |
||||
|
|
||||
|
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") |
||||
|
@JsonSubTypes({ |
||||
|
@Type(name = "ATTRIBUTES", value = AttributesSubscriptionCmd.class), |
||||
|
@Type(name = "TIMESERIES", value = TimeseriesSubscriptionCmd.class), |
||||
|
@Type(name = "TIMESERIES_HISTORY", value = GetHistoryCmd.class), |
||||
|
@Type(name = "ENTITY_DATA", value = EntityDataCmd.class), |
||||
|
@Type(name = "ENTITY_COUNT", value = EntityCountCmd.class), |
||||
|
@Type(name = "ALARM_DATA", value = AlarmDataCmd.class), |
||||
|
@Type(name = "ALARM_COUNT", value = AlarmCountCmd.class), |
||||
|
@Type(name = "NOTIFICATIONS", value = NotificationsSubCmd.class), |
||||
|
@Type(name = "NOTIFICATIONS_COUNT", value = NotificationsCountSubCmd.class), |
||||
|
@Type(name = "MARK_NOTIFICATIONS_AS_READ", value = MarkNotificationsAsReadCmd.class), |
||||
|
@Type(name = "MARK_ALL_NOTIFICATIONS_AS_READ", value = MarkAllNotificationsAsReadCmd.class), |
||||
|
@Type(name = "ALARM_DATA_UNSUBSCRIBE", value = AlarmDataUnsubscribeCmd.class), |
||||
|
@Type(name = "ALARM_COUNT_UNSUBSCRIBE", value = AlarmCountUnsubscribeCmd.class), |
||||
|
@Type(name = "ENTITY_DATA_UNSUBSCRIBE", value = EntityDataUnsubscribeCmd.class), |
||||
|
@Type(name = "ENTITY_COUNT_UNSUBSCRIBE", value = EntityCountUnsubscribeCmd.class), |
||||
|
@Type(name = "NOTIFICATIONS_UNSUBSCRIBE", value = NotificationsUnsubCmd.class), |
||||
|
}) |
||||
|
private List<WsCmd> cmds; |
||||
|
|
||||
|
} |
||||
@ -1,240 +0,0 @@ |
|||||
///
|
|
||||
/// Copyright © 2016-2023 The Thingsboard Authors
|
|
||||
///
|
|
||||
/// 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.
|
|
||||
///
|
|
||||
|
|
||||
import { BehaviorSubject, ReplaySubject } from 'rxjs'; |
|
||||
import { CmdUpdate, CmdUpdateMsg, CmdUpdateType, WebsocketCmd } from '@shared/models/telemetry/telemetry.models'; |
|
||||
import { map } from 'rxjs/operators'; |
|
||||
import { NgZone } from '@angular/core'; |
|
||||
import { isDefinedAndNotNull } from '@core/utils'; |
|
||||
import { Notification } from '@shared/models/notification.models'; |
|
||||
import { CmdWrapper, WsSubscriber } from '@shared/models/websocket/websocket.models'; |
|
||||
import { NotificationWebsocketService } from '@core/ws/notification-websocket.service'; |
|
||||
|
|
||||
export class NotificationCountUpdate extends CmdUpdate { |
|
||||
totalUnreadCount: number; |
|
||||
|
|
||||
constructor(msg: NotificationCountUpdateMsg) { |
|
||||
super(msg); |
|
||||
this.totalUnreadCount = msg.totalUnreadCount; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export class NotificationsUpdate extends CmdUpdate { |
|
||||
totalUnreadCount: number; |
|
||||
update?: Notification; |
|
||||
notifications?: Notification[]; |
|
||||
|
|
||||
constructor(msg: NotificationsUpdateMsg) { |
|
||||
super(msg); |
|
||||
this.totalUnreadCount = msg.totalUnreadCount; |
|
||||
this.update = msg.update; |
|
||||
this.notifications = msg.notifications; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export class NotificationSubscriber extends WsSubscriber { |
|
||||
private notificationCountSubject = new ReplaySubject<NotificationCountUpdate>(1); |
|
||||
private notificationsSubject = new BehaviorSubject<NotificationsUpdate>({ |
|
||||
cmdId: 0, |
|
||||
cmdUpdateType: undefined, |
|
||||
errorCode: 0, |
|
||||
errorMsg: '', |
|
||||
notifications: null, |
|
||||
totalUnreadCount: 0 |
|
||||
}); |
|
||||
|
|
||||
public messageLimit = 10; |
|
||||
|
|
||||
public notificationCount$ = this.notificationCountSubject.asObservable().pipe(map(msg => msg.totalUnreadCount)); |
|
||||
public notifications$ = this.notificationsSubject.asObservable().pipe(map(msg => msg.notifications )); |
|
||||
|
|
||||
public static createNotificationCountSubscription(notificationWsService: NotificationWebsocketService, |
|
||||
zone: NgZone): NotificationSubscriber { |
|
||||
const subscriptionCommand = new UnreadCountSubCmd(); |
|
||||
const subscriber = new NotificationSubscriber(notificationWsService, zone); |
|
||||
subscriber.subscriptionCommands.push(subscriptionCommand); |
|
||||
return subscriber; |
|
||||
} |
|
||||
|
|
||||
public static createNotificationsSubscription(notificationWsService: NotificationWebsocketService, |
|
||||
zone: NgZone, limit = 10): NotificationSubscriber { |
|
||||
const subscriptionCommand = new UnreadSubCmd(limit); |
|
||||
const subscriber = new NotificationSubscriber(notificationWsService, zone); |
|
||||
subscriber.messageLimit = limit; |
|
||||
subscriber.subscriptionCommands.push(subscriptionCommand); |
|
||||
return subscriber; |
|
||||
} |
|
||||
|
|
||||
public static createMarkAsReadCommand(notificationWsService: NotificationWebsocketService, |
|
||||
ids: string[]): NotificationSubscriber { |
|
||||
const subscriptionCommand = new MarkAsReadCmd(ids); |
|
||||
const subscriber = new NotificationSubscriber(notificationWsService); |
|
||||
subscriber.subscriptionCommands.push(subscriptionCommand); |
|
||||
return subscriber; |
|
||||
} |
|
||||
|
|
||||
public static createMarkAllAsReadCommand(notificationWsService: NotificationWebsocketService): NotificationSubscriber { |
|
||||
const subscriptionCommand = new MarkAllAsReadCmd(); |
|
||||
const subscriber = new NotificationSubscriber(notificationWsService); |
|
||||
subscriber.subscriptionCommands.push(subscriptionCommand); |
|
||||
return subscriber; |
|
||||
} |
|
||||
|
|
||||
constructor(private notificationWsService: NotificationWebsocketService, protected zone?: NgZone) { |
|
||||
super(notificationWsService, zone); |
|
||||
} |
|
||||
|
|
||||
onNotificationCountUpdate(message: NotificationCountUpdate) { |
|
||||
if (this.zone) { |
|
||||
this.zone.run( |
|
||||
() => { |
|
||||
this.notificationCountSubject.next(message); |
|
||||
} |
|
||||
); |
|
||||
} else { |
|
||||
this.notificationCountSubject.next(message); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public complete() { |
|
||||
this.notificationCountSubject.complete(); |
|
||||
this.notificationsSubject.complete(); |
|
||||
super.complete(); |
|
||||
} |
|
||||
|
|
||||
onNotificationsUpdate(message: NotificationsUpdate) { |
|
||||
const currentNotifications = this.notificationsSubject.value; |
|
||||
let processMessage = message; |
|
||||
if (isDefinedAndNotNull(currentNotifications) && message.update) { |
|
||||
currentNotifications.notifications.unshift(message.update); |
|
||||
if (currentNotifications.notifications.length > this.messageLimit) { |
|
||||
currentNotifications.notifications.pop(); |
|
||||
} |
|
||||
processMessage = currentNotifications; |
|
||||
processMessage.totalUnreadCount = message.totalUnreadCount; |
|
||||
} |
|
||||
if (this.zone) { |
|
||||
this.zone.run( |
|
||||
() => { |
|
||||
this.notificationsSubject.next(processMessage); |
|
||||
this.notificationCountSubject.next(processMessage); |
|
||||
} |
|
||||
); |
|
||||
} else { |
|
||||
this.notificationsSubject.next(processMessage); |
|
||||
this.notificationCountSubject.next(processMessage); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export class UnreadCountSubCmd implements WebsocketCmd { |
|
||||
cmdId: number; |
|
||||
} |
|
||||
|
|
||||
export class UnreadSubCmd implements WebsocketCmd { |
|
||||
limit: number; |
|
||||
cmdId: number; |
|
||||
|
|
||||
constructor(limit = 10) { |
|
||||
this.limit = limit; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export class UnsubscribeCmd implements WebsocketCmd { |
|
||||
cmdId: number; |
|
||||
} |
|
||||
|
|
||||
export class MarkAsReadCmd implements WebsocketCmd { |
|
||||
|
|
||||
cmdId: number; |
|
||||
notifications: string[]; |
|
||||
|
|
||||
constructor(ids: string[]) { |
|
||||
this.notifications = ids; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export class MarkAllAsReadCmd implements WebsocketCmd { |
|
||||
cmdId: number; |
|
||||
} |
|
||||
|
|
||||
export interface NotificationCountUpdateMsg extends CmdUpdateMsg { |
|
||||
cmdUpdateType: CmdUpdateType.NOTIFICATIONS_COUNT; |
|
||||
totalUnreadCount: number; |
|
||||
} |
|
||||
|
|
||||
export interface NotificationsUpdateMsg extends CmdUpdateMsg { |
|
||||
cmdUpdateType: CmdUpdateType.NOTIFICATIONS; |
|
||||
totalUnreadCount: number; |
|
||||
update?: Notification; |
|
||||
notifications?: Notification[]; |
|
||||
} |
|
||||
|
|
||||
export type WebsocketNotificationMsg = NotificationCountUpdateMsg | NotificationsUpdateMsg; |
|
||||
|
|
||||
export const isNotificationCountUpdateMsg = (message: WebsocketNotificationMsg): message is NotificationCountUpdateMsg => { |
|
||||
const updateMsg = (message as CmdUpdateMsg); |
|
||||
return updateMsg.cmdId !== undefined && updateMsg.cmdUpdateType === CmdUpdateType.NOTIFICATIONS_COUNT; |
|
||||
}; |
|
||||
|
|
||||
export const isNotificationsUpdateMsg = (message: WebsocketNotificationMsg): message is NotificationsUpdateMsg => { |
|
||||
const updateMsg = (message as CmdUpdateMsg); |
|
||||
return updateMsg.cmdId !== undefined && updateMsg.cmdUpdateType === CmdUpdateType.NOTIFICATIONS; |
|
||||
}; |
|
||||
|
|
||||
export class NotificationPluginCmdWrapper implements CmdWrapper { |
|
||||
|
|
||||
constructor() { |
|
||||
this.unreadCountSubCmd = null; |
|
||||
this.unreadSubCmd = null; |
|
||||
this.unsubCmd = null; |
|
||||
this.markAsReadCmd = null; |
|
||||
this.markAllAsReadCmd = null; |
|
||||
} |
|
||||
|
|
||||
unreadCountSubCmd: UnreadCountSubCmd; |
|
||||
unreadSubCmd: UnreadSubCmd; |
|
||||
unsubCmd: UnsubscribeCmd; |
|
||||
markAsReadCmd: MarkAsReadCmd; |
|
||||
markAllAsReadCmd: MarkAllAsReadCmd; |
|
||||
|
|
||||
public hasCommands(): boolean { |
|
||||
return isDefinedAndNotNull(this.unreadCountSubCmd) || |
|
||||
isDefinedAndNotNull(this.unreadSubCmd) || |
|
||||
isDefinedAndNotNull(this.unsubCmd) || |
|
||||
isDefinedAndNotNull(this.markAsReadCmd) || |
|
||||
isDefinedAndNotNull(this.markAllAsReadCmd); |
|
||||
} |
|
||||
|
|
||||
public clear() { |
|
||||
this.unreadCountSubCmd = null; |
|
||||
this.unreadSubCmd = null; |
|
||||
this.unsubCmd = null; |
|
||||
this.markAsReadCmd = null; |
|
||||
this.markAllAsReadCmd = null; |
|
||||
} |
|
||||
|
|
||||
public preparePublishCommands(): NotificationPluginCmdWrapper { |
|
||||
const preparedWrapper = new NotificationPluginCmdWrapper(); |
|
||||
preparedWrapper.unreadCountSubCmd = this.unreadCountSubCmd || undefined; |
|
||||
preparedWrapper.unreadSubCmd = this.unreadSubCmd || undefined; |
|
||||
preparedWrapper.unsubCmd = this.unsubCmd || undefined; |
|
||||
preparedWrapper.markAsReadCmd = this.markAsReadCmd || undefined; |
|
||||
preparedWrapper.markAllAsReadCmd = this.markAllAsReadCmd || undefined; |
|
||||
this.clear(); |
|
||||
return preparedWrapper; |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue