Browse Source
# Conflicts: # application/src/main/java/org/thingsboard/server/controller/AdminController.java # application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java # application/src/main/java/org/thingsboard/server/service/security/model/token/JwtTokenFactory.javapull/7297/head
1075 changed files with 36973 additions and 8393 deletions
@ -0,0 +1,234 @@ |
|||||
|
-- |
||||
|
-- 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. |
||||
|
-- |
||||
|
|
||||
|
CREATE TABLE IF NOT EXISTS rule_node_debug_event ( |
||||
|
id uuid NOT NULL, |
||||
|
tenant_id uuid NOT NULL , |
||||
|
ts bigint NOT NULL, |
||||
|
entity_id uuid NOT NULL, |
||||
|
service_id varchar, |
||||
|
e_type varchar, |
||||
|
e_entity_id uuid, |
||||
|
e_entity_type varchar, |
||||
|
e_msg_id uuid, |
||||
|
e_msg_type varchar, |
||||
|
e_data_type varchar, |
||||
|
e_relation_type varchar, |
||||
|
e_data varchar, |
||||
|
e_metadata varchar, |
||||
|
e_error varchar |
||||
|
) PARTITION BY RANGE (ts); |
||||
|
|
||||
|
CREATE TABLE IF NOT EXISTS rule_chain_debug_event ( |
||||
|
id uuid NOT NULL, |
||||
|
tenant_id uuid NOT NULL, |
||||
|
ts bigint NOT NULL, |
||||
|
entity_id uuid NOT NULL, |
||||
|
service_id varchar NOT NULL, |
||||
|
e_message varchar, |
||||
|
e_error varchar |
||||
|
) PARTITION BY RANGE (ts); |
||||
|
|
||||
|
CREATE TABLE IF NOT EXISTS stats_event ( |
||||
|
id uuid NOT NULL, |
||||
|
tenant_id uuid NOT NULL, |
||||
|
ts bigint NOT NULL, |
||||
|
entity_id uuid NOT NULL, |
||||
|
service_id varchar NOT NULL, |
||||
|
e_messages_processed bigint NOT NULL, |
||||
|
e_errors_occurred bigint NOT NULL |
||||
|
) PARTITION BY RANGE (ts); |
||||
|
|
||||
|
CREATE TABLE IF NOT EXISTS lc_event ( |
||||
|
id uuid NOT NULL, |
||||
|
tenant_id uuid NOT NULL, |
||||
|
ts bigint NOT NULL, |
||||
|
entity_id uuid NOT NULL, |
||||
|
service_id varchar NOT NULL, |
||||
|
e_type varchar NOT NULL, |
||||
|
e_success boolean NOT NULL, |
||||
|
e_error varchar |
||||
|
) PARTITION BY RANGE (ts); |
||||
|
|
||||
|
CREATE TABLE IF NOT EXISTS error_event ( |
||||
|
id uuid NOT NULL, |
||||
|
tenant_id uuid NOT NULL, |
||||
|
ts bigint NOT NULL, |
||||
|
entity_id uuid NOT NULL, |
||||
|
service_id varchar NOT NULL, |
||||
|
e_method varchar NOT NULL, |
||||
|
e_error varchar |
||||
|
) PARTITION BY RANGE (ts); |
||||
|
|
||||
|
CREATE INDEX IF NOT EXISTS idx_rule_node_debug_event_main |
||||
|
ON rule_node_debug_event (tenant_id ASC, entity_id ASC, ts DESC NULLS LAST) WITH (FILLFACTOR=95); |
||||
|
|
||||
|
CREATE INDEX IF NOT EXISTS idx_rule_chain_debug_event_main |
||||
|
ON rule_chain_debug_event (tenant_id ASC, entity_id ASC, ts DESC NULLS LAST) WITH (FILLFACTOR=95); |
||||
|
|
||||
|
CREATE INDEX IF NOT EXISTS idx_stats_event_main |
||||
|
ON stats_event (tenant_id ASC, entity_id ASC, ts DESC NULLS LAST) WITH (FILLFACTOR=95); |
||||
|
|
||||
|
CREATE INDEX IF NOT EXISTS idx_lc_event_main |
||||
|
ON lc_event (tenant_id ASC, entity_id ASC, ts DESC NULLS LAST) WITH (FILLFACTOR=95); |
||||
|
|
||||
|
CREATE INDEX IF NOT EXISTS idx_error_event_main |
||||
|
ON error_event (tenant_id ASC, entity_id ASC, ts DESC NULLS LAST) WITH (FILLFACTOR=95); |
||||
|
|
||||
|
CREATE OR REPLACE FUNCTION to_safe_json(p_json text) RETURNS json |
||||
|
LANGUAGE plpgsql AS |
||||
|
$$ |
||||
|
BEGIN |
||||
|
return REPLACE(p_json, '\u0000', '' )::json; |
||||
|
EXCEPTION |
||||
|
WHEN OTHERS THEN |
||||
|
return '{}'::json; |
||||
|
END; |
||||
|
$$; |
||||
|
|
||||
|
-- Useful to migrate old events to the new table structure; |
||||
|
CREATE OR REPLACE PROCEDURE migrate_regular_events(IN start_ts_in_ms bigint, IN end_ts_in_ms bigint, IN partition_size_in_hours int) |
||||
|
LANGUAGE plpgsql AS |
||||
|
$$ |
||||
|
DECLARE |
||||
|
partition_size_in_ms bigint; |
||||
|
p record; |
||||
|
table_name varchar; |
||||
|
BEGIN |
||||
|
partition_size_in_ms = partition_size_in_hours * 3600 * 1000; |
||||
|
|
||||
|
FOR p IN SELECT DISTINCT event_type as event_type, (created_time - created_time % partition_size_in_ms) as partition_ts FROM event e WHERE e.event_type in ('STATS', 'LC_EVENT', 'ERROR') and ts >= start_ts_in_ms and ts < end_ts_in_ms |
||||
|
LOOP |
||||
|
IF p.event_type = 'STATS' THEN |
||||
|
table_name := 'stats_event'; |
||||
|
ELSEIF p.event_type = 'LC_EVENT' THEN |
||||
|
table_name := 'lc_event'; |
||||
|
ELSEIF p.event_type = 'ERROR' THEN |
||||
|
table_name := 'error_event'; |
||||
|
END IF; |
||||
|
RAISE NOTICE '[%] Partition to create : [%-%]', table_name, p.partition_ts, (p.partition_ts + partition_size_in_ms); |
||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS %s_%s PARTITION OF %s FOR VALUES FROM ( %s ) TO ( %s )', table_name, p.partition_ts, table_name, p.partition_ts, (p.partition_ts + partition_size_in_ms)); |
||||
|
END LOOP; |
||||
|
|
||||
|
INSERT INTO stats_event |
||||
|
SELECT id, |
||||
|
tenant_id, |
||||
|
ts, |
||||
|
entity_id, |
||||
|
body ->> 'server', |
||||
|
(body ->> 'messagesProcessed')::bigint, |
||||
|
(body ->> 'errorsOccurred')::bigint |
||||
|
FROM |
||||
|
(select id, tenant_id, ts, entity_id, to_safe_json(body) as body |
||||
|
FROM event WHERE ts >= start_ts_in_ms and ts < end_ts_in_ms AND event_type = 'STATS' AND to_safe_json(body) ->> 'server' IS NOT NULL |
||||
|
) safe_event |
||||
|
ON CONFLICT DO NOTHING; |
||||
|
|
||||
|
INSERT INTO lc_event |
||||
|
SELECT id, |
||||
|
tenant_id, |
||||
|
ts, |
||||
|
entity_id, |
||||
|
body ->> 'server', |
||||
|
body ->> 'event', |
||||
|
(body ->> 'success')::boolean, |
||||
|
body ->> 'error' |
||||
|
FROM |
||||
|
(select id, tenant_id, ts, entity_id, to_safe_json(body) as body |
||||
|
FROM event WHERE ts >= start_ts_in_ms and ts < end_ts_in_ms AND event_type = 'LC_EVENT' AND to_safe_json(body) ->> 'server' IS NOT NULL |
||||
|
) safe_event |
||||
|
ON CONFLICT DO NOTHING; |
||||
|
|
||||
|
INSERT INTO error_event |
||||
|
SELECT id, |
||||
|
tenant_id, |
||||
|
ts, |
||||
|
entity_id, |
||||
|
body ->> 'server', |
||||
|
body ->> 'method', |
||||
|
body ->> 'error' |
||||
|
FROM |
||||
|
(select id, tenant_id, ts, entity_id, to_safe_json(body) as body |
||||
|
FROM event WHERE ts >= start_ts_in_ms and ts < end_ts_in_ms AND event_type = 'ERROR' AND to_safe_json(body) ->> 'server' IS NOT NULL |
||||
|
) safe_event |
||||
|
ON CONFLICT DO NOTHING; |
||||
|
|
||||
|
END |
||||
|
$$; |
||||
|
|
||||
|
-- Useful to migrate old debug events to the new table structure; |
||||
|
CREATE OR REPLACE PROCEDURE migrate_debug_events(IN start_ts_in_ms bigint, IN end_ts_in_ms bigint, IN partition_size_in_hours int) |
||||
|
LANGUAGE plpgsql AS |
||||
|
$$ |
||||
|
DECLARE |
||||
|
partition_size_in_ms bigint; |
||||
|
p record; |
||||
|
table_name varchar; |
||||
|
BEGIN |
||||
|
partition_size_in_ms = partition_size_in_hours * 3600 * 1000; |
||||
|
|
||||
|
FOR p IN SELECT DISTINCT event_type as event_type, (created_time - created_time % partition_size_in_ms) as partition_ts FROM event e WHERE e.event_type in ('DEBUG_RULE_NODE', 'DEBUG_RULE_CHAIN') and ts >= start_ts_in_ms and ts < end_ts_in_ms |
||||
|
LOOP |
||||
|
IF p.event_type = 'DEBUG_RULE_NODE' THEN |
||||
|
table_name := 'rule_node_debug_event'; |
||||
|
ELSEIF p.event_type = 'DEBUG_RULE_CHAIN' THEN |
||||
|
table_name := 'rule_chain_debug_event'; |
||||
|
END IF; |
||||
|
RAISE NOTICE '[%] Partition to create : [%-%]', table_name, p.partition_ts, (p.partition_ts + partition_size_in_ms); |
||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS %s_%s PARTITION OF %s FOR VALUES FROM ( %s ) TO ( %s )', table_name, p.partition_ts, table_name, p.partition_ts, (p.partition_ts + partition_size_in_ms)); |
||||
|
END LOOP; |
||||
|
|
||||
|
INSERT INTO rule_node_debug_event |
||||
|
SELECT id, |
||||
|
tenant_id, |
||||
|
ts, |
||||
|
entity_id, |
||||
|
body ->> 'server', |
||||
|
body ->> 'type', |
||||
|
(body ->> 'entityId')::uuid, |
||||
|
body ->> 'entityName', |
||||
|
(body ->> 'msgId')::uuid, |
||||
|
body ->> 'msgType', |
||||
|
body ->> 'dataType', |
||||
|
body ->> 'relationType', |
||||
|
body ->> 'data', |
||||
|
body ->> 'metadata', |
||||
|
body ->> 'error' |
||||
|
FROM |
||||
|
(select id, tenant_id, ts, entity_id, to_safe_json(body) as body |
||||
|
FROM event WHERE ts >= start_ts_in_ms and ts < end_ts_in_ms AND event_type = 'DEBUG_RULE_NODE' AND to_safe_json(body) ->> 'server' IS NOT NULL |
||||
|
) safe_event |
||||
|
ON CONFLICT DO NOTHING; |
||||
|
|
||||
|
INSERT INTO rule_chain_debug_event |
||||
|
SELECT id, |
||||
|
tenant_id, |
||||
|
ts, |
||||
|
entity_id, |
||||
|
body ->> 'server', |
||||
|
body ->> 'message', |
||||
|
body ->> 'error' |
||||
|
FROM |
||||
|
(select id, tenant_id, ts, entity_id, to_safe_json(body) as body |
||||
|
FROM event WHERE ts >= start_ts_in_ms and ts < end_ts_in_ms AND event_type = 'DEBUG_RULE_CHAIN' AND to_safe_json(body) ->> 'server' IS NOT NULL |
||||
|
) safe_event |
||||
|
ON CONFLICT DO NOTHING; |
||||
|
END |
||||
|
$$; |
||||
|
|
||||
|
UPDATE tb_user |
||||
|
SET additional_info = REPLACE(additional_info, '"lang":"ja_JA"', '"lang":"ja_JP"') |
||||
|
WHERE additional_info LIKE '%"lang":"ja_JA"%'; |
||||
@ -0,0 +1,74 @@ |
|||||
|
-- |
||||
|
-- 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. |
||||
|
-- |
||||
|
|
||||
|
DO |
||||
|
$$ |
||||
|
DECLARE table_partition RECORD; |
||||
|
BEGIN |
||||
|
-- in case of running the upgrade script a second time: |
||||
|
IF NOT (SELECT exists(SELECT FROM pg_tables WHERE tablename = 'old_audit_log')) THEN |
||||
|
ALTER TABLE audit_log RENAME TO old_audit_log; |
||||
|
ALTER INDEX IF EXISTS idx_audit_log_tenant_id_and_created_time RENAME TO idx_old_audit_log_tenant_id_and_created_time; |
||||
|
|
||||
|
FOR table_partition IN SELECT tablename AS name, split_part(tablename, '_', 3) AS partition_ts |
||||
|
FROM pg_tables WHERE tablename LIKE 'audit_log_%' |
||||
|
LOOP |
||||
|
EXECUTE format('ALTER TABLE %s RENAME TO old_audit_log_%s', table_partition.name, table_partition.partition_ts); |
||||
|
END LOOP; |
||||
|
ELSE |
||||
|
RAISE NOTICE 'Table old_audit_log already exists, leaving as is'; |
||||
|
END IF; |
||||
|
END; |
||||
|
$$; |
||||
|
|
||||
|
CREATE TABLE IF NOT EXISTS audit_log ( |
||||
|
id uuid NOT NULL, |
||||
|
created_time bigint NOT NULL, |
||||
|
tenant_id uuid, |
||||
|
customer_id uuid, |
||||
|
entity_id uuid, |
||||
|
entity_type varchar(255), |
||||
|
entity_name varchar(255), |
||||
|
user_id uuid, |
||||
|
user_name varchar(255), |
||||
|
action_type varchar(255), |
||||
|
action_data varchar(1000000), |
||||
|
action_status varchar(255), |
||||
|
action_failure_details varchar(1000000) |
||||
|
) PARTITION BY RANGE (created_time); |
||||
|
CREATE INDEX IF NOT EXISTS idx_audit_log_tenant_id_and_created_time ON audit_log(tenant_id, created_time DESC); |
||||
|
|
||||
|
CREATE OR REPLACE PROCEDURE migrate_audit_logs(IN start_time_ms BIGINT, IN end_time_ms BIGINT, IN partition_size_ms BIGINT) |
||||
|
LANGUAGE plpgsql AS |
||||
|
$$ |
||||
|
DECLARE |
||||
|
p RECORD; |
||||
|
partition_end_ts BIGINT; |
||||
|
BEGIN |
||||
|
FOR p IN SELECT DISTINCT (created_time - created_time % partition_size_ms) AS partition_ts FROM old_audit_log |
||||
|
WHERE created_time >= start_time_ms AND created_time < end_time_ms |
||||
|
LOOP |
||||
|
partition_end_ts = p.partition_ts + partition_size_ms; |
||||
|
RAISE NOTICE '[audit_log] Partition to create : [%-%]', p.partition_ts, partition_end_ts; |
||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS audit_log_%s PARTITION OF audit_log ' || |
||||
|
'FOR VALUES FROM ( %s ) TO ( %s )', p.partition_ts, p.partition_ts, partition_end_ts); |
||||
|
END LOOP; |
||||
|
|
||||
|
INSERT INTO audit_log |
||||
|
SELECT * FROM old_audit_log |
||||
|
WHERE created_time >= start_time_ms AND created_time < end_time_ms; |
||||
|
END; |
||||
|
$$; |
||||
@ -0,0 +1,21 @@ |
|||||
|
-- |
||||
|
-- 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 update_asset_profiles; |
||||
|
|
||||
|
ALTER TABLE asset ALTER COLUMN asset_profile_id SET NOT NULL; |
||||
|
ALTER TABLE asset DROP CONSTRAINT IF EXISTS fk_asset_profile; |
||||
|
ALTER TABLE asset ADD CONSTRAINT fk_asset_profile FOREIGN KEY (asset_profile_id) REFERENCES asset_profile(id); |
||||
@ -0,0 +1,45 @@ |
|||||
|
-- |
||||
|
-- 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. |
||||
|
-- |
||||
|
|
||||
|
CREATE TABLE IF NOT EXISTS asset_profile ( |
||||
|
id uuid NOT NULL CONSTRAINT asset_profile_pkey PRIMARY KEY, |
||||
|
created_time bigint NOT NULL, |
||||
|
name varchar(255), |
||||
|
image varchar(1000000), |
||||
|
description varchar, |
||||
|
search_text varchar(255), |
||||
|
is_default boolean, |
||||
|
tenant_id uuid, |
||||
|
default_rule_chain_id uuid, |
||||
|
default_dashboard_id uuid, |
||||
|
default_queue_name varchar(255), |
||||
|
external_id uuid, |
||||
|
CONSTRAINT asset_profile_name_unq_key UNIQUE (tenant_id, name), |
||||
|
CONSTRAINT asset_profile_external_id_unq_key UNIQUE (tenant_id, external_id), |
||||
|
CONSTRAINT fk_default_rule_chain_asset_profile FOREIGN KEY (default_rule_chain_id) REFERENCES rule_chain(id), |
||||
|
CONSTRAINT fk_default_dashboard_asset_profile FOREIGN KEY (default_dashboard_id) REFERENCES dashboard(id) |
||||
|
); |
||||
|
|
||||
|
CREATE OR REPLACE PROCEDURE update_asset_profiles() |
||||
|
LANGUAGE plpgsql AS |
||||
|
$$ |
||||
|
BEGIN |
||||
|
UPDATE asset as a SET asset_profile_id = p.id |
||||
|
FROM |
||||
|
(SELECT id, tenant_id, name from asset_profile) as p |
||||
|
WHERE a.asset_profile_id IS NULL AND p.tenant_id = a.tenant_id AND a.type = p.name; |
||||
|
END; |
||||
|
$$; |
||||
@ -0,0 +1,227 @@ |
|||||
|
/** |
||||
|
* 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 io.swagger.annotations.ApiOperation; |
||||
|
import io.swagger.annotations.ApiParam; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.http.HttpStatus; |
||||
|
import org.springframework.security.access.prepost.PreAuthorize; |
||||
|
import org.springframework.web.bind.annotation.PathVariable; |
||||
|
import org.springframework.web.bind.annotation.RequestBody; |
||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestMethod; |
||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||
|
import org.springframework.web.bind.annotation.ResponseBody; |
||||
|
import org.springframework.web.bind.annotation.ResponseStatus; |
||||
|
import org.springframework.web.bind.annotation.RestController; |
||||
|
import org.thingsboard.server.common.data.asset.AssetProfile; |
||||
|
import org.thingsboard.server.common.data.asset.AssetProfileInfo; |
||||
|
import org.thingsboard.server.common.data.exception.ThingsboardException; |
||||
|
import org.thingsboard.server.common.data.id.AssetProfileId; |
||||
|
import org.thingsboard.server.common.data.page.PageData; |
||||
|
import org.thingsboard.server.common.data.page.PageLink; |
||||
|
import org.thingsboard.server.dao.timeseries.TimeseriesService; |
||||
|
import org.thingsboard.server.queue.util.TbCoreComponent; |
||||
|
import org.thingsboard.server.service.entitiy.asset.profile.TbAssetProfileService; |
||||
|
import org.thingsboard.server.service.security.permission.Operation; |
||||
|
import org.thingsboard.server.service.security.permission.Resource; |
||||
|
|
||||
|
import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_ID; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_ID_PARAM_DESCRIPTION; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_INFO_DESCRIPTION; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_TEXT_SEARCH_DESCRIPTION; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH; |
||||
|
import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK; |
||||
|
|
||||
|
@RestController |
||||
|
@TbCoreComponent |
||||
|
@RequestMapping("/api") |
||||
|
@RequiredArgsConstructor |
||||
|
@Slf4j |
||||
|
public class AssetProfileController extends BaseController { |
||||
|
|
||||
|
private final TbAssetProfileService tbAssetProfileService; |
||||
|
|
||||
|
@ApiOperation(value = "Get Asset Profile (getAssetProfileById)", |
||||
|
notes = "Fetch the Asset Profile object based on the provided Asset Profile Id. " + |
||||
|
"The server checks that the asset profile is owned by the same tenant. " + TENANT_AUTHORITY_PARAGRAPH, |
||||
|
produces = "application/json") |
||||
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
||||
|
@RequestMapping(value = "/assetProfile/{assetProfileId}", method = RequestMethod.GET) |
||||
|
@ResponseBody |
||||
|
public AssetProfile getAssetProfileById( |
||||
|
@ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION) |
||||
|
@PathVariable(ASSET_PROFILE_ID) String strAssetProfileId) throws ThingsboardException { |
||||
|
checkParameter(ASSET_PROFILE_ID, strAssetProfileId); |
||||
|
try { |
||||
|
AssetProfileId assetProfileId = new AssetProfileId(toUUID(strAssetProfileId)); |
||||
|
return checkAssetProfileId(assetProfileId, Operation.READ); |
||||
|
} catch (Exception e) { |
||||
|
throw handleException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@ApiOperation(value = "Get Asset Profile Info (getAssetProfileInfoById)", |
||||
|
notes = "Fetch the Asset Profile Info object based on the provided Asset Profile Id. " |
||||
|
+ ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, |
||||
|
produces = "application/json") |
||||
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
||||
|
@RequestMapping(value = "/assetProfileInfo/{assetProfileId}", method = RequestMethod.GET) |
||||
|
@ResponseBody |
||||
|
public AssetProfileInfo getAssetProfileInfoById( |
||||
|
@ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION) |
||||
|
@PathVariable(ASSET_PROFILE_ID) String strAssetProfileId) throws ThingsboardException { |
||||
|
checkParameter(ASSET_PROFILE_ID, strAssetProfileId); |
||||
|
try { |
||||
|
AssetProfileId assetProfileId = new AssetProfileId(toUUID(strAssetProfileId)); |
||||
|
return new AssetProfileInfo(checkAssetProfileId(assetProfileId, Operation.READ)); |
||||
|
} catch (Exception e) { |
||||
|
throw handleException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@ApiOperation(value = "Get Default Asset Profile (getDefaultAssetProfileInfo)", |
||||
|
notes = "Fetch the Default Asset Profile Info object. " + |
||||
|
ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, |
||||
|
produces = "application/json") |
||||
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
||||
|
@RequestMapping(value = "/assetProfileInfo/default", method = RequestMethod.GET) |
||||
|
@ResponseBody |
||||
|
public AssetProfileInfo getDefaultAssetProfileInfo() throws ThingsboardException { |
||||
|
try { |
||||
|
return checkNotNull(assetProfileService.findDefaultAssetProfileInfo(getTenantId())); |
||||
|
} catch (Exception e) { |
||||
|
throw handleException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@ApiOperation(value = "Create Or Update Asset Profile (saveAssetProfile)", |
||||
|
notes = "Create or update the Asset Profile. When creating asset profile, platform generates asset profile id as " + UUID_WIKI_LINK + |
||||
|
"The newly created asset profile id will be present in the response. " + |
||||
|
"Specify existing asset profile id to update the asset profile. " + |
||||
|
"Referencing non-existing asset profile Id will cause 'Not Found' error. " + NEW_LINE + |
||||
|
"Asset profile name is unique in the scope of tenant. Only one 'default' asset profile may exist in scope of tenant. " + |
||||
|
"Remove 'id', 'tenantId' from the request body example (below) to create new Asset Profile entity. " + |
||||
|
TENANT_AUTHORITY_PARAGRAPH, |
||||
|
produces = "application/json", |
||||
|
consumes = "application/json") |
||||
|
@PreAuthorize("hasAuthority('TENANT_ADMIN')") |
||||
|
@RequestMapping(value = "/assetProfile", method = RequestMethod.POST) |
||||
|
@ResponseBody |
||||
|
public AssetProfile saveAssetProfile( |
||||
|
@ApiParam(value = "A JSON value representing the asset profile.") |
||||
|
@RequestBody AssetProfile assetProfile) throws Exception { |
||||
|
assetProfile.setTenantId(getTenantId()); |
||||
|
checkEntity(assetProfile.getId(), assetProfile, Resource.ASSET_PROFILE); |
||||
|
return tbAssetProfileService.save(assetProfile, getCurrentUser()); |
||||
|
} |
||||
|
|
||||
|
@ApiOperation(value = "Delete asset profile (deleteAssetProfile)", |
||||
|
notes = "Deletes the asset profile. Referencing non-existing asset profile Id will cause an error. " + |
||||
|
"Can't delete the asset profile if it is referenced by existing assets." + TENANT_AUTHORITY_PARAGRAPH, |
||||
|
produces = "application/json") |
||||
|
@PreAuthorize("hasAuthority('TENANT_ADMIN')") |
||||
|
@RequestMapping(value = "/assetProfile/{assetProfileId}", method = RequestMethod.DELETE) |
||||
|
@ResponseStatus(value = HttpStatus.OK) |
||||
|
public void deleteAssetProfile( |
||||
|
@ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION) |
||||
|
@PathVariable(ASSET_PROFILE_ID) String strAssetProfileId) throws ThingsboardException { |
||||
|
checkParameter(ASSET_PROFILE_ID, strAssetProfileId); |
||||
|
AssetProfileId assetProfileId = new AssetProfileId(toUUID(strAssetProfileId)); |
||||
|
AssetProfile assetProfile = checkAssetProfileId(assetProfileId, Operation.DELETE); |
||||
|
tbAssetProfileService.delete(assetProfile, getCurrentUser()); |
||||
|
} |
||||
|
|
||||
|
@ApiOperation(value = "Make Asset Profile Default (setDefaultAssetProfile)", |
||||
|
notes = "Marks asset profile as default within a tenant scope." + TENANT_AUTHORITY_PARAGRAPH, |
||||
|
produces = "application/json") |
||||
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
||||
|
@RequestMapping(value = "/assetProfile/{assetProfileId}/default", method = RequestMethod.POST) |
||||
|
@ResponseBody |
||||
|
public AssetProfile setDefaultAssetProfile( |
||||
|
@ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION) |
||||
|
@PathVariable(ASSET_PROFILE_ID) String strAssetProfileId) throws ThingsboardException { |
||||
|
checkParameter(ASSET_PROFILE_ID, strAssetProfileId); |
||||
|
AssetProfileId assetProfileId = new AssetProfileId(toUUID(strAssetProfileId)); |
||||
|
AssetProfile assetProfile = checkAssetProfileId(assetProfileId, Operation.WRITE); |
||||
|
AssetProfile previousDefaultAssetProfile = assetProfileService.findDefaultAssetProfile(getTenantId()); |
||||
|
return tbAssetProfileService.setDefaultAssetProfile(assetProfile, previousDefaultAssetProfile, getCurrentUser()); |
||||
|
} |
||||
|
|
||||
|
@ApiOperation(value = "Get Asset Profiles (getAssetProfiles)", |
||||
|
notes = "Returns a page of asset profile objects owned by tenant. " + |
||||
|
PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, |
||||
|
produces = "application/json") |
||||
|
@PreAuthorize("hasAuthority('TENANT_ADMIN')") |
||||
|
@RequestMapping(value = "/assetProfiles", params = {"pageSize", "page"}, method = RequestMethod.GET) |
||||
|
@ResponseBody |
||||
|
public PageData<AssetProfile> getAssetProfiles( |
||||
|
@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) |
||||
|
@RequestParam int pageSize, |
||||
|
@ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) |
||||
|
@RequestParam int page, |
||||
|
@ApiParam(value = ASSET_PROFILE_TEXT_SEARCH_DESCRIPTION) |
||||
|
@RequestParam(required = false) String textSearch, |
||||
|
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES) |
||||
|
@RequestParam(required = false) String sortProperty, |
||||
|
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) |
||||
|
@RequestParam(required = false) String sortOrder) throws ThingsboardException { |
||||
|
try { |
||||
|
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
||||
|
return checkNotNull(assetProfileService.findAssetProfiles(getTenantId(), pageLink)); |
||||
|
} catch (Exception e) { |
||||
|
throw handleException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@ApiOperation(value = "Get Asset Profile infos (getAssetProfileInfos)", |
||||
|
notes = "Returns a page of asset profile info objects owned by tenant. " + |
||||
|
PAGE_DATA_PARAMETERS + ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, |
||||
|
produces = "application/json") |
||||
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
||||
|
@RequestMapping(value = "/assetProfileInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) |
||||
|
@ResponseBody |
||||
|
public PageData<AssetProfileInfo> getAssetProfileInfos( |
||||
|
@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) |
||||
|
@RequestParam int pageSize, |
||||
|
@ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) |
||||
|
@RequestParam int page, |
||||
|
@ApiParam(value = ASSET_PROFILE_TEXT_SEARCH_DESCRIPTION) |
||||
|
@RequestParam(required = false) String textSearch, |
||||
|
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES) |
||||
|
@RequestParam(required = false) String sortProperty, |
||||
|
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) |
||||
|
@RequestParam(required = false) String sortOrder) throws ThingsboardException { |
||||
|
try { |
||||
|
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
||||
|
return checkNotNull(assetProfileService.findAssetProfileInfos(getTenantId(), pageLink)); |
||||
|
} catch (Exception e) { |
||||
|
throw handleException(e); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,62 @@ |
|||||
|
/** |
||||
|
* 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.constructor; |
||||
|
|
||||
|
import com.google.protobuf.ByteString; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
import org.thingsboard.server.common.data.asset.AssetProfile; |
||||
|
import org.thingsboard.server.common.data.id.AssetProfileId; |
||||
|
import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg; |
||||
|
import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
||||
|
import org.thingsboard.server.queue.util.TbCoreComponent; |
||||
|
|
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
|
||||
|
@Component |
||||
|
@TbCoreComponent |
||||
|
public class AssetProfileMsgConstructor { |
||||
|
|
||||
|
public AssetProfileUpdateMsg constructAssetProfileUpdatedMsg(UpdateMsgType msgType, AssetProfile assetProfile) { |
||||
|
AssetProfileUpdateMsg.Builder builder = AssetProfileUpdateMsg.newBuilder() |
||||
|
.setMsgType(msgType) |
||||
|
.setIdMSB(assetProfile.getId().getId().getMostSignificantBits()) |
||||
|
.setIdLSB(assetProfile.getId().getId().getLeastSignificantBits()) |
||||
|
.setName(assetProfile.getName()) |
||||
|
.setDefault(assetProfile.isDefault()); |
||||
|
if (assetProfile.getDefaultDashboardId() != null) { |
||||
|
builder.setDefaultDashboardIdMSB(assetProfile.getDefaultDashboardId().getId().getMostSignificantBits()) |
||||
|
.setDefaultDashboardIdLSB(assetProfile.getDefaultDashboardId().getId().getLeastSignificantBits()); |
||||
|
} |
||||
|
if (assetProfile.getDefaultQueueName() != null) { |
||||
|
builder.setDefaultQueueName(assetProfile.getDefaultQueueName()); |
||||
|
} |
||||
|
if (assetProfile.getDescription() != null) { |
||||
|
builder.setDescription(assetProfile.getDescription()); |
||||
|
} |
||||
|
if (assetProfile.getImage() != null) { |
||||
|
builder.setImage(ByteString.copyFrom(assetProfile.getImage().getBytes(StandardCharsets.UTF_8))); |
||||
|
} |
||||
|
return builder.build(); |
||||
|
} |
||||
|
|
||||
|
public AssetProfileUpdateMsg constructAssetProfileDeleteMsg(AssetProfileId assetProfileId) { |
||||
|
return AssetProfileUpdateMsg.newBuilder() |
||||
|
.setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE) |
||||
|
.setIdMSB(assetProfileId.getId().getMostSignificantBits()) |
||||
|
.setIdLSB(assetProfileId.getId().getLeastSignificantBits()).build(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
/** |
||||
|
* 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.constructor; |
||||
|
|
||||
|
import org.springframework.stereotype.Component; |
||||
|
import org.thingsboard.common.util.JacksonUtil; |
||||
|
import org.thingsboard.server.common.data.edge.Edge; |
||||
|
import org.thingsboard.server.gen.edge.v1.EdgeConfiguration; |
||||
|
import org.thingsboard.server.queue.util.TbCoreComponent; |
||||
|
|
||||
|
@Component |
||||
|
@TbCoreComponent |
||||
|
public class EdgeMsgConstructor { |
||||
|
|
||||
|
public EdgeConfiguration constructEdgeConfiguration(Edge edge) { |
||||
|
EdgeConfiguration.Builder builder = EdgeConfiguration.newBuilder() |
||||
|
.setEdgeIdMSB(edge.getId().getId().getMostSignificantBits()) |
||||
|
.setEdgeIdLSB(edge.getId().getId().getLeastSignificantBits()) |
||||
|
.setTenantIdMSB(edge.getTenantId().getId().getMostSignificantBits()) |
||||
|
.setTenantIdLSB(edge.getTenantId().getId().getLeastSignificantBits()) |
||||
|
.setName(edge.getName()) |
||||
|
.setType(edge.getType()) |
||||
|
.setRoutingKey(edge.getRoutingKey()) |
||||
|
.setSecret(edge.getSecret()) |
||||
|
.setAdditionalInfo(JacksonUtil.toString(edge.getAdditionalInfo())) |
||||
|
.setCloudType("CE"); |
||||
|
if (edge.getCustomerId() != null) { |
||||
|
builder.setCustomerIdMSB(edge.getCustomerId().getId().getMostSignificantBits()) |
||||
|
.setCustomerIdLSB(edge.getCustomerId().getId().getLeastSignificantBits()); |
||||
|
} |
||||
|
return builder.build(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
/** |
||||
|
* 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.fetch; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.thingsboard.server.common.data.EdgeUtils; |
||||
|
import org.thingsboard.server.common.data.asset.AssetProfile; |
||||
|
import org.thingsboard.server.common.data.edge.Edge; |
||||
|
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.TenantId; |
||||
|
import org.thingsboard.server.common.data.page.PageData; |
||||
|
import org.thingsboard.server.common.data.page.PageLink; |
||||
|
import org.thingsboard.server.dao.asset.AssetProfileService; |
||||
|
|
||||
|
@AllArgsConstructor |
||||
|
@Slf4j |
||||
|
public class AssetProfilesEdgeEventFetcher extends BasePageableEdgeEventFetcher<AssetProfile> { |
||||
|
|
||||
|
private final AssetProfileService assetProfileService; |
||||
|
|
||||
|
@Override |
||||
|
PageData<AssetProfile> fetchPageData(TenantId tenantId, Edge edge, PageLink pageLink) { |
||||
|
return assetProfileService.findAssetProfiles(tenantId, pageLink); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
EdgeEvent constructEdgeEvent(TenantId tenantId, Edge edge, AssetProfile assetProfile) { |
||||
|
return EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ASSET_PROFILE, |
||||
|
EdgeEventActionType.ADDED, assetProfile.getId(), null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
/** |
||||
|
* 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.fetch; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.thingsboard.server.common.data.Device; |
||||
|
import org.thingsboard.server.common.data.EdgeUtils; |
||||
|
import org.thingsboard.server.common.data.edge.Edge; |
||||
|
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.TenantId; |
||||
|
import org.thingsboard.server.common.data.page.PageData; |
||||
|
import org.thingsboard.server.common.data.page.PageLink; |
||||
|
import org.thingsboard.server.dao.device.DeviceService; |
||||
|
|
||||
|
@AllArgsConstructor |
||||
|
@Slf4j |
||||
|
public class DevicesEdgeEventFetcher extends BasePageableEdgeEventFetcher<Device> { |
||||
|
|
||||
|
private final DeviceService deviceService; |
||||
|
|
||||
|
@Override |
||||
|
PageData<Device> fetchPageData(TenantId tenantId, Edge edge, PageLink pageLink) { |
||||
|
return deviceService.findDevicesByTenantIdAndEdgeId(tenantId, edge.getId(), pageLink); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
EdgeEvent constructEdgeEvent(TenantId tenantId, Edge edge, Device device) { |
||||
|
return EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, |
||||
|
EdgeEventActionType.ADDED, device.getId(), null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
/** |
||||
|
* 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.fetch; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.thingsboard.server.common.data.EdgeUtils; |
||||
|
import org.thingsboard.server.common.data.EntityView; |
||||
|
import org.thingsboard.server.common.data.edge.Edge; |
||||
|
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.TenantId; |
||||
|
import org.thingsboard.server.common.data.page.PageData; |
||||
|
import org.thingsboard.server.common.data.page.PageLink; |
||||
|
import org.thingsboard.server.dao.entityview.EntityViewService; |
||||
|
|
||||
|
@AllArgsConstructor |
||||
|
@Slf4j |
||||
|
public class EntityViewsEdgeEventFetcher extends BasePageableEdgeEventFetcher<EntityView> { |
||||
|
|
||||
|
private final EntityViewService entityViewService; |
||||
|
|
||||
|
@Override |
||||
|
PageData<EntityView> fetchPageData(TenantId tenantId, Edge edge, PageLink pageLink) { |
||||
|
return entityViewService.findEntityViewsByTenantIdAndEdgeId(tenantId, edge.getId(), pageLink); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
EdgeEvent constructEdgeEvent(TenantId tenantId, Edge edge, EntityView entityView) { |
||||
|
return EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ENTITY_VIEW, |
||||
|
EdgeEventActionType.ADDED, entityView.getId(), null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,70 @@ |
|||||
|
/** |
||||
|
* 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.processor; |
||||
|
|
||||
|
import com.google.common.util.concurrent.ListenableFuture; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
import org.thingsboard.server.common.data.EdgeUtils; |
||||
|
import org.thingsboard.server.common.data.asset.AssetProfile; |
||||
|
import org.thingsboard.server.common.data.edge.EdgeEvent; |
||||
|
import org.thingsboard.server.common.data.id.AssetProfileId; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg; |
||||
|
import org.thingsboard.server.gen.edge.v1.DownlinkMsg; |
||||
|
import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
||||
|
import org.thingsboard.server.gen.transport.TransportProtos; |
||||
|
import org.thingsboard.server.queue.util.TbCoreComponent; |
||||
|
|
||||
|
@Component |
||||
|
@Slf4j |
||||
|
@TbCoreComponent |
||||
|
public class AssetProfileEdgeProcessor extends BaseEdgeProcessor { |
||||
|
|
||||
|
public DownlinkMsg convertAssetProfileEventToDownlink(EdgeEvent edgeEvent) { |
||||
|
AssetProfileId assetProfileId = new AssetProfileId(edgeEvent.getEntityId()); |
||||
|
DownlinkMsg downlinkMsg = null; |
||||
|
switch (edgeEvent.getAction()) { |
||||
|
case ADDED: |
||||
|
case UPDATED: |
||||
|
AssetProfile assetProfile = assetProfileService.findAssetProfileById(edgeEvent.getTenantId(), assetProfileId); |
||||
|
if (assetProfile != null) { |
||||
|
UpdateMsgType msgType = getUpdateMsgType(edgeEvent.getAction()); |
||||
|
AssetProfileUpdateMsg assetProfileUpdateMsg = |
||||
|
assetProfileMsgConstructor.constructAssetProfileUpdatedMsg(msgType, assetProfile); |
||||
|
downlinkMsg = DownlinkMsg.newBuilder() |
||||
|
.setDownlinkMsgId(EdgeUtils.nextPositiveInt()) |
||||
|
.addAssetProfileUpdateMsg(assetProfileUpdateMsg) |
||||
|
.build(); |
||||
|
} |
||||
|
break; |
||||
|
case DELETED: |
||||
|
AssetProfileUpdateMsg assetProfileUpdateMsg = |
||||
|
assetProfileMsgConstructor.constructAssetProfileDeleteMsg(assetProfileId); |
||||
|
downlinkMsg = DownlinkMsg.newBuilder() |
||||
|
.setDownlinkMsgId(EdgeUtils.nextPositiveInt()) |
||||
|
.addAssetProfileUpdateMsg(assetProfileUpdateMsg) |
||||
|
.build(); |
||||
|
break; |
||||
|
} |
||||
|
return downlinkMsg; |
||||
|
} |
||||
|
|
||||
|
public ListenableFuture<Void> processAssetProfileNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { |
||||
|
return processEntityNotificationForAllEdges(tenantId, edgeNotificationMsg); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -1,235 +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.processor; |
|
||||
|
|
||||
import com.google.common.util.concurrent.Futures; |
|
||||
import com.google.common.util.concurrent.ListenableFuture; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.data.Device; |
|
||||
import org.thingsboard.server.common.data.EdgeUtils; |
|
||||
import org.thingsboard.server.common.data.edge.Edge; |
|
||||
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.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.EntityIdFactory; |
|
||||
import org.thingsboard.server.common.data.id.RuleChainId; |
|
||||
import org.thingsboard.server.common.data.id.TenantId; |
|
||||
import org.thingsboard.server.common.data.page.PageData; |
|
||||
import org.thingsboard.server.common.data.page.PageLink; |
|
||||
import org.thingsboard.server.common.data.rule.RuleChain; |
|
||||
import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; |
|
||||
import org.thingsboard.server.gen.edge.v1.DeviceCredentialsRequestMsg; |
|
||||
import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg; |
|
||||
import org.thingsboard.server.gen.edge.v1.DownlinkMsg; |
|
||||
import org.thingsboard.server.gen.edge.v1.UpdateMsgType; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos; |
|
||||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|
||||
|
|
||||
import java.util.ArrayList; |
|
||||
import java.util.List; |
|
||||
import java.util.UUID; |
|
||||
|
|
||||
@Component |
|
||||
@Slf4j |
|
||||
@TbCoreComponent |
|
||||
public class EntityEdgeProcessor extends BaseEdgeProcessor { |
|
||||
|
|
||||
public DownlinkMsg processEntityMergeRequestMessageToEdge(Edge edge, EdgeEvent edgeEvent) { |
|
||||
DownlinkMsg downlinkMsg = null; |
|
||||
if (EdgeEventType.DEVICE.equals(edgeEvent.getType())) { |
|
||||
DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); |
|
||||
Device device = deviceService.findDeviceById(edge.getTenantId(), deviceId); |
|
||||
CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device, edge); |
|
||||
String conflictName = null; |
|
||||
if(edgeEvent.getBody() != null) { |
|
||||
conflictName = edgeEvent.getBody().get("conflictName").asText(); |
|
||||
} |
|
||||
DeviceUpdateMsg deviceUpdateMsg = deviceMsgConstructor |
|
||||
.constructDeviceUpdatedMsg(UpdateMsgType.ENTITY_MERGE_RPC_MESSAGE, device, customerId, conflictName); |
|
||||
downlinkMsg = DownlinkMsg.newBuilder() |
|
||||
.setDownlinkMsgId(EdgeUtils.nextPositiveInt()) |
|
||||
.addDeviceUpdateMsg(deviceUpdateMsg) |
|
||||
.build(); |
|
||||
} |
|
||||
return downlinkMsg; |
|
||||
} |
|
||||
|
|
||||
public DownlinkMsg processCredentialsRequestMessageToEdge(EdgeEvent edgeEvent) { |
|
||||
DownlinkMsg downlinkMsg = null; |
|
||||
if (EdgeEventType.DEVICE.equals(edgeEvent.getType())) { |
|
||||
DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); |
|
||||
DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = DeviceCredentialsRequestMsg.newBuilder() |
|
||||
.setDeviceIdMSB(deviceId.getId().getMostSignificantBits()) |
|
||||
.setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()) |
|
||||
.build(); |
|
||||
DownlinkMsg.Builder builder = DownlinkMsg.newBuilder() |
|
||||
.setDownlinkMsgId(EdgeUtils.nextPositiveInt()) |
|
||||
.addDeviceCredentialsRequestMsg(deviceCredentialsRequestMsg); |
|
||||
downlinkMsg = builder.build(); |
|
||||
} |
|
||||
return downlinkMsg; |
|
||||
} |
|
||||
|
|
||||
public ListenableFuture<Void> processEntityNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { |
|
||||
EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); |
|
||||
EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); |
|
||||
EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, |
|
||||
new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); |
|
||||
EdgeId edgeId = safeGetEdgeId(edgeNotificationMsg); |
|
||||
switch (actionType) { |
|
||||
case ADDED: // used only for USER entity
|
|
||||
case UPDATED: |
|
||||
case CREDENTIALS_UPDATED: |
|
||||
return pushNotificationToAllRelatedEdges(tenantId, entityId, type, actionType); |
|
||||
case ASSIGNED_TO_CUSTOMER: |
|
||||
case UNASSIGNED_FROM_CUSTOMER: |
|
||||
return pushNotificationToAllRelatedCustomerEdges(tenantId, edgeNotificationMsg, entityId, actionType, type); |
|
||||
case DELETED: |
|
||||
if (edgeId != null) { |
|
||||
return saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null); |
|
||||
} else { |
|
||||
return pushNotificationToAllRelatedEdges(tenantId, entityId, type, actionType); |
|
||||
} |
|
||||
case ASSIGNED_TO_EDGE: |
|
||||
case UNASSIGNED_FROM_EDGE: |
|
||||
ListenableFuture<Void> future = saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null); |
|
||||
return Futures.transformAsync(future, unused -> { |
|
||||
if (type.equals(EdgeEventType.RULE_CHAIN)) { |
|
||||
return updateDependentRuleChains(tenantId, new RuleChainId(entityId.getId()), edgeId); |
|
||||
} else { |
|
||||
return Futures.immediateFuture(null); |
|
||||
} |
|
||||
}, dbCallbackExecutorService); |
|
||||
default: |
|
||||
return Futures.immediateFuture(null); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private ListenableFuture<Void> pushNotificationToAllRelatedCustomerEdges(TenantId tenantId, |
|
||||
TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, |
|
||||
EntityId entityId, |
|
||||
EdgeEventActionType actionType, |
|
||||
EdgeEventType type) { |
|
||||
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); |
|
||||
PageData<EdgeId> pageData; |
|
||||
List<ListenableFuture<Void>> futures = new ArrayList<>(); |
|
||||
do { |
|
||||
pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId, pageLink); |
|
||||
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { |
|
||||
for (EdgeId relatedEdgeId : pageData.getData()) { |
|
||||
try { |
|
||||
CustomerId customerId = mapper.readValue(edgeNotificationMsg.getBody(), CustomerId.class); |
|
||||
ListenableFuture<Edge> future = edgeService.findEdgeByIdAsync(tenantId, relatedEdgeId); |
|
||||
futures.add(Futures.transformAsync(future, edge -> { |
|
||||
if (edge != null && edge.getCustomerId() != null && |
|
||||
!edge.getCustomerId().isNullUid() && edge.getCustomerId().equals(customerId)) { |
|
||||
return saveEdgeEvent(tenantId, relatedEdgeId, type, actionType, entityId, null); |
|
||||
} else { |
|
||||
return Futures.immediateFuture(null); |
|
||||
} |
|
||||
}, dbCallbackExecutorService)); |
|
||||
} catch (Exception e) { |
|
||||
log.error("Can't parse customer id from entity body [{}]", edgeNotificationMsg, e); |
|
||||
return Futures.immediateFailedFuture(e); |
|
||||
} |
|
||||
} |
|
||||
if (pageData.hasNext()) { |
|
||||
pageLink = pageLink.nextPageLink(); |
|
||||
} |
|
||||
} |
|
||||
} while (pageData != null && pageData.hasNext()); |
|
||||
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService); |
|
||||
} |
|
||||
|
|
||||
private EdgeId safeGetEdgeId(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { |
|
||||
if (edgeNotificationMsg.getEdgeIdMSB() != 0 && edgeNotificationMsg.getEdgeIdLSB() != 0) { |
|
||||
return new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); |
|
||||
} else { |
|
||||
return null; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private ListenableFuture<Void> pushNotificationToAllRelatedEdges(TenantId tenantId, EntityId entityId, EdgeEventType type, EdgeEventActionType actionType) { |
|
||||
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); |
|
||||
PageData<EdgeId> pageData; |
|
||||
List<ListenableFuture<Void>> futures = new ArrayList<>(); |
|
||||
do { |
|
||||
pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId, pageLink); |
|
||||
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { |
|
||||
for (EdgeId relatedEdgeId : pageData.getData()) { |
|
||||
futures.add(saveEdgeEvent(tenantId, relatedEdgeId, type, actionType, entityId, null)); |
|
||||
} |
|
||||
if (pageData.hasNext()) { |
|
||||
pageLink = pageLink.nextPageLink(); |
|
||||
} |
|
||||
} |
|
||||
} while (pageData != null && pageData.hasNext()); |
|
||||
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService); |
|
||||
} |
|
||||
|
|
||||
private ListenableFuture<Void> updateDependentRuleChains(TenantId tenantId, RuleChainId processingRuleChainId, EdgeId edgeId) { |
|
||||
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); |
|
||||
PageData<RuleChain> pageData; |
|
||||
List<ListenableFuture<Void>> futures = new ArrayList<>(); |
|
||||
do { |
|
||||
pageData = ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, pageLink); |
|
||||
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { |
|
||||
for (RuleChain ruleChain : pageData.getData()) { |
|
||||
if (!ruleChain.getId().equals(processingRuleChainId)) { |
|
||||
List<RuleChainConnectionInfo> connectionInfos = |
|
||||
ruleChainService.loadRuleChainMetaData(ruleChain.getTenantId(), ruleChain.getId()).getRuleChainConnections(); |
|
||||
if (connectionInfos != null && !connectionInfos.isEmpty()) { |
|
||||
for (RuleChainConnectionInfo connectionInfo : connectionInfos) { |
|
||||
if (connectionInfo.getTargetRuleChainId().equals(processingRuleChainId)) { |
|
||||
futures.add(saveEdgeEvent(tenantId, |
|
||||
edgeId, |
|
||||
EdgeEventType.RULE_CHAIN_METADATA, |
|
||||
EdgeEventActionType.UPDATED, |
|
||||
ruleChain.getId(), |
|
||||
null)); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
if (pageData.hasNext()) { |
|
||||
pageLink = pageLink.nextPageLink(); |
|
||||
} |
|
||||
} |
|
||||
} while (pageData != null && pageData.hasNext()); |
|
||||
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService); |
|
||||
} |
|
||||
|
|
||||
public ListenableFuture<Void> processEntityNotificationForAllEdges(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { |
|
||||
EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); |
|
||||
EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); |
|
||||
EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); |
|
||||
switch (actionType) { |
|
||||
case ADDED: |
|
||||
case UPDATED: |
|
||||
case DELETED: |
|
||||
return processActionForAllEdges(tenantId, type, actionType, entityId); |
|
||||
default: |
|
||||
return Futures.immediateFuture(null); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@ -0,0 +1,110 @@ |
|||||
|
/** |
||||
|
* 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.profile; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.User; |
||||
|
import org.thingsboard.server.common.data.asset.AssetProfile; |
||||
|
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.AssetProfileId; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
||||
|
import org.thingsboard.server.dao.asset.AssetProfileService; |
||||
|
import org.thingsboard.server.queue.util.TbCoreComponent; |
||||
|
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
||||
|
|
||||
|
import static org.thingsboard.server.dao.asset.BaseAssetService.TB_SERVICE_QUEUE; |
||||
|
|
||||
|
@Service |
||||
|
@TbCoreComponent |
||||
|
@AllArgsConstructor |
||||
|
@Slf4j |
||||
|
public class DefaultTbAssetProfileService extends AbstractTbEntityService implements TbAssetProfileService { |
||||
|
|
||||
|
private final AssetProfileService assetProfileService; |
||||
|
|
||||
|
@Override |
||||
|
public AssetProfile save(AssetProfile assetProfile, User user) throws Exception { |
||||
|
ActionType actionType = assetProfile.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
||||
|
TenantId tenantId = assetProfile.getTenantId(); |
||||
|
try { |
||||
|
if (TB_SERVICE_QUEUE.equals(assetProfile.getName())) { |
||||
|
throw new ThingsboardException("Unable to save asset profile with name " + TB_SERVICE_QUEUE, ThingsboardErrorCode.BAD_REQUEST_PARAMS); |
||||
|
} else if (assetProfile.getId() != null) { |
||||
|
AssetProfile foundAssetProfile = assetProfileService.findAssetProfileById(tenantId, assetProfile.getId()); |
||||
|
if (foundAssetProfile != null && TB_SERVICE_QUEUE.equals(foundAssetProfile.getName())) { |
||||
|
throw new ThingsboardException("Updating asset profile with name " + TB_SERVICE_QUEUE + " is prohibited!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); |
||||
|
} |
||||
|
} |
||||
|
AssetProfile savedAssetProfile = checkNotNull(assetProfileService.saveAssetProfile(assetProfile)); |
||||
|
autoCommit(user, savedAssetProfile.getId()); |
||||
|
tbClusterService.broadcastEntityStateChangeEvent(tenantId, savedAssetProfile.getId(), |
||||
|
actionType.equals(ActionType.ADDED) ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); |
||||
|
|
||||
|
notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, savedAssetProfile.getId(), |
||||
|
savedAssetProfile, user, actionType, true, null); |
||||
|
return savedAssetProfile; |
||||
|
} catch (Exception e) { |
||||
|
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ASSET_PROFILE), assetProfile, actionType, user, e); |
||||
|
throw e; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void delete(AssetProfile assetProfile, User user) { |
||||
|
AssetProfileId assetProfileId = assetProfile.getId(); |
||||
|
TenantId tenantId = assetProfile.getTenantId(); |
||||
|
try { |
||||
|
assetProfileService.deleteAssetProfile(tenantId, assetProfileId); |
||||
|
|
||||
|
tbClusterService.broadcastEntityStateChangeEvent(tenantId, assetProfileId, ComponentLifecycleEvent.DELETED); |
||||
|
notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, assetProfileId, assetProfile, |
||||
|
user, ActionType.DELETED, true, null, assetProfileId.toString()); |
||||
|
} catch (Exception e) { |
||||
|
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ASSET_PROFILE), ActionType.DELETED, |
||||
|
user, e, assetProfileId.toString()); |
||||
|
throw e; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public AssetProfile setDefaultAssetProfile(AssetProfile assetProfile, AssetProfile previousDefaultAssetProfile, User user) throws ThingsboardException { |
||||
|
TenantId tenantId = assetProfile.getTenantId(); |
||||
|
AssetProfileId assetProfileId = assetProfile.getId(); |
||||
|
try { |
||||
|
if (assetProfileService.setDefaultAssetProfile(tenantId, assetProfileId)) { |
||||
|
if (previousDefaultAssetProfile != null) { |
||||
|
previousDefaultAssetProfile = assetProfileService.findAssetProfileById(tenantId, previousDefaultAssetProfile.getId()); |
||||
|
notificationEntityService.logEntityAction(tenantId, previousDefaultAssetProfile.getId(), previousDefaultAssetProfile, |
||||
|
ActionType.UPDATED, user); |
||||
|
} |
||||
|
assetProfile = assetProfileService.findAssetProfileById(tenantId, assetProfileId); |
||||
|
|
||||
|
notificationEntityService.logEntityAction(tenantId, assetProfileId, assetProfile, ActionType.UPDATED, user); |
||||
|
} |
||||
|
return assetProfile; |
||||
|
} catch (Exception e) { |
||||
|
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ASSET_PROFILE), ActionType.UPDATED, |
||||
|
user, e, assetProfileId.toString()); |
||||
|
throw e; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
/** |
||||
|
* 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.profile; |
||||
|
|
||||
|
import org.thingsboard.server.common.data.User; |
||||
|
import org.thingsboard.server.common.data.asset.AssetProfile; |
||||
|
import org.thingsboard.server.common.data.exception.ThingsboardException; |
||||
|
import org.thingsboard.server.service.entitiy.SimpleTbEntityService; |
||||
|
|
||||
|
public interface TbAssetProfileService extends SimpleTbEntityService<AssetProfile> { |
||||
|
|
||||
|
AssetProfile setDefaultAssetProfile(AssetProfile assetProfile, AssetProfile previousDefaultAssetProfile, User user) throws ThingsboardException; |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue