576 changed files with 14574 additions and 8654 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,50 @@ |
|||
-- |
|||
-- Copyright © 2016-2022 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. |
|||
-- |
|||
|
|||
|
|||
DROP PROCEDURE IF EXISTS public.cleanup_events_by_ttl(bigint, bigint, bigint); |
|||
|
|||
CREATE OR REPLACE PROCEDURE cleanup_events_by_ttl( |
|||
IN regular_events_start_ts bigint, |
|||
IN regular_events_end_ts bigint, |
|||
IN debug_events_start_ts bigint, |
|||
IN debug_events_end_ts bigint, |
|||
INOUT deleted bigint) |
|||
LANGUAGE plpgsql AS |
|||
$$ |
|||
DECLARE |
|||
ttl_deleted_count bigint DEFAULT 0; |
|||
debug_ttl_deleted_count bigint DEFAULT 0; |
|||
BEGIN |
|||
IF regular_events_start_ts > 0 AND regular_events_end_ts > 0 THEN |
|||
EXECUTE format( |
|||
'WITH deleted AS (DELETE FROM event WHERE id in (SELECT id from event WHERE ts > %L::bigint AND ts < %L::bigint AND ' || |
|||
'(event_type != %L::varchar AND event_type != %L::varchar)) RETURNING *) ' || |
|||
'SELECT count(*) FROM deleted', regular_events_start_ts, regular_events_end_ts, |
|||
'DEBUG_RULE_NODE', 'DEBUG_RULE_CHAIN') into ttl_deleted_count; |
|||
END IF; |
|||
IF debug_events_start_ts > 0 AND debug_events_end_ts > 0 THEN |
|||
EXECUTE format( |
|||
'WITH deleted AS (DELETE FROM event WHERE id in (SELECT id from event WHERE ts > %L::bigint AND ts < %L::bigint AND ' || |
|||
'(event_type = %L::varchar OR event_type = %L::varchar)) RETURNING *) ' || |
|||
'SELECT count(*) FROM deleted', debug_events_start_ts, debug_events_end_ts, |
|||
'DEBUG_RULE_NODE', 'DEBUG_RULE_CHAIN') into debug_ttl_deleted_count; |
|||
END IF; |
|||
RAISE NOTICE 'Events removed by ttl: %', ttl_deleted_count; |
|||
RAISE NOTICE 'Debug Events removed by ttl: %', debug_ttl_deleted_count; |
|||
deleted := ttl_deleted_count + debug_ttl_deleted_count; |
|||
END |
|||
$$; |
|||
@ -0,0 +1,29 @@ |
|||
-- |
|||
-- Copyright © 2016-2022 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. |
|||
-- |
|||
|
|||
DELETE from ota_package as op WHERE NOT EXISTS(SELECT * FROM device_profile dp where op.device_profile_id = dp.id); |
|||
|
|||
DO |
|||
$$ |
|||
BEGIN |
|||
IF NOT EXISTS(SELECT 1 FROM pg_constraint WHERE conname = 'fk_device_profile_ota_package') THEN |
|||
ALTER TABLE ota_package |
|||
ADD CONSTRAINT fk_device_profile_ota_package |
|||
FOREIGN KEY (device_profile_id) REFERENCES device_profile (id) |
|||
ON DELETE CASCADE; |
|||
END IF; |
|||
END; |
|||
$$; |
|||
@ -1,48 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.edge.rpc; |
|||
|
|||
import com.fasterxml.jackson.databind.JsonNode; |
|||
import org.thingsboard.server.common.data.edge.EdgeEvent; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventType; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
public final class EdgeEventUtils { |
|||
|
|||
private EdgeEventUtils() { |
|||
} |
|||
|
|||
public static EdgeEvent constructEdgeEvent(TenantId tenantId, |
|||
EdgeId edgeId, |
|||
EdgeEventType type, |
|||
EdgeEventActionType action, |
|||
EntityId entityId, |
|||
JsonNode body) { |
|||
EdgeEvent edgeEvent = new EdgeEvent(); |
|||
edgeEvent.setTenantId(tenantId); |
|||
edgeEvent.setEdgeId(edgeId); |
|||
edgeEvent.setType(type); |
|||
edgeEvent.setAction(action); |
|||
if (entityId != null) { |
|||
edgeEvent.setEntityId(entityId.getId()); |
|||
} |
|||
edgeEvent.setBody(body); |
|||
return edgeEvent; |
|||
} |
|||
} |
|||
@ -0,0 +1,201 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy; |
|||
|
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
import com.google.common.util.concurrent.Futures; |
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import lombok.Getter; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.thingsboard.server.cluster.TbClusterService; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.HasName; |
|||
import org.thingsboard.server.common.data.User; |
|||
import org.thingsboard.server.common.data.alarm.AlarmInfo; |
|||
import org.thingsboard.server.common.data.alarm.AlarmQuery; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.AlarmId; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.EntityIdFactory; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.page.PageData; |
|||
import org.thingsboard.server.common.data.page.PageDataIterableByTenantIdEntityId; |
|||
import org.thingsboard.server.common.data.page.TimePageLink; |
|||
import org.thingsboard.server.dao.alarm.AlarmService; |
|||
import org.thingsboard.server.dao.asset.AssetService; |
|||
import org.thingsboard.server.dao.customer.CustomerService; |
|||
import org.thingsboard.server.dao.device.ClaimDevicesService; |
|||
import org.thingsboard.server.dao.device.DeviceCredentialsService; |
|||
import org.thingsboard.server.dao.device.DeviceService; |
|||
import org.thingsboard.server.dao.edge.EdgeService; |
|||
import org.thingsboard.server.dao.exception.DataValidationException; |
|||
import org.thingsboard.server.dao.exception.IncorrectParameterException; |
|||
import org.thingsboard.server.dao.model.ModelConstants; |
|||
import org.thingsboard.server.dao.rule.RuleChainService; |
|||
import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
|||
import org.thingsboard.server.dao.tenant.TenantService; |
|||
import org.thingsboard.server.service.action.EntityActionService; |
|||
import org.thingsboard.server.service.edge.EdgeNotificationService; |
|||
import org.thingsboard.server.service.executors.DbCallbackExecutorService; |
|||
|
|||
import javax.mail.MessagingException; |
|||
import java.util.ArrayList; |
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
import java.util.Optional; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractTbEntityService { |
|||
|
|||
protected static final int DEFAULT_PAGE_SIZE = 1000; |
|||
|
|||
private static final ObjectMapper json = new ObjectMapper(); |
|||
|
|||
@Value("${server.log_controller_error_stack_trace}") |
|||
@Getter |
|||
private boolean logControllerErrorStackTrace; |
|||
@Value("${edges.enabled}") |
|||
@Getter |
|||
protected boolean edgesEnabled; |
|||
|
|||
@Autowired |
|||
protected DbCallbackExecutorService dbExecutor; |
|||
@Autowired |
|||
protected TbNotificationEntityService notificationEntityService; |
|||
@Autowired(required = false) |
|||
protected EdgeService edgeService; |
|||
@Autowired |
|||
protected AlarmService alarmService; |
|||
@Autowired |
|||
protected EntityActionService entityActionService; |
|||
@Autowired |
|||
protected DeviceService deviceService; |
|||
@Autowired |
|||
protected AssetService assetService; |
|||
@Autowired |
|||
protected DeviceCredentialsService deviceCredentialsService; |
|||
@Autowired |
|||
protected TenantService tenantService; |
|||
@Autowired |
|||
protected CustomerService customerService; |
|||
@Autowired |
|||
protected ClaimDevicesService claimDevicesService; |
|||
@Autowired |
|||
protected TbTenantProfileCache tenantProfileCache; |
|||
@Autowired |
|||
protected RuleChainService ruleChainService; |
|||
@Autowired |
|||
protected EdgeNotificationService edgeNotificationService; |
|||
|
|||
protected ListenableFuture<Void> removeAlarmsByEntityId(TenantId tenantId, EntityId entityId) { |
|||
ListenableFuture<PageData<AlarmInfo>> alarmsFuture = |
|||
alarmService.findAlarms(tenantId, new AlarmQuery(entityId, new TimePageLink(Integer.MAX_VALUE), null, null, false)); |
|||
|
|||
ListenableFuture<List<AlarmId>> alarmIdsFuture = Futures.transform(alarmsFuture, page -> |
|||
page.getData().stream().map(AlarmInfo::getId).collect(Collectors.toList()), dbExecutor); |
|||
|
|||
return Futures.transform(alarmIdsFuture, ids -> { |
|||
ids.stream().map(alarmId -> alarmService.deleteAlarm(tenantId, alarmId)).collect(Collectors.toList()); |
|||
return null; |
|||
}, dbExecutor); |
|||
} |
|||
|
|||
protected <E extends HasName, I extends EntityId> void logEntityAction(User user, TenantId tenantId, I entityId, E entity, CustomerId customerId, |
|||
ActionType actionType, Exception e, Object... additionalInfo) throws ThingsboardException { |
|||
if (user != null) { |
|||
entityActionService.logEntityAction(user, entityId, entity, customerId, actionType, e, additionalInfo); |
|||
} else if (e == null) { |
|||
entityActionService.pushEntityActionToRuleEngine(entityId, entity, tenantId, customerId, actionType, null, additionalInfo); |
|||
} |
|||
} |
|||
|
|||
protected <T> T checkNotNull(T reference) throws ThingsboardException { |
|||
return checkNotNull(reference, "Requested item wasn't found!"); |
|||
} |
|||
|
|||
protected <T> T checkNotNull(T reference, String notFoundMessage) throws ThingsboardException { |
|||
if (reference == null) { |
|||
throw new ThingsboardException(notFoundMessage, ThingsboardErrorCode.ITEM_NOT_FOUND); |
|||
} |
|||
return reference; |
|||
} |
|||
|
|||
protected <T> T checkNotNull(Optional<T> reference) throws ThingsboardException { |
|||
return checkNotNull(reference, "Requested item wasn't found!"); |
|||
} |
|||
|
|||
protected <T> T checkNotNull(Optional<T> reference, String notFoundMessage) throws ThingsboardException { |
|||
if (reference.isPresent()) { |
|||
return reference.get(); |
|||
} else { |
|||
throw new ThingsboardException(notFoundMessage, ThingsboardErrorCode.ITEM_NOT_FOUND); |
|||
} |
|||
} |
|||
|
|||
protected ThingsboardException handleException(Exception exception) { |
|||
return handleException(exception, true); |
|||
} |
|||
|
|||
protected ThingsboardException handleException(Exception exception, boolean logException) { |
|||
if (logException && logControllerErrorStackTrace) { |
|||
log.error("Error [{}]", exception.getMessage(), exception); |
|||
} |
|||
|
|||
String cause = ""; |
|||
if (exception.getCause() != null) { |
|||
cause = exception.getCause().getClass().getCanonicalName(); |
|||
} |
|||
|
|||
if (exception instanceof ThingsboardException) { |
|||
return (ThingsboardException) exception; |
|||
} else if (exception instanceof IllegalArgumentException || exception instanceof IncorrectParameterException |
|||
|| exception instanceof DataValidationException || cause.contains("IncorrectParameterException")) { |
|||
return new ThingsboardException(exception.getMessage(), ThingsboardErrorCode.BAD_REQUEST_PARAMS); |
|||
} else if (exception instanceof MessagingException) { |
|||
return new ThingsboardException("Unable to send mail: " + exception.getMessage(), ThingsboardErrorCode.GENERAL); |
|||
} else { |
|||
return new ThingsboardException(exception.getMessage(), exception, ThingsboardErrorCode.GENERAL); |
|||
} |
|||
} |
|||
|
|||
@SuppressWarnings("unchecked") |
|||
protected <I extends EntityId> I emptyId(EntityType entityType) { |
|||
return (I) EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID); |
|||
} |
|||
|
|||
protected List<EdgeId> findRelatedEdgeIds(TenantId tenantId, EntityId entityId) { |
|||
if (!edgesEnabled) { |
|||
return null; |
|||
} |
|||
if (EntityType.EDGE.equals(entityId.getEntityType())) { |
|||
return Collections.singletonList(new EdgeId(entityId.getId())); |
|||
} |
|||
PageDataIterableByTenantIdEntityId<EdgeId> relatedEdgeIdsIterator = |
|||
new PageDataIterableByTenantIdEntityId<>(edgeService::findRelatedEdgeIdsByEntityId, tenantId, entityId, DEFAULT_PAGE_SIZE); |
|||
List<EdgeId> result = new ArrayList<>(); |
|||
for (EdgeId edgeId : relatedEdgeIdsIterator) { |
|||
result.add(edgeId); |
|||
} |
|||
return result; |
|||
} |
|||
} |
|||
@ -0,0 +1,262 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy; |
|||
|
|||
import com.fasterxml.jackson.core.JsonProcessingException; |
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg; |
|||
import org.thingsboard.server.cluster.TbClusterService; |
|||
import org.thingsboard.server.common.data.DataConstants; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.HasName; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.asset.Asset; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventType; |
|||
import org.thingsboard.server.common.data.id.AssetId; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.common.msg.TbMsg; |
|||
import org.thingsboard.server.common.msg.TbMsgDataType; |
|||
import org.thingsboard.server.common.msg.TbMsgMetaData; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.action.EntityActionService; |
|||
import org.thingsboard.server.service.gateway_device.GatewayNotificationsService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
@TbCoreComponent |
|||
@RequiredArgsConstructor |
|||
public class DefaultTbNotificationEntityService implements TbNotificationEntityService { |
|||
private static final ObjectMapper json = new ObjectMapper(); |
|||
|
|||
private final EntityActionService entityActionService; |
|||
private final TbClusterService tbClusterService; |
|||
private final GatewayNotificationsService gatewayNotificationsService; |
|||
|
|||
@Override |
|||
public <E extends HasName, I extends EntityId> void notifyEntity(TenantId tenantId, I entityId, E entity, CustomerId customerId, |
|||
ActionType actionType, SecurityUser user, Exception e, |
|||
Object... additionalInfo) { |
|||
logEntityAction(tenantId, entityId, entity, customerId, actionType, user, e, additionalInfo); |
|||
} |
|||
|
|||
@Override |
|||
public <E extends HasName, I extends EntityId> void notifyDeleteEntity(TenantId tenantId, I entityId, E entity, |
|||
CustomerId customerId, List<EdgeId> relatedEdgeIds, |
|||
SecurityUser user, Object... additionalInfo) { |
|||
logEntityAction(tenantId, entityId, entity, customerId, ActionType.DELETED, user, additionalInfo); |
|||
sendDeleteNotificationMsg(tenantId, entityId, relatedEdgeIds); |
|||
} |
|||
|
|||
@Override |
|||
public <E extends HasName, I extends EntityId> void notifyAssignOrUnassignEntityToCustomer(TenantId tenantId, I entityId, |
|||
CustomerId customerId, E entity, |
|||
ActionType actionType, |
|||
EdgeEventActionType edgeActionType, |
|||
SecurityUser user, boolean sendToEdge, |
|||
Object... additionalInfo) { |
|||
logEntityAction(tenantId, entityId, entity, customerId, actionType, user, additionalInfo); |
|||
|
|||
if (sendToEdge) { |
|||
sendEntityAssignToCustomerNotificationMsg(tenantId, entityId, customerId, edgeActionType); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public <E extends HasName, I extends EntityId> void notifyAssignOrUnassignEntityToEdge(TenantId tenantId, I entityId, |
|||
CustomerId customerId, EdgeId edgeId, |
|||
E entity, ActionType actionType, |
|||
EdgeEventActionType edgeActionType, |
|||
SecurityUser user, Object... additionalInfo) { |
|||
logEntityAction(tenantId, entityId, entity, customerId, actionType, user, additionalInfo); |
|||
sendEntityAssignToEdgeNotificationMsg(tenantId, edgeId, entityId, edgeActionType); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyCreateOruUpdateTenant(Tenant tenant, ComponentLifecycleEvent event) { |
|||
tbClusterService.onTenantChange(tenant, null); |
|||
tbClusterService.broadcastEntityStateChangeEvent(tenant.getId(), tenant.getId(), event); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyDeleteTenant(Tenant tenant) { |
|||
tbClusterService.onTenantDelete(tenant, null); |
|||
tbClusterService.broadcastEntityStateChangeEvent(tenant.getId(), tenant.getId(), ComponentLifecycleEvent.DELETED); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyCreateOrUpdateDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, |
|||
Device device, Device oldDevice, ActionType actionType, |
|||
SecurityUser user, Object... additionalInfo) { |
|||
tbClusterService.onDeviceUpdated(device, oldDevice); |
|||
logEntityAction(tenantId, deviceId, device, customerId, actionType, user, additionalInfo); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyDeleteDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, |
|||
List<EdgeId> relatedEdgeIds, SecurityUser user, Object... additionalInfo) { |
|||
gatewayNotificationsService.onDeviceDeleted(device); |
|||
tbClusterService.onDeviceDeleted(device, null); |
|||
|
|||
notifyDeleteEntity(tenantId, deviceId, device, customerId, relatedEdgeIds, user, additionalInfo); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyUpdateDeviceCredentials(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, |
|||
DeviceCredentials deviceCredentials, SecurityUser user) { |
|||
tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(tenantId, deviceCredentials.getDeviceId(), deviceCredentials), null); |
|||
sendEntityNotificationMsg(tenantId, deviceId, EdgeEventActionType.CREDENTIALS_UPDATED); |
|||
logEntityAction(tenantId, deviceId, device, customerId, ActionType.CREDENTIALS_UPDATED, user, deviceCredentials); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyAssignDeviceToTenant(TenantId tenantId, TenantId newTenantId, DeviceId deviceId, CustomerId customerId, |
|||
Device device, Tenant tenant, SecurityUser user, Object... additionalInfo) { |
|||
logEntityAction(tenantId, deviceId, device, customerId, ActionType.ASSIGNED_TO_TENANT, user, additionalInfo); |
|||
pushAssignedFromNotification(tenant, newTenantId, device); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyCreateOrUpdateAsset(TenantId tenantId, AssetId assetId, CustomerId customerId, Asset asset, |
|||
ActionType actionType, SecurityUser user, Object... additionalInfo) { |
|||
logEntityAction(tenantId, assetId, asset, customerId, actionType, user, additionalInfo); |
|||
|
|||
if (actionType == ActionType.UPDATED) { |
|||
sendEntityNotificationMsg(asset.getTenantId(), asset.getId(), EdgeEventActionType.UPDATED); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void notifyEdge(TenantId tenantId, EdgeId edgeId, CustomerId customerId, Edge edge, ActionType actionType, |
|||
SecurityUser user, Object... additionalInfo) { |
|||
ComponentLifecycleEvent lifecycleEvent; |
|||
EdgeEventActionType edgeEventActionType = null; |
|||
switch (actionType) { |
|||
case ADDED: |
|||
lifecycleEvent = ComponentLifecycleEvent.CREATED; |
|||
break; |
|||
case UPDATED: |
|||
lifecycleEvent = ComponentLifecycleEvent.UPDATED; |
|||
break; |
|||
case ASSIGNED_TO_CUSTOMER: |
|||
lifecycleEvent = ComponentLifecycleEvent.UPDATED; |
|||
edgeEventActionType = EdgeEventActionType.ASSIGNED_TO_CUSTOMER; |
|||
break; |
|||
case UNASSIGNED_FROM_CUSTOMER: |
|||
lifecycleEvent = ComponentLifecycleEvent.UPDATED; |
|||
edgeEventActionType = EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER; |
|||
break; |
|||
case DELETED: |
|||
lifecycleEvent = ComponentLifecycleEvent.DELETED; |
|||
break; |
|||
default: |
|||
throw new IllegalArgumentException("Unknown actionType: " + actionType); |
|||
} |
|||
|
|||
tbClusterService.broadcastEntityStateChangeEvent(tenantId, edgeId, lifecycleEvent); |
|||
logEntityAction(tenantId, edgeId, edge, customerId, actionType, user, additionalInfo); |
|||
|
|||
//Send notification to edge
|
|||
if (edgeEventActionType != null) { |
|||
sendEntityAssignToCustomerNotificationMsg(tenantId, edgeId, customerId, edgeEventActionType); |
|||
} |
|||
} |
|||
|
|||
private <E extends HasName, I extends EntityId> void logEntityAction(TenantId tenantId, I entityId, E entity, CustomerId customerId, |
|||
ActionType actionType, SecurityUser user, Object... additionalInfo) { |
|||
logEntityAction(tenantId, entityId, entity, customerId, actionType, user, null, additionalInfo); |
|||
} |
|||
|
|||
private <E extends HasName, I extends EntityId> void logEntityAction(TenantId tenantId, I entityId, E entity, CustomerId customerId, |
|||
ActionType actionType, SecurityUser user, Exception e, Object... additionalInfo) { |
|||
if (user != null) { |
|||
entityActionService.logEntityAction(user, entityId, entity, customerId, actionType, e, additionalInfo); |
|||
} else if (e == null) { |
|||
entityActionService.pushEntityActionToRuleEngine(entityId, entity, tenantId, customerId, actionType, null, additionalInfo); |
|||
} |
|||
} |
|||
|
|||
private void sendEntityNotificationMsg(TenantId tenantId, EntityId entityId, EdgeEventActionType action) { |
|||
sendNotificationMsgToEdgeService(tenantId, null, entityId, null, null, action); |
|||
} |
|||
|
|||
private void sendEntityAssignToCustomerNotificationMsg(TenantId tenantId, EntityId entityId, CustomerId customerId, EdgeEventActionType action) { |
|||
try { |
|||
sendNotificationMsgToEdgeService(tenantId, null, entityId, json.writeValueAsString(customerId), null, action); |
|||
} catch (Exception e) { |
|||
log.warn("Failed to push assign/unassign to/from customer to core: {}", customerId, e); |
|||
} |
|||
} |
|||
|
|||
private void sendDeleteNotificationMsg(TenantId tenantId, EntityId entityId, List<EdgeId> edgeIds) { |
|||
sendDeleteNotificationMsg(tenantId, entityId, edgeIds, null); |
|||
} |
|||
|
|||
private void sendDeleteNotificationMsg(TenantId tenantId, EntityId entityId, List<EdgeId> edgeIds, String body) { |
|||
if (edgeIds != null && !edgeIds.isEmpty()) { |
|||
for (EdgeId edgeId : edgeIds) { |
|||
sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, body, null, EdgeEventActionType.DELETED); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void sendEntityAssignToEdgeNotificationMsg(TenantId tenantId, EdgeId edgeId, EntityId entityId, EdgeEventActionType action) { |
|||
sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, null, null, action); |
|||
} |
|||
|
|||
private void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, String body, EdgeEventType type, EdgeEventActionType action) { |
|||
tbClusterService.sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, body, type, action); |
|||
} |
|||
|
|||
private void pushAssignedFromNotification(Tenant currentTenant, TenantId newTenantId, Device assignedDevice) { |
|||
String data = entityToStr(assignedDevice); |
|||
if (data != null) { |
|||
TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_ASSIGNED_FROM_TENANT, assignedDevice.getId(), assignedDevice.getCustomerId(), getMetaDataForAssignedFrom(currentTenant), TbMsgDataType.JSON, data); |
|||
tbClusterService.pushMsgToRuleEngine(newTenantId, assignedDevice.getId(), tbMsg, null); |
|||
} |
|||
} |
|||
|
|||
private TbMsgMetaData getMetaDataForAssignedFrom(Tenant tenant) { |
|||
TbMsgMetaData metaData = new TbMsgMetaData(); |
|||
metaData.putValue("assignedFromTenantId", tenant.getId().getId().toString()); |
|||
metaData.putValue("assignedFromTenantName", tenant.getName()); |
|||
return metaData; |
|||
} |
|||
|
|||
private <E extends HasName> String entityToStr(E entity) { |
|||
try { |
|||
return json.writeValueAsString(json.valueToTree(entity)); |
|||
} catch (JsonProcessingException e) { |
|||
log.warn("[{}] Failed to convert entity to string!", entity, e); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,81 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy; |
|||
|
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.HasName; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.asset.Asset; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
|||
import org.thingsboard.server.common.data.id.AssetId; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import java.util.List; |
|||
|
|||
public interface TbNotificationEntityService { |
|||
|
|||
<E extends HasName, I extends EntityId> void notifyEntity(TenantId tenantId, I entityId, E entity, CustomerId customerId, |
|||
ActionType actionType, SecurityUser user, Exception e, |
|||
Object... additionalInfo); |
|||
|
|||
<E extends HasName, I extends EntityId> void notifyDeleteEntity(TenantId tenantId, I entityId, E entity, CustomerId customerId, |
|||
List<EdgeId> relatedEdgeIds, SecurityUser user, |
|||
Object... additionalInfo); |
|||
|
|||
<E extends HasName, I extends EntityId> void notifyAssignOrUnassignEntityToCustomer(TenantId tenantId, I entityId, |
|||
CustomerId customerId, E entity, |
|||
ActionType actionType, |
|||
EdgeEventActionType edgeActionType, |
|||
SecurityUser user, boolean sendToEdge, |
|||
Object... additionalInfo); |
|||
|
|||
<E extends HasName, I extends EntityId> void notifyAssignOrUnassignEntityToEdge(TenantId tenantId, I entityId, |
|||
CustomerId customerId, EdgeId edgeId, |
|||
E entity, ActionType actionType, |
|||
EdgeEventActionType edgeActionType, |
|||
SecurityUser user, Object... additionalInfo); |
|||
|
|||
void notifyCreateOruUpdateTenant(Tenant tenant, ComponentLifecycleEvent event); |
|||
|
|||
void notifyDeleteTenant(Tenant tenant); |
|||
|
|||
void notifyCreateOrUpdateDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, |
|||
Device oldDevice, ActionType actionType, SecurityUser user, Object... additionalInfo); |
|||
|
|||
void notifyDeleteDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, |
|||
List<EdgeId> relatedEdgeIds, SecurityUser user, Object... additionalInfo); |
|||
|
|||
void notifyUpdateDeviceCredentials(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, |
|||
DeviceCredentials deviceCredentials, SecurityUser user); |
|||
|
|||
void notifyAssignDeviceToTenant(TenantId tenantId, TenantId newTenantId, DeviceId deviceId, CustomerId customerId, |
|||
Device device, Tenant tenant, SecurityUser user, Object... additionalInfo); |
|||
|
|||
void notifyCreateOrUpdateAsset(TenantId tenantId, AssetId assetId, CustomerId customerId, Asset asset, |
|||
ActionType actionType, SecurityUser user, Object... additionalInfo); |
|||
|
|||
void notifyEdge(TenantId tenantId, EdgeId edgeId, CustomerId customerId, Edge edge, ActionType actionType, SecurityUser user, Object... additionalInfo); |
|||
|
|||
} |
|||
@ -0,0 +1,163 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.asset; |
|||
|
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import lombok.AllArgsConstructor; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.asset.Asset; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.AssetId; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Service |
|||
@TbCoreComponent |
|||
@AllArgsConstructor |
|||
public class DefaultTbAssetService extends AbstractTbEntityService implements TbAssetService { |
|||
@Override |
|||
public Asset save(Asset asset, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
|||
TenantId tenantId = asset.getTenantId(); |
|||
try { |
|||
Asset savedAsset = checkNotNull(assetService.saveAsset(asset)); |
|||
notificationEntityService.notifyCreateOrUpdateAsset(tenantId, savedAsset.getId(), savedAsset.getCustomerId(), asset, actionType, user); |
|||
return savedAsset; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), asset, null, actionType, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<Void> delete(Asset asset, SecurityUser user) throws ThingsboardException { |
|||
TenantId tenantId = asset.getTenantId(); |
|||
AssetId assetId = asset.getId(); |
|||
try { |
|||
List<EdgeId> relatedEdgeIds = findRelatedEdgeIds(tenantId, assetId); |
|||
assetService.deleteAsset(tenantId, assetId); |
|||
notificationEntityService.notifyDeleteEntity(tenantId, assetId, asset, asset.getCustomerId(), relatedEdgeIds, user, asset.toString()); |
|||
|
|||
return removeAlarmsByEntityId(tenantId, assetId); |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, |
|||
ActionType.DELETED, user, e, asset.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Asset assignAssetToCustomer(TenantId tenantId, AssetId assetId, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
CustomerId customerId = customer.getId(); |
|||
try { |
|||
Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(tenantId, assetId, customerId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, customerId, savedAsset, |
|||
actionType, EdgeEventActionType.ASSIGNED_TO_CUSTOMER, user, true, customerId.toString(), customer.getName()); |
|||
|
|||
return savedAsset; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, |
|||
actionType, user, e, assetId.toString(), customerId.toString()); |
|||
|
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Asset unassignAssetToCustomer(TenantId tenantId, AssetId assetId, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER; |
|||
try { |
|||
Asset savedAsset = checkNotNull(assetService.unassignAssetFromCustomer(tenantId, assetId)); |
|||
CustomerId customerId = customer.getId(); |
|||
|
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, customerId, savedAsset, |
|||
actionType, EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER, user, |
|||
true, customerId.toString(), customer.getName()); |
|||
|
|||
return savedAsset; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, |
|||
actionType, user, e, assetId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Asset assignAssetToPublicCustomer(TenantId tenantId, AssetId assetId, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
try { |
|||
Customer publicCustomer = customerService.findOrCreatePublicCustomer(tenantId); |
|||
Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(tenantId, assetId, publicCustomer.getId())); |
|||
|
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, savedAsset.getCustomerId(), savedAsset, |
|||
actionType, null, user, false, actionType.toString(), |
|||
publicCustomer.getId().toString(), publicCustomer.getName()); |
|||
|
|||
return savedAsset; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, |
|||
actionType, user, e, assetId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Asset assignAssetToEdge(TenantId tenantId, AssetId assetId, Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_EDGE; |
|||
EdgeId edgeId = edge.getId(); |
|||
try { |
|||
Asset savedAsset = checkNotNull(assetService.assignAssetToEdge(tenantId, assetId, edgeId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, assetId, savedAsset.getCustomerId(), |
|||
edgeId, savedAsset, actionType, EdgeEventActionType.ASSIGNED_TO_EDGE, user, assetId.toString(), edgeId.toString(), edge.getName()); |
|||
|
|||
return savedAsset; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, |
|||
actionType, user, e, assetId.toString(), edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Asset unassignAssetFromEdge(TenantId tenantId, Asset asset, Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_EDGE; |
|||
AssetId assetId = asset.getId(); |
|||
EdgeId edgeId = edge.getId(); |
|||
try { |
|||
Asset savedAsset = checkNotNull(assetService.unassignAssetFromEdge(tenantId, assetId, edgeId)); |
|||
|
|||
notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, assetId, asset.getCustomerId(), |
|||
edgeId, asset, actionType, EdgeEventActionType.UNASSIGNED_FROM_EDGE, user, assetId.toString(), edgeId.toString(), edge.getName()); |
|||
return savedAsset; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, |
|||
actionType, user, e, assetId.toString(), edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.asset; |
|||
|
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.asset.Asset; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.AssetId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
public interface TbAssetService { |
|||
Asset save(Asset asset, SecurityUser user) throws ThingsboardException; |
|||
|
|||
ListenableFuture<Void> delete(Asset asset, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Asset assignAssetToCustomer(TenantId tenantId, AssetId assetId, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Asset unassignAssetToCustomer(TenantId tenantId, AssetId assetId, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Asset assignAssetToPublicCustomer(TenantId tenantId, AssetId assetId, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Asset assignAssetToEdge(TenantId tenantId, AssetId assetId, Edge edge, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Asset unassignAssetFromEdge(TenantId tenantId, Asset asset, Edge edge, SecurityUser user) throws ThingsboardException; |
|||
|
|||
} |
|||
@ -0,0 +1,279 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.device; |
|||
|
|||
import com.google.common.util.concurrent.Futures; |
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import com.google.common.util.concurrent.MoreExecutors; |
|||
import lombok.AllArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.dao.device.claim.ClaimResponse; |
|||
import org.thingsboard.server.dao.device.claim.ClaimResult; |
|||
import org.thingsboard.server.dao.device.claim.ReclaimResult; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import java.util.List; |
|||
|
|||
@AllArgsConstructor |
|||
@TbCoreComponent |
|||
@Service |
|||
@Slf4j |
|||
public class DefaultTbDeviceService extends AbstractTbEntityService implements TbDeviceService { |
|||
|
|||
@Override |
|||
public Device save(TenantId tenantId, Device device, Device oldDevice, String accessToken, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = device.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
|||
try { |
|||
Device savedDevice = checkNotNull(deviceService.saveDeviceWithAccessToken(device, accessToken)); |
|||
notificationEntityService.notifyCreateOrUpdateDevice(tenantId, savedDevice.getId(), savedDevice.getCustomerId(), |
|||
savedDevice, oldDevice, actionType, user); |
|||
|
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), device, null, actionType, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device saveDeviceWithCredentials(TenantId tenantId, Device device, DeviceCredentials credentials, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = device.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
|||
try { |
|||
Device savedDevice = checkNotNull(deviceService.saveDeviceWithCredentials(device, credentials)); |
|||
notificationEntityService.notifyCreateOrUpdateDevice(tenantId, savedDevice.getId(), savedDevice.getCustomerId(), |
|||
savedDevice, device, actionType, user); |
|||
|
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), device, null, actionType, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<Void> deleteDevice(Device device, SecurityUser user) throws ThingsboardException { |
|||
TenantId tenantId = device.getTenantId(); |
|||
DeviceId deviceId = device.getId(); |
|||
try { |
|||
List<EdgeId> relatedEdgeIds = findRelatedEdgeIds(tenantId, deviceId); |
|||
deviceService.deleteDevice(tenantId, deviceId); |
|||
notificationEntityService.notifyDeleteDevice(tenantId, deviceId, device.getCustomerId(), device, |
|||
relatedEdgeIds, user, deviceId.toString()); |
|||
|
|||
return removeAlarmsByEntityId(tenantId, deviceId); |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
ActionType.DELETED, user, e, deviceId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
CustomerId customerId = customer.getId(); |
|||
try { |
|||
Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(user.getTenantId(), deviceId, customerId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, deviceId, customerId, savedDevice, |
|||
actionType, EdgeEventActionType.ASSIGNED_TO_CUSTOMER, user, true, customerId.toString(), customer.getName()); |
|||
|
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, deviceId.toString(), customerId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device unassignDeviceFromCustomer(Device device, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER; |
|||
TenantId tenantId = device.getTenantId(); |
|||
DeviceId deviceId = device.getId(); |
|||
try { |
|||
Device savedDevice = checkNotNull(deviceService.unassignDeviceFromCustomer(tenantId, deviceId)); |
|||
CustomerId customerId = customer.getId(); |
|||
|
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, deviceId, customerId, savedDevice, |
|||
actionType, EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER, user, |
|||
true, customerId.toString(), customer.getName()); |
|||
|
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, deviceId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device assignDeviceToPublicCustomer(TenantId tenantId, DeviceId deviceId, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
try { |
|||
Customer publicCustomer = customerService.findOrCreatePublicCustomer(tenantId); |
|||
Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(tenantId, deviceId, publicCustomer.getId())); |
|||
|
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, deviceId, savedDevice.getCustomerId(), savedDevice, |
|||
actionType, null, user, false, deviceId.toString(), |
|||
publicCustomer.getId().toString(), publicCustomer.getName()); |
|||
|
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, deviceId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public DeviceCredentials getDeviceCredentialsByDeviceId(Device device, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.CREDENTIALS_READ; |
|||
TenantId tenantId = device.getTenantId(); |
|||
DeviceId deviceId = device.getId(); |
|||
try { |
|||
DeviceCredentials deviceCredentials = checkNotNull(deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, deviceId)); |
|||
notificationEntityService.notifyEntity(tenantId, deviceId, device, device.getCustomerId(), |
|||
actionType, user, null, deviceId.toString()); |
|||
return deviceCredentials; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, deviceId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public DeviceCredentials updateDeviceCredentials(Device device, DeviceCredentials deviceCredentials, SecurityUser user) throws ThingsboardException { |
|||
TenantId tenantId = device.getTenantId(); |
|||
DeviceId deviceId = device.getId(); |
|||
try { |
|||
DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(tenantId, deviceCredentials)); |
|||
notificationEntityService.notifyUpdateDeviceCredentials(tenantId, deviceId, device.getCustomerId(), device, result, user); |
|||
return result; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
ActionType.CREDENTIALS_UPDATED, user, e, deviceCredentials); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<ClaimResult> claimDevice(TenantId tenantId, Device device, CustomerId customerId, String secretKey, SecurityUser user) throws ThingsboardException { |
|||
try { |
|||
ListenableFuture<ClaimResult> future = claimDevicesService.claimDevice(device, customerId, secretKey); |
|||
|
|||
return Futures.transform(future, result -> { |
|||
if (result != null && result.getResponse().equals(ClaimResponse.SUCCESS)) { |
|||
notificationEntityService.notifyEntity(tenantId, device.getId(), result.getDevice(), customerId, |
|||
ActionType.ASSIGNED_TO_CUSTOMER, user, null, device.getId().toString(), customerId.toString(), |
|||
customerService.findCustomerById(tenantId, customerId).getName()); |
|||
} |
|||
return result; |
|||
}, MoreExecutors.directExecutor()); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<ReclaimResult> reclaimDevice(TenantId tenantId, Device device, SecurityUser user) throws ThingsboardException { |
|||
try { |
|||
ListenableFuture<ReclaimResult> future = claimDevicesService.reClaimDevice(tenantId, device); |
|||
|
|||
return Futures.transform(future, result -> { |
|||
Customer unassignedCustomer = result.getUnassignedCustomer(); |
|||
if (unassignedCustomer != null) { |
|||
notificationEntityService.notifyEntity(tenantId, device.getId(), device, device.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER, user, null, |
|||
device.getId().toString(), unassignedCustomer.getId().toString(), unassignedCustomer.getName()); |
|||
} |
|||
return result; |
|||
}, MoreExecutors.directExecutor()); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device assignDeviceToTenant(Device device, Tenant newTenant, SecurityUser user) throws ThingsboardException { |
|||
TenantId tenantId = device.getTenantId(); |
|||
TenantId newTenantId = newTenant.getId(); |
|||
try { |
|||
Tenant tenant = tenantService.findTenantById(tenantId); |
|||
Device assignedDevice = deviceService.assignDeviceToTenant(newTenantId, device); |
|||
|
|||
notificationEntityService.notifyAssignDeviceToTenant(tenantId, newTenantId, device.getId(), |
|||
assignedDevice.getCustomerId(), assignedDevice, tenant, user, newTenantId.toString(), newTenant.getName()); |
|||
|
|||
return assignedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
ActionType.ASSIGNED_TO_TENANT, user, e, newTenantId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device assignDeviceToEdge(TenantId tenantId, DeviceId deviceId, Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_EDGE; |
|||
EdgeId edgeId = edge.getId(); |
|||
try { |
|||
Device savedDevice = checkNotNull(deviceService.assignDeviceToEdge(tenantId, deviceId, edgeId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, deviceId, savedDevice.getCustomerId(), |
|||
edgeId, savedDevice, actionType, EdgeEventActionType.ASSIGNED_TO_EDGE, user, deviceId.toString(), edgeId.toString(), edge.getName()); |
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, deviceId.toString(), edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device unassignDeviceFromEdge(Device device, Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_EDGE; |
|||
TenantId tenantId = device.getTenantId(); |
|||
DeviceId deviceId = device.getId(); |
|||
EdgeId edgeId = edge.getId(); |
|||
try { |
|||
Device savedDevice = checkNotNull(deviceService.unassignDeviceFromEdge(tenantId, deviceId, edgeId)); |
|||
|
|||
notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, deviceId, device.getCustomerId(), |
|||
edgeId, device, actionType, EdgeEventActionType.UNASSIGNED_FROM_EDGE, user, deviceId.toString(), edgeId.toString(), edge.getName()); |
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, deviceId.toString(), edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.device; |
|||
|
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.dao.device.claim.ClaimResult; |
|||
import org.thingsboard.server.dao.device.claim.ReclaimResult; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
public interface TbDeviceService { |
|||
|
|||
Device save(TenantId tenantId, Device device, Device oldDevice, String accessToken, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device saveDeviceWithCredentials(TenantId tenantId, Device device, DeviceCredentials deviceCredentials, SecurityUser user) throws ThingsboardException; |
|||
|
|||
ListenableFuture<Void> deleteDevice(Device device, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device unassignDeviceFromCustomer(Device device, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device assignDeviceToPublicCustomer(TenantId tenantId, DeviceId deviceId, SecurityUser user) throws ThingsboardException; |
|||
|
|||
DeviceCredentials getDeviceCredentialsByDeviceId(Device device, SecurityUser user) throws ThingsboardException; |
|||
|
|||
DeviceCredentials updateDeviceCredentials(Device device, DeviceCredentials deviceCredentials, SecurityUser user) throws ThingsboardException; |
|||
|
|||
ListenableFuture<ClaimResult> claimDevice(TenantId tenantId, Device device, CustomerId customerId, String secretKey, SecurityUser user) throws ThingsboardException; |
|||
|
|||
ListenableFuture<ReclaimResult> reclaimDevice(TenantId tenantId, Device device, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device assignDeviceToTenant(Device device, Tenant newTenant, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device assignDeviceToEdge(TenantId tenantId, DeviceId deviceId, Edge edge, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device unassignDeviceFromEdge(Device device, Edge edge, SecurityUser user) throws ThingsboardException; |
|||
} |
|||
@ -0,0 +1,150 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.edge; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.RuleChainId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.rule.RuleChain; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
@AllArgsConstructor |
|||
@TbCoreComponent |
|||
@Service |
|||
@Slf4j |
|||
public class DefaultTbEdgeService extends AbstractTbEntityService implements TbEdgeService { |
|||
|
|||
@Override |
|||
public Edge saveEdge(Edge edge, RuleChain edgeTemplateRootRuleChain, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = edge.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
|||
TenantId tenantId = edge.getTenantId(); |
|||
try { |
|||
Edge savedEdge = checkNotNull(edgeService.saveEdge(edge)); |
|||
EdgeId edgeId = savedEdge.getId(); |
|||
|
|||
if (actionType == ActionType.ADDED) { |
|||
ruleChainService.assignRuleChainToEdge(tenantId, edgeTemplateRootRuleChain.getId(), edgeId); |
|||
edgeNotificationService.setEdgeRootRuleChain(tenantId, savedEdge, edgeTemplateRootRuleChain.getId()); |
|||
edgeService.assignDefaultRuleChainsToEdge(tenantId, edgeId); |
|||
} |
|||
|
|||
notificationEntityService.notifyEdge(tenantId, edgeId, savedEdge.getCustomerId(), savedEdge, actionType, user); |
|||
|
|||
return savedEdge; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), edge, null, actionType, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void deleteEdge(Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.DELETED; |
|||
EdgeId edgeId = edge.getId(); |
|||
TenantId tenantId = edge.getTenantId(); |
|||
try { |
|||
edgeService.deleteEdge(tenantId, edgeId); |
|||
notificationEntityService.notifyEdge(tenantId, edgeId, edge.getCustomerId(), edge, actionType, user, edgeId.toString()); |
|||
|
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), edge, null, actionType, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Edge assignEdgeToCustomer(TenantId tenantId, EdgeId edgeId, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
CustomerId customerId = customer.getId(); |
|||
try { |
|||
Edge savedEdge = checkNotNull(edgeService.assignEdgeToCustomer(tenantId, edgeId, customerId)); |
|||
|
|||
notificationEntityService.notifyEdge(tenantId, edgeId, customerId, savedEdge, actionType, user, |
|||
edgeId.toString(), customerId.toString(), customer.getName()); |
|||
|
|||
return savedEdge; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), null, null, |
|||
actionType, user, e, edgeId.toString(), customerId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Edge unassignEdgeFromCustomer(Edge edge, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER; |
|||
TenantId tenantId = edge.getTenantId(); |
|||
EdgeId edgeId = edge.getId(); |
|||
CustomerId customerId = customer.getId(); |
|||
try { |
|||
Edge savedEdge = checkNotNull(edgeService.unassignEdgeFromCustomer(tenantId, edgeId)); |
|||
|
|||
notificationEntityService.notifyEdge(tenantId, edgeId, customerId, savedEdge, actionType, user, |
|||
edgeId.toString(), customerId.toString(), customer.getName()); |
|||
return savedEdge; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), null, null, |
|||
actionType, user, e, edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Edge assignEdgeToPublicCustomer(TenantId tenantId, EdgeId edgeId, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
try { |
|||
Customer publicCustomer = customerService.findOrCreatePublicCustomer(tenantId); |
|||
CustomerId customerId = publicCustomer.getId(); |
|||
Edge savedEdge = checkNotNull(edgeService.assignEdgeToCustomer(tenantId, edgeId, customerId)); |
|||
|
|||
notificationEntityService.notifyEdge(tenantId, edgeId, customerId, savedEdge, actionType, user, |
|||
edgeId.toString(), customerId.toString(), publicCustomer.getName()); |
|||
|
|||
return savedEdge; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), null, null, |
|||
actionType, user, e, edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Edge setEdgeRootRuleChain(Edge edge, RuleChainId ruleChainId, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UPDATED; |
|||
TenantId tenantId = edge.getTenantId(); |
|||
EdgeId edgeId = edge.getId(); |
|||
try { |
|||
Edge updatedEdge = edgeNotificationService.setEdgeRootRuleChain(tenantId, edge, ruleChainId); |
|||
notificationEntityService.notifyEdge(tenantId, edgeId, null, updatedEdge, actionType, user); |
|||
return updatedEdge; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), null, null, |
|||
actionType, user, e, edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.edge; |
|||
|
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.RuleChainId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.rule.RuleChain; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
public interface TbEdgeService { |
|||
Edge saveEdge(Edge edge, RuleChain edgeTemplateRootRuleChain, SecurityUser user) throws ThingsboardException; |
|||
|
|||
void deleteEdge(Edge edge, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Edge assignEdgeToCustomer(TenantId tenantId, EdgeId edgeId, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Edge unassignEdgeFromCustomer(Edge edge, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Edge assignEdgeToPublicCustomer(TenantId tenantId, EdgeId edgeId, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Edge setEdgeRootRuleChain(Edge edge, RuleChainId ruleChainId, SecurityUser user) throws ThingsboardException; |
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.tenant; |
|||
|
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.TenantProfile; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
|||
import org.thingsboard.server.dao.tenant.TenantProfileService; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
|||
import org.thingsboard.server.service.entitiy.queue.TbQueueService; |
|||
import org.thingsboard.server.service.install.InstallScripts; |
|||
|
|||
import java.util.Collections; |
|||
|
|||
@Service |
|||
@TbCoreComponent |
|||
@RequiredArgsConstructor |
|||
public class DefaultTbTenantService extends AbstractTbEntityService implements TbTenantService { |
|||
|
|||
private final InstallScripts installScripts; |
|||
private final TbQueueService tbQueueService; |
|||
private final TenantProfileService tenantProfileService; |
|||
|
|||
@Override |
|||
public Tenant save(Tenant tenant) throws ThingsboardException { |
|||
try { |
|||
boolean created = tenant.getId() == null; |
|||
Tenant oldTenant = !created ? tenantService.findTenantById(tenant.getId()) : null; |
|||
|
|||
Tenant savedTenant = checkNotNull(tenantService.saveTenant(tenant)); |
|||
if (created) { |
|||
installScripts.createDefaultRuleChains(savedTenant.getId()); |
|||
installScripts.createDefaultEdgeRuleChains(savedTenant.getId()); |
|||
} |
|||
tenantProfileCache.evict(savedTenant.getId()); |
|||
notificationEntityService.notifyCreateOruUpdateTenant(savedTenant, created ? |
|||
ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); |
|||
|
|||
TenantProfile oldTenantProfile = oldTenant != null ? tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, oldTenant.getTenantProfileId()) : null; |
|||
TenantProfile newTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenant.getTenantProfileId()); |
|||
tbQueueService.updateQueuesByTenants(Collections.singletonList(savedTenant.getTenantId()), newTenantProfile, oldTenantProfile); |
|||
return savedTenant; |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void delete(Tenant tenant) throws ThingsboardException { |
|||
try { |
|||
TenantId tenantId = tenant.getId(); |
|||
tenantService.deleteTenant(tenantId); |
|||
tenantProfileCache.evict(tenantId); |
|||
notificationEntityService.notifyDeleteTenant(tenant); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
} |
|||
@ -1,58 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entity.tenant; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.TenantProfile; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
|||
import org.thingsboard.server.dao.tenant.TenantProfileService; |
|||
import org.thingsboard.server.dao.tenant.TenantService; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entity.queue.TbQueueService; |
|||
|
|||
import java.util.Collections; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
@TbCoreComponent |
|||
@AllArgsConstructor |
|||
public class DefaultTbTenantService implements TbTenantService { |
|||
|
|||
private final TenantService tenantService; |
|||
private final TbQueueService tbQueueService; |
|||
private final TenantProfileService tenantProfileService; |
|||
private final TbTenantProfileCache tenantProfileCache; |
|||
|
|||
@Override |
|||
public Tenant saveTenant(Tenant tenant) { |
|||
boolean updated = tenant.getId() != null; |
|||
Tenant oldTenant = updated ? tenantService.findTenantById(tenant.getId()) : null; |
|||
|
|||
Tenant savedTenant = tenantService.saveTenant(tenant); |
|||
tenantProfileCache.evict(savedTenant.getId()); |
|||
|
|||
TenantProfile oldTenantProfile = oldTenant != null ? tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, oldTenant.getTenantProfileId()) : null; |
|||
TenantProfile newTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenant.getTenantProfileId()); |
|||
//TODO: send notifications before queue update
|
|||
tbQueueService.updateQueuesByTenants(Collections.singletonList(savedTenant.getTenantId()), newTenantProfile, oldTenantProfile); |
|||
return savedTenant; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,148 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.partition; |
|||
|
|||
import com.google.common.util.concurrent.ListeningScheduledExecutorService; |
|||
import com.google.common.util.concurrent.MoreExecutors; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.common.util.ThingsBoardThreadFactory; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
|||
import org.thingsboard.server.queue.discovery.TbApplicationEventListener; |
|||
import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; |
|||
|
|||
import java.util.HashSet; |
|||
import java.util.Queue; |
|||
import java.util.Set; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
import java.util.concurrent.ConcurrentLinkedQueue; |
|||
import java.util.concurrent.ConcurrentMap; |
|||
import java.util.concurrent.Executors; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractPartitionBasedService<T extends EntityId> extends TbApplicationEventListener<PartitionChangeEvent> { |
|||
|
|||
protected final ConcurrentMap<TopicPartitionInfo, Set<T>> partitionedEntities = new ConcurrentHashMap<>(); |
|||
final Queue<Set<TopicPartitionInfo>> subscribeQueue = new ConcurrentLinkedQueue<>(); |
|||
|
|||
protected ListeningScheduledExecutorService scheduledExecutor; |
|||
|
|||
abstract protected String getServiceName(); |
|||
|
|||
abstract protected String getSchedulerExecutorName(); |
|||
|
|||
abstract protected void onAddedPartitions(Set<TopicPartitionInfo> addedPartitions); |
|||
|
|||
abstract protected void cleanupEntityOnPartitionRemoval(T entityId); |
|||
|
|||
public Set<T> getPartitionedEntities(TopicPartitionInfo tpi) { |
|||
return partitionedEntities.get(tpi); |
|||
} |
|||
|
|||
protected void init() { |
|||
// Should be always single threaded due to absence of locks.
|
|||
scheduledExecutor = MoreExecutors.listeningDecorator(Executors.newSingleThreadScheduledExecutor(ThingsBoardThreadFactory.forName(getSchedulerExecutorName()))); |
|||
} |
|||
|
|||
protected ServiceType getServiceType() { |
|||
return ServiceType.TB_CORE; |
|||
} |
|||
|
|||
protected void stop() { |
|||
if (scheduledExecutor != null) { |
|||
scheduledExecutor.shutdownNow(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* DiscoveryService will call this event from the single thread (one-by-one). |
|||
* Events order is guaranteed by DiscoveryService. |
|||
* The only concurrency is expected from the [main] thread on Application started. |
|||
* Async implementation. Locks is not allowed by design. |
|||
* Any locks or delays in this module will affect DiscoveryService and entire system |
|||
*/ |
|||
@Override |
|||
protected void onTbApplicationEvent(PartitionChangeEvent partitionChangeEvent) { |
|||
if (getServiceType().equals(partitionChangeEvent.getServiceType())) { |
|||
log.debug("onTbApplicationEvent, processing event: {}", partitionChangeEvent); |
|||
subscribeQueue.add(partitionChangeEvent.getPartitions()); |
|||
scheduledExecutor.submit(this::pollInitStateFromDB); |
|||
} |
|||
} |
|||
|
|||
protected void pollInitStateFromDB() { |
|||
final Set<TopicPartitionInfo> partitions = getLatestPartitions(); |
|||
if (partitions == null) { |
|||
log.debug("Nothing to do. Partitions are empty."); |
|||
return; |
|||
} |
|||
initStateFromDB(partitions); |
|||
} |
|||
|
|||
private void initStateFromDB(Set<TopicPartitionInfo> partitions) { |
|||
try { |
|||
log.info("[{}] CURRENT PARTITIONS: {}", getServiceName(), partitionedEntities.keySet()); |
|||
log.info("[{}] NEW PARTITIONS: {}", getServiceName(), partitions); |
|||
|
|||
Set<TopicPartitionInfo> addedPartitions = new HashSet<>(partitions); |
|||
addedPartitions.removeAll(partitionedEntities.keySet()); |
|||
|
|||
log.info("[{}] ADDED PARTITIONS: {}", getServiceName(), addedPartitions); |
|||
|
|||
Set<TopicPartitionInfo> removedPartitions = new HashSet<>(partitionedEntities.keySet()); |
|||
removedPartitions.removeAll(partitions); |
|||
|
|||
log.info("[{}] REMOVED PARTITIONS: {}", getServiceName(), removedPartitions); |
|||
|
|||
// We no longer manage current partition of entities;
|
|||
removedPartitions.forEach(partition -> { |
|||
Set<T> entities = partitionedEntities.remove(partition); |
|||
entities.forEach(this::cleanupEntityOnPartitionRemoval); |
|||
}); |
|||
|
|||
onRepartitionEvent(); |
|||
|
|||
addedPartitions.forEach(tpi -> partitionedEntities.computeIfAbsent(tpi, key -> ConcurrentHashMap.newKeySet())); |
|||
|
|||
if (!addedPartitions.isEmpty()) { |
|||
onAddedPartitions(addedPartitions); |
|||
} |
|||
|
|||
log.info("[{}] Managing following partitions:", getServiceName()); |
|||
partitionedEntities.forEach((tpi, entities) -> { |
|||
log.info("[{}][{}]: {} entities", getServiceName(), tpi.getFullTopicName(), entities.size()); |
|||
}); |
|||
} catch (Throwable t) { |
|||
log.warn("[{}] Failed to init entities state from DB", getServiceName(), t); |
|||
} |
|||
} |
|||
|
|||
protected void onRepartitionEvent() { |
|||
} |
|||
|
|||
private Set<TopicPartitionInfo> getLatestPartitions() { |
|||
log.debug("getLatestPartitionsFromQueue, queue size {}", subscribeQueue.size()); |
|||
Set<TopicPartitionInfo> partitions = null; |
|||
while (!subscribeQueue.isEmpty()) { |
|||
partitions = subscribeQueue.poll(); |
|||
log.debug("polled from the queue partitions {}", partitions); |
|||
} |
|||
log.debug("getLatestPartitionsFromQueue, partitions {}", partitions); |
|||
return partitions; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,186 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.sms.smpp; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.apache.commons.lang3.exception.ExceptionUtils; |
|||
import org.smpp.Connection; |
|||
import org.smpp.Data; |
|||
import org.smpp.Session; |
|||
import org.smpp.TCPIPConnection; |
|||
import org.smpp.TimeoutException; |
|||
import org.smpp.WrongSessionStateException; |
|||
import org.smpp.pdu.Address; |
|||
import org.smpp.pdu.BindReceiver; |
|||
import org.smpp.pdu.BindRequest; |
|||
import org.smpp.pdu.BindResponse; |
|||
import org.smpp.pdu.BindTransciever; |
|||
import org.smpp.pdu.BindTransmitter; |
|||
import org.smpp.pdu.PDUException; |
|||
import org.smpp.pdu.SubmitSM; |
|||
import org.smpp.pdu.SubmitSMResp; |
|||
import org.thingsboard.rule.engine.api.sms.exception.SmsException; |
|||
import org.thingsboard.server.common.data.sms.config.SmppSmsProviderConfiguration; |
|||
import org.thingsboard.server.service.sms.AbstractSmsSender; |
|||
|
|||
import java.io.IOException; |
|||
import java.util.Optional; |
|||
|
|||
@Slf4j |
|||
public class SmppSmsSender extends AbstractSmsSender { |
|||
protected SmppSmsProviderConfiguration config; |
|||
|
|||
protected Session smppSession; |
|||
|
|||
public SmppSmsSender(SmppSmsProviderConfiguration config) { |
|||
if (config.getBindType() == null) { |
|||
config.setBindType(SmppSmsProviderConfiguration.SmppBindType.TX); |
|||
} |
|||
if (StringUtils.isNotEmpty(config.getSourceAddress())) { |
|||
if (config.getSourceTon() == null) { |
|||
config.setSourceTon((byte) 5); |
|||
} |
|||
if (config.getSourceNpi() == null) { |
|||
config.setSourceNpi((byte) 0); |
|||
} |
|||
} |
|||
if (config.getDestinationTon() == null) { |
|||
config.setDestinationTon((byte) 5); |
|||
} |
|||
if (config.getDestinationNpi() == null) { |
|||
config.setDestinationNpi((byte) 0); |
|||
} |
|||
|
|||
this.config = config; |
|||
this.smppSession = initSmppSession(); |
|||
} |
|||
|
|||
private SmppSmsSender() {} // for testing purposes
|
|||
|
|||
|
|||
@Override |
|||
public int sendSms(String numberTo, String message) throws SmsException { |
|||
try { |
|||
checkSmppSession(); |
|||
|
|||
SubmitSM request = new SubmitSM(); |
|||
if (StringUtils.isNotEmpty(config.getServiceType())) { |
|||
request.setServiceType(config.getServiceType()); |
|||
} |
|||
if (StringUtils.isNotEmpty(config.getSourceAddress())) { |
|||
request.setSourceAddr(new Address(config.getSourceTon(), config.getSourceNpi(), config.getSourceAddress())); |
|||
} |
|||
request.setDestAddr(new Address(config.getDestinationTon(), config.getDestinationNpi(), prepareNumber(numberTo))); |
|||
request.setShortMessage(message); |
|||
request.setDataCoding(Optional.ofNullable(config.getCodingScheme()).orElse((byte) 0)); |
|||
request.setReplaceIfPresentFlag((byte) 0); |
|||
request.setEsmClass((byte) 0); |
|||
request.setProtocolId((byte) 0); |
|||
request.setPriorityFlag((byte) 0); |
|||
request.setRegisteredDelivery((byte) 0); |
|||
request.setSmDefaultMsgId((byte) 0); |
|||
|
|||
SubmitSMResp response = smppSession.submit(request); |
|||
|
|||
log.debug("SMPP submit command status: {}", response.getCommandStatus()); |
|||
} catch (Exception e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
|
|||
return countMessageSegments(message); |
|||
} |
|||
|
|||
private synchronized void checkSmppSession() { |
|||
if (smppSession == null || !smppSession.isOpened()) { |
|||
smppSession = initSmppSession(); |
|||
} |
|||
} |
|||
|
|||
protected Session initSmppSession() { |
|||
try { |
|||
Connection connection = new TCPIPConnection(config.getHost(), config.getPort()); |
|||
Session session = new Session(connection); |
|||
|
|||
BindRequest bindRequest; |
|||
switch (config.getBindType()) { |
|||
case TX: |
|||
bindRequest = new BindTransmitter(); |
|||
break; |
|||
case RX: |
|||
bindRequest = new BindReceiver(); |
|||
break; |
|||
case TRX: |
|||
bindRequest = new BindTransciever(); |
|||
break; |
|||
default: |
|||
throw new UnsupportedOperationException("Unsupported bind type " + config.getBindType()); |
|||
} |
|||
|
|||
bindRequest.setSystemId(config.getSystemId()); |
|||
bindRequest.setPassword(config.getPassword()); |
|||
|
|||
byte interfaceVersion; |
|||
switch (config.getProtocolVersion()) { |
|||
case "3.3": |
|||
interfaceVersion = Data.SMPP_V33; |
|||
break; |
|||
case "3.4": |
|||
interfaceVersion = Data.SMPP_V34; |
|||
break; |
|||
default: |
|||
throw new UnsupportedOperationException("Unsupported SMPP version: " + config.getProtocolVersion()); |
|||
} |
|||
bindRequest.setInterfaceVersion(interfaceVersion); |
|||
|
|||
if (StringUtils.isNotEmpty(config.getSystemType())) { |
|||
bindRequest.setSystemType(config.getSystemType()); |
|||
} |
|||
if (StringUtils.isNotEmpty(config.getAddressRange())) { |
|||
bindRequest.setAddressRange(config.getDestinationTon(), config.getDestinationNpi(), config.getAddressRange()); |
|||
} |
|||
|
|||
BindResponse bindResponse = session.bind(bindRequest); |
|||
log.debug("SMPP bind response: {}", bindResponse.debugString()); |
|||
|
|||
if (bindResponse.getCommandStatus() != 0) { |
|||
throw new IllegalStateException("Error status when binding: " + bindResponse.getCommandStatus()); |
|||
} |
|||
|
|||
return session; |
|||
} catch (Exception e) { |
|||
throw new IllegalArgumentException("Failed to establish SMPP session: " + ExceptionUtils.getRootCauseMessage(e), e); |
|||
} |
|||
} |
|||
|
|||
private String prepareNumber(String number) { |
|||
if (config.getDestinationTon() == Data.GSM_TON_INTERNATIONAL) { |
|||
return StringUtils.removeStart(number, "+"); |
|||
} |
|||
return number; |
|||
} |
|||
|
|||
@Override |
|||
public void destroy() { |
|||
try { |
|||
smppSession.unbind(); |
|||
smppSession.close(); |
|||
} catch (TimeoutException | PDUException | IOException | WrongSessionStateException e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -1,54 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.controller; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.junit.Assert; |
|||
import org.junit.runner.RunWith; |
|||
import org.springframework.boot.test.context.SpringBootContextLoader; |
|||
import org.springframework.boot.test.context.SpringBootTest; |
|||
import org.springframework.boot.web.server.LocalServerPort; |
|||
import org.springframework.context.annotation.ComponentScan; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.test.annotation.DirtiesContext; |
|||
import org.springframework.test.context.ActiveProfiles; |
|||
import org.springframework.test.context.ContextConfiguration; |
|||
import org.springframework.test.context.junit4.SpringRunner; |
|||
import java.net.URI; |
|||
import java.net.URISyntaxException; |
|||
|
|||
@ActiveProfiles("test") |
|||
@RunWith(SpringRunner.class) |
|||
@ContextConfiguration(classes = AbstractControllerTest.class, loader = SpringBootContextLoader.class) |
|||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) |
|||
@Configuration |
|||
@ComponentScan({"org.thingsboard.server"}) |
|||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) |
|||
@Slf4j |
|||
public abstract class AbstractWebsocketTest extends AbstractWebTest { |
|||
|
|||
protected static final String WS_URL = "ws://localhost:"; |
|||
|
|||
@LocalServerPort |
|||
protected int wsPort; |
|||
|
|||
protected TbTestWebSocketClient buildAndConnectWebSocketClient() throws URISyntaxException, InterruptedException { |
|||
TbTestWebSocketClient wsClient = new TbTestWebSocketClient(new URI(WS_URL + wsPort + "/api/ws/plugins/telemetry?token=" + token)); |
|||
Assert.assertTrue(wsClient.connectBlocking()); |
|||
return wsClient; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,230 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.controller; |
|||
|
|||
import org.junit.After; |
|||
import org.junit.Assert; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.alarm.Alarm; |
|||
import org.thingsboard.server.common.data.alarm.AlarmSeverity; |
|||
import org.thingsboard.server.common.data.alarm.AlarmStatus; |
|||
|
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
|
|||
public abstract class BaseAlarmControllerTest extends AbstractControllerTest { |
|||
|
|||
public static final String TEST_ALARM_TYPE = "Test"; |
|||
|
|||
protected Device customerDevice; |
|||
|
|||
@Before |
|||
public void setup() throws Exception { |
|||
loginTenantAdmin(); |
|||
|
|||
Device device = new Device(); |
|||
device.setTenantId(tenantId); |
|||
device.setName("Test device"); |
|||
device.setLabel("Label"); |
|||
device.setType("Type"); |
|||
device.setCustomerId(customerId); |
|||
customerDevice = doPost("/api/device", device, Device.class); |
|||
|
|||
logout(); |
|||
} |
|||
|
|||
@After |
|||
public void teardown() throws Exception { |
|||
loginSysAdmin(); |
|||
deleteDifferentTenant(); |
|||
} |
|||
|
|||
@Test |
|||
public void testCreateAlarmViaCustomer() throws Exception { |
|||
loginCustomerUser(); |
|||
createAlarm(TEST_ALARM_TYPE); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testCreateAlarmViaTenant() throws Exception { |
|||
loginTenantAdmin(); |
|||
createAlarm(TEST_ALARM_TYPE); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testUpdateAlarmViaCustomer() throws Exception { |
|||
loginCustomerUser(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
alarm.setSeverity(AlarmSeverity.MAJOR); |
|||
Alarm updatedAlarm = doPost("/api/alarm", alarm, Alarm.class); |
|||
Assert.assertNotNull(updatedAlarm); |
|||
Assert.assertEquals(AlarmSeverity.MAJOR, updatedAlarm.getSeverity()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testUpdateAlarmViaTenant() throws Exception { |
|||
loginTenantAdmin(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
alarm.setSeverity(AlarmSeverity.MAJOR); |
|||
Alarm updatedAlarm = doPost("/api/alarm", alarm, Alarm.class); |
|||
Assert.assertNotNull(updatedAlarm); |
|||
Assert.assertEquals(AlarmSeverity.MAJOR, updatedAlarm.getSeverity()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testUpdateAlarmViaDifferentTenant() throws Exception { |
|||
loginTenantAdmin(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
alarm.setSeverity(AlarmSeverity.MAJOR); |
|||
loginDifferentTenant(); |
|||
doPost("/api/alarm", alarm).andExpect(status().isForbidden()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testUpdateAlarmViaDifferentCustomer() throws Exception { |
|||
loginCustomerUser(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
loginDifferentCustomer(); |
|||
alarm.setSeverity(AlarmSeverity.MAJOR); |
|||
doPost("/api/alarm", alarm).andExpect(status().isForbidden()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testDeleteAlarmViaCustomer() throws Exception { |
|||
loginCustomerUser(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
doDelete("/api/alarm/" + alarm.getId()).andExpect(status().isOk()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testDeleteAlarmViaTenant() throws Exception { |
|||
loginTenantAdmin(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
doDelete("/api/alarm/" + alarm.getId()).andExpect(status().isOk()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testDeleteAlarmViaDifferentTenant() throws Exception { |
|||
loginTenantAdmin(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
loginDifferentTenant(); |
|||
doDelete("/api/alarm/" + alarm.getId()).andExpect(status().isForbidden()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testDeleteAlarmViaAnotherCustomer() throws Exception { |
|||
loginCustomerUser(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
loginDifferentCustomer(); |
|||
doDelete("/api/alarm/" + alarm.getId()).andExpect(status().isForbidden()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testClearAlarmViaCustomer() throws Exception { |
|||
loginCustomerUser(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
doPost("/api/alarm/" + alarm.getId() + "/clear").andExpect(status().isOk()); |
|||
Alarm foundAlarm = doGet("/api/alarm/" + alarm.getId(), Alarm.class); |
|||
Assert.assertNotNull(foundAlarm); |
|||
Assert.assertEquals(AlarmStatus.CLEARED_UNACK, foundAlarm.getStatus()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testClearAlarmViaTenant() throws Exception { |
|||
loginTenantAdmin(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
doPost("/api/alarm/" + alarm.getId() + "/clear").andExpect(status().isOk()); |
|||
Alarm foundAlarm = doGet("/api/alarm/" + alarm.getId(), Alarm.class); |
|||
Assert.assertNotNull(foundAlarm); |
|||
Assert.assertEquals(AlarmStatus.CLEARED_UNACK, foundAlarm.getStatus()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testAcknowledgeAlarmViaCustomer() throws Exception { |
|||
loginCustomerUser(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
doPost("/api/alarm/" + alarm.getId() + "/ack").andExpect(status().isOk()); |
|||
Alarm foundAlarm = doGet("/api/alarm/" + alarm.getId(), Alarm.class); |
|||
Assert.assertNotNull(foundAlarm); |
|||
Assert.assertEquals(AlarmStatus.ACTIVE_ACK, foundAlarm.getStatus()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testClearAlarmViaDifferentCustomer() throws Exception { |
|||
loginCustomerUser(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
loginDifferentCustomer(); |
|||
doPost("/api/alarm/" + alarm.getId() + "/clear").andExpect(status().isForbidden()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testClearAlarmViaDifferentTenant() throws Exception { |
|||
loginTenantAdmin(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
loginDifferentTenant(); |
|||
doPost("/api/alarm/" + alarm.getId() + "/clear").andExpect(status().isForbidden()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testAcknowledgeAlarmViaDifferentCustomer() throws Exception { |
|||
loginCustomerUser(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
loginDifferentCustomer(); |
|||
doPost("/api/alarm/" + alarm.getId() + "/ack").andExpect(status().isForbidden()); |
|||
logout(); |
|||
} |
|||
|
|||
@Test |
|||
public void testAcknowledgeAlarmViaDifferentTenant() throws Exception { |
|||
loginTenantAdmin(); |
|||
Alarm alarm = createAlarm(TEST_ALARM_TYPE); |
|||
loginDifferentTenant(); |
|||
doPost("/api/alarm/" + alarm.getId() + "/ack").andExpect(status().isForbidden()); |
|||
logout(); |
|||
} |
|||
|
|||
private Alarm createAlarm(String type) throws Exception { |
|||
Alarm alarm = Alarm.builder() |
|||
.tenantId(tenantId) |
|||
.customerId(customerId) |
|||
.originator(customerDevice.getId()) |
|||
.status(AlarmStatus.ACTIVE_UNACK) |
|||
.severity(AlarmSeverity.CRITICAL) |
|||
.type(type) |
|||
.build(); |
|||
|
|||
alarm = doPost("/api/alarm", alarm, Alarm.class); |
|||
Assert.assertNotNull(alarm); |
|||
|
|||
return alarm; |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue