Showing
59 changed files
with
2035 additions
and
736 deletions
Too many changes to show.
To preserve performance only 59 of 142 files are displayed.
@@ -146,6 +146,10 @@ | @@ -146,6 +146,10 @@ | ||
146 | <scope>runtime</scope> | 146 | <scope>runtime</scope> |
147 | </dependency> | 147 | </dependency> |
148 | <dependency> | 148 | <dependency> |
149 | + <groupId>org.springframework.integration</groupId> | ||
150 | + <artifactId>spring-integration-redis</artifactId> | ||
151 | + </dependency> | ||
152 | + <dependency> | ||
149 | <groupId>org.springframework.boot</groupId> | 153 | <groupId>org.springframework.boot</groupId> |
150 | <artifactId>spring-boot-starter-security</artifactId> | 154 | <artifactId>spring-boot-starter-security</artifactId> |
151 | </dependency> | 155 | </dependency> |
@@ -78,14 +78,24 @@ CREATE TABLE IF NOT EXISTS firmware ( | @@ -78,14 +78,24 @@ CREATE TABLE IF NOT EXISTS firmware ( | ||
78 | CONSTRAINT firmware_tenant_title_version_unq_key UNIQUE (tenant_id, title, version) | 78 | CONSTRAINT firmware_tenant_title_version_unq_key UNIQUE (tenant_id, title, version) |
79 | ); | 79 | ); |
80 | 80 | ||
81 | +ALTER TABLE dashboard | ||
82 | + ADD COLUMN IF NOT EXISTS image varchar(1000000); | ||
83 | + | ||
81 | ALTER TABLE device_profile | 84 | ALTER TABLE device_profile |
85 | + ADD COLUMN IF NOT EXISTS image varchar(1000000), | ||
82 | ADD COLUMN IF NOT EXISTS firmware_id uuid, | 86 | ADD COLUMN IF NOT EXISTS firmware_id uuid, |
83 | - ADD COLUMN IF NOT EXISTS software_id uuid; | 87 | + ADD COLUMN IF NOT EXISTS software_id uuid, |
88 | + ADD COLUMN IF NOT EXISTS default_dashboard_id uuid; | ||
84 | 89 | ||
85 | ALTER TABLE device | 90 | ALTER TABLE device |
86 | ADD COLUMN IF NOT EXISTS firmware_id uuid, | 91 | ADD COLUMN IF NOT EXISTS firmware_id uuid, |
87 | ADD COLUMN IF NOT EXISTS software_id uuid; | 92 | ADD COLUMN IF NOT EXISTS software_id uuid; |
88 | 93 | ||
94 | +ALTER TABLE alarm | ||
95 | + ADD COLUMN IF NOT EXISTS customer_id uuid; | ||
96 | + | ||
97 | +DELETE FROM relation WHERE from_type = 'TENANT' AND relation_type_group = 'RULE_CHAIN'; | ||
98 | + | ||
89 | DO $$ | 99 | DO $$ |
90 | BEGIN | 100 | BEGIN |
91 | IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device_profile') THEN | 101 | IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device_profile') THEN |
@@ -100,6 +110,12 @@ DO $$ | @@ -100,6 +110,12 @@ DO $$ | ||
100 | FOREIGN KEY (firmware_id) REFERENCES firmware(id); | 110 | FOREIGN KEY (firmware_id) REFERENCES firmware(id); |
101 | END IF; | 111 | END IF; |
102 | 112 | ||
113 | + IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_default_dashboard_device_profile') THEN | ||
114 | + ALTER TABLE device_profile | ||
115 | + ADD CONSTRAINT fk_default_dashboard_device_profile | ||
116 | + FOREIGN KEY (default_dashboard_id) REFERENCES dashboard(id); | ||
117 | + END IF; | ||
118 | + | ||
103 | IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device') THEN | 119 | IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device') THEN |
104 | ALTER TABLE device | 120 | ALTER TABLE device |
105 | ADD CONSTRAINT fk_firmware_device | 121 | ADD CONSTRAINT fk_firmware_device |
@@ -114,3 +130,7 @@ DO $$ | @@ -114,3 +130,7 @@ DO $$ | ||
114 | END; | 130 | END; |
115 | $$; | 131 | $$; |
116 | 132 | ||
133 | + | ||
134 | +ALTER TABLE api_usage_state | ||
135 | + ADD COLUMN IF NOT EXISTS alarm_exec VARCHAR(32); | ||
136 | +UPDATE api_usage_state SET alarm_exec = 'ENABLED' WHERE alarm_exec IS NULL; |
@@ -197,6 +197,40 @@ public class AlarmController extends BaseController { | @@ -197,6 +197,40 @@ public class AlarmController extends BaseController { | ||
197 | } | 197 | } |
198 | 198 | ||
199 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 199 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
200 | + @RequestMapping(value = "/alarms", method = RequestMethod.GET) | ||
201 | + @ResponseBody | ||
202 | + public PageData<AlarmInfo> getAllAlarms( | ||
203 | + @RequestParam(required = false) String searchStatus, | ||
204 | + @RequestParam(required = false) String status, | ||
205 | + @RequestParam int pageSize, | ||
206 | + @RequestParam int page, | ||
207 | + @RequestParam(required = false) String textSearch, | ||
208 | + @RequestParam(required = false) String sortProperty, | ||
209 | + @RequestParam(required = false) String sortOrder, | ||
210 | + @RequestParam(required = false) Long startTime, | ||
211 | + @RequestParam(required = false) Long endTime, | ||
212 | + @RequestParam(required = false) Boolean fetchOriginator | ||
213 | + ) throws ThingsboardException { | ||
214 | + AlarmSearchStatus alarmSearchStatus = StringUtils.isEmpty(searchStatus) ? null : AlarmSearchStatus.valueOf(searchStatus); | ||
215 | + AlarmStatus alarmStatus = StringUtils.isEmpty(status) ? null : AlarmStatus.valueOf(status); | ||
216 | + if (alarmSearchStatus != null && alarmStatus != null) { | ||
217 | + throw new ThingsboardException("Invalid alarms search query: Both parameters 'searchStatus' " + | ||
218 | + "and 'status' can't be specified at the same time!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); | ||
219 | + } | ||
220 | + TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); | ||
221 | + | ||
222 | + try { | ||
223 | + if (getCurrentUser().isCustomerUser()) { | ||
224 | + return checkNotNull(alarmService.findCustomerAlarms(getCurrentUser().getTenantId(), getCurrentUser().getCustomerId(), new AlarmQuery(null, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator)).get()); | ||
225 | + } else { | ||
226 | + return checkNotNull(alarmService.findAlarms(getCurrentUser().getTenantId(), new AlarmQuery(null, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator)).get()); | ||
227 | + } | ||
228 | + } catch (Exception e) { | ||
229 | + throw handleException(e); | ||
230 | + } | ||
231 | + } | ||
232 | + | ||
233 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | ||
200 | @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET) | 234 | @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET) |
201 | @ResponseBody | 235 | @ResponseBody |
202 | public AlarmSeverity getHighestAlarmSeverity( | 236 | public AlarmSeverity getHighestAlarmSeverity( |
@@ -106,6 +106,8 @@ public abstract class BaseApiUsageState { | @@ -106,6 +106,8 @@ public abstract class BaseApiUsageState { | ||
106 | return apiUsageState.getEmailExecState(); | 106 | return apiUsageState.getEmailExecState(); |
107 | case SMS: | 107 | case SMS: |
108 | return apiUsageState.getSmsExecState(); | 108 | return apiUsageState.getSmsExecState(); |
109 | + case ALARM: | ||
110 | + return apiUsageState.getAlarmExecState(); | ||
109 | default: | 111 | default: |
110 | return ApiUsageStateValue.ENABLED; | 112 | return ApiUsageStateValue.ENABLED; |
111 | } | 113 | } |
@@ -132,6 +134,9 @@ public abstract class BaseApiUsageState { | @@ -132,6 +134,9 @@ public abstract class BaseApiUsageState { | ||
132 | case SMS: | 134 | case SMS: |
133 | apiUsageState.setSmsExecState(value); | 135 | apiUsageState.setSmsExecState(value); |
134 | break; | 136 | break; |
137 | + case ALARM: | ||
138 | + apiUsageState.setAlarmExecState(value); | ||
139 | + break; | ||
135 | } | 140 | } |
136 | return !currentValue.equals(value); | 141 | return !currentValue.equals(value); |
137 | } | 142 | } |
@@ -24,8 +24,9 @@ import org.thingsboard.server.common.data.DataConstants; | @@ -24,8 +24,9 @@ import org.thingsboard.server.common.data.DataConstants; | ||
24 | import org.thingsboard.server.common.data.Device; | 24 | import org.thingsboard.server.common.data.Device; |
25 | import org.thingsboard.server.common.data.DeviceProfile; | 25 | import org.thingsboard.server.common.data.DeviceProfile; |
26 | import org.thingsboard.server.common.data.FirmwareInfo; | 26 | import org.thingsboard.server.common.data.FirmwareInfo; |
27 | -import org.thingsboard.server.common.data.firmware.FirmwareUtil; | ||
28 | import org.thingsboard.server.common.data.firmware.FirmwareType; | 27 | import org.thingsboard.server.common.data.firmware.FirmwareType; |
28 | +import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus; | ||
29 | +import org.thingsboard.server.common.data.firmware.FirmwareUtil; | ||
29 | import org.thingsboard.server.common.data.id.DeviceId; | 30 | import org.thingsboard.server.common.data.id.DeviceId; |
30 | import org.thingsboard.server.common.data.id.FirmwareId; | 31 | import org.thingsboard.server.common.data.id.FirmwareId; |
31 | import org.thingsboard.server.common.data.id.TenantId; | 32 | import org.thingsboard.server.common.data.id.TenantId; |
@@ -66,11 +67,11 @@ import static org.thingsboard.server.common.data.firmware.FirmwareKey.STATE; | @@ -66,11 +67,11 @@ import static org.thingsboard.server.common.data.firmware.FirmwareKey.STATE; | ||
66 | import static org.thingsboard.server.common.data.firmware.FirmwareKey.TITLE; | 67 | import static org.thingsboard.server.common.data.firmware.FirmwareKey.TITLE; |
67 | import static org.thingsboard.server.common.data.firmware.FirmwareKey.TS; | 68 | import static org.thingsboard.server.common.data.firmware.FirmwareKey.TS; |
68 | import static org.thingsboard.server.common.data.firmware.FirmwareKey.VERSION; | 69 | import static org.thingsboard.server.common.data.firmware.FirmwareKey.VERSION; |
70 | +import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE; | ||
71 | +import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE; | ||
69 | import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getAttributeKey; | 72 | import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getAttributeKey; |
70 | import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getTargetTelemetryKey; | 73 | import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getTargetTelemetryKey; |
71 | import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getTelemetryKey; | 74 | import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getTelemetryKey; |
72 | -import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE; | ||
73 | -import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE; | ||
74 | 75 | ||
75 | @Slf4j | 76 | @Slf4j |
76 | @Service | 77 | @Service |
@@ -27,6 +27,9 @@ import org.thingsboard.rule.engine.profile.TbDeviceProfileNode; | @@ -27,6 +27,9 @@ import org.thingsboard.rule.engine.profile.TbDeviceProfileNode; | ||
27 | import org.thingsboard.rule.engine.profile.TbDeviceProfileNodeConfiguration; | 27 | import org.thingsboard.rule.engine.profile.TbDeviceProfileNodeConfiguration; |
28 | import org.thingsboard.server.common.data.EntityView; | 28 | import org.thingsboard.server.common.data.EntityView; |
29 | import org.thingsboard.server.common.data.Tenant; | 29 | import org.thingsboard.server.common.data.Tenant; |
30 | +import org.thingsboard.server.common.data.alarm.Alarm; | ||
31 | +import org.thingsboard.server.common.data.alarm.AlarmInfo; | ||
32 | +import org.thingsboard.server.common.data.alarm.AlarmQuery; | ||
30 | import org.thingsboard.server.common.data.id.EntityViewId; | 33 | import org.thingsboard.server.common.data.id.EntityViewId; |
31 | import org.thingsboard.server.common.data.id.TenantId; | 34 | import org.thingsboard.server.common.data.id.TenantId; |
32 | import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery; | 35 | import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery; |
@@ -34,9 +37,13 @@ import org.thingsboard.server.common.data.kv.ReadTsKvQuery; | @@ -34,9 +37,13 @@ import org.thingsboard.server.common.data.kv.ReadTsKvQuery; | ||
34 | import org.thingsboard.server.common.data.kv.TsKvEntry; | 37 | import org.thingsboard.server.common.data.kv.TsKvEntry; |
35 | import org.thingsboard.server.common.data.page.PageData; | 38 | import org.thingsboard.server.common.data.page.PageData; |
36 | import org.thingsboard.server.common.data.page.PageLink; | 39 | import org.thingsboard.server.common.data.page.PageLink; |
40 | +import org.thingsboard.server.common.data.page.TimePageLink; | ||
37 | import org.thingsboard.server.common.data.rule.RuleChain; | 41 | import org.thingsboard.server.common.data.rule.RuleChain; |
38 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; | 42 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
39 | import org.thingsboard.server.common.data.rule.RuleNode; | 43 | import org.thingsboard.server.common.data.rule.RuleNode; |
44 | +import org.thingsboard.server.dao.alarm.AlarmDao; | ||
45 | +import org.thingsboard.server.dao.alarm.AlarmService; | ||
46 | +import org.thingsboard.server.dao.entity.EntityService; | ||
40 | import org.thingsboard.server.dao.entityview.EntityViewService; | 47 | import org.thingsboard.server.dao.entityview.EntityViewService; |
41 | import org.thingsboard.server.dao.rule.RuleChainService; | 48 | import org.thingsboard.server.dao.rule.RuleChainService; |
42 | import org.thingsboard.server.dao.tenant.TenantService; | 49 | import org.thingsboard.server.dao.tenant.TenantService; |
@@ -72,6 +79,15 @@ public class DefaultDataUpdateService implements DataUpdateService { | @@ -72,6 +79,15 @@ public class DefaultDataUpdateService implements DataUpdateService { | ||
72 | @Autowired | 79 | @Autowired |
73 | private TimeseriesService tsService; | 80 | private TimeseriesService tsService; |
74 | 81 | ||
82 | + @Autowired | ||
83 | + private AlarmService alarmService; | ||
84 | + | ||
85 | + @Autowired | ||
86 | + private EntityService entityService; | ||
87 | + | ||
88 | + @Autowired | ||
89 | + private AlarmDao alarmDao; | ||
90 | + | ||
75 | @Override | 91 | @Override |
76 | public void updateData(String fromVersion) throws Exception { | 92 | public void updateData(String fromVersion) throws Exception { |
77 | switch (fromVersion) { | 93 | switch (fromVersion) { |
@@ -90,14 +106,25 @@ public class DefaultDataUpdateService implements DataUpdateService { | @@ -90,14 +106,25 @@ public class DefaultDataUpdateService implements DataUpdateService { | ||
90 | case "3.2.2": | 106 | case "3.2.2": |
91 | log.info("Updating data from version 3.2.2 to 3.3.0 ..."); | 107 | log.info("Updating data from version 3.2.2 to 3.3.0 ..."); |
92 | tenantsDefaultEdgeRuleChainUpdater.updateEntities(null); | 108 | tenantsDefaultEdgeRuleChainUpdater.updateEntities(null); |
109 | + tenantsAlarmsCustomerUpdater.updateEntities(null); | ||
93 | break; | 110 | break; |
94 | default: | 111 | default: |
95 | throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion); | 112 | throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion); |
96 | } | 113 | } |
97 | } | 114 | } |
98 | 115 | ||
99 | - private PaginatedUpdater<String, Tenant> tenantsDefaultRuleChainUpdater = | ||
100 | - new PaginatedUpdater<String, Tenant>() { | 116 | + private final PaginatedUpdater<String, Tenant> tenantsDefaultRuleChainUpdater = |
117 | + new PaginatedUpdater<>() { | ||
118 | + | ||
119 | + @Override | ||
120 | + protected String getName() { | ||
121 | + return "Tenants default rule chain updater"; | ||
122 | + } | ||
123 | + | ||
124 | + @Override | ||
125 | + protected boolean forceReportTotal() { | ||
126 | + return true; | ||
127 | + } | ||
101 | 128 | ||
102 | @Override | 129 | @Override |
103 | protected PageData<Tenant> findEntities(String region, PageLink pageLink) { | 130 | protected PageData<Tenant> findEntities(String region, PageLink pageLink) { |
@@ -117,8 +144,18 @@ public class DefaultDataUpdateService implements DataUpdateService { | @@ -117,8 +144,18 @@ public class DefaultDataUpdateService implements DataUpdateService { | ||
117 | } | 144 | } |
118 | }; | 145 | }; |
119 | 146 | ||
120 | - private PaginatedUpdater<String, Tenant> tenantsDefaultEdgeRuleChainUpdater = | ||
121 | - new PaginatedUpdater<String, Tenant>() { | 147 | + private final PaginatedUpdater<String, Tenant> tenantsDefaultEdgeRuleChainUpdater = |
148 | + new PaginatedUpdater<>() { | ||
149 | + | ||
150 | + @Override | ||
151 | + protected String getName() { | ||
152 | + return "Tenants default edge rule chain updater"; | ||
153 | + } | ||
154 | + | ||
155 | + @Override | ||
156 | + protected boolean forceReportTotal() { | ||
157 | + return true; | ||
158 | + } | ||
122 | 159 | ||
123 | @Override | 160 | @Override |
124 | protected PageData<Tenant> findEntities(String region, PageLink pageLink) { | 161 | protected PageData<Tenant> findEntities(String region, PageLink pageLink) { |
@@ -138,8 +175,18 @@ public class DefaultDataUpdateService implements DataUpdateService { | @@ -138,8 +175,18 @@ public class DefaultDataUpdateService implements DataUpdateService { | ||
138 | } | 175 | } |
139 | }; | 176 | }; |
140 | 177 | ||
141 | - private PaginatedUpdater<String, Tenant> tenantsRootRuleChainUpdater = | ||
142 | - new PaginatedUpdater<String, Tenant>() { | 178 | + private final PaginatedUpdater<String, Tenant> tenantsRootRuleChainUpdater = |
179 | + new PaginatedUpdater<>() { | ||
180 | + | ||
181 | + @Override | ||
182 | + protected String getName() { | ||
183 | + return "Tenants root rule chain updater"; | ||
184 | + } | ||
185 | + | ||
186 | + @Override | ||
187 | + protected boolean forceReportTotal() { | ||
188 | + return true; | ||
189 | + } | ||
143 | 190 | ||
144 | @Override | 191 | @Override |
145 | protected PageData<Tenant> findEntities(String region, PageLink pageLink) { | 192 | protected PageData<Tenant> findEntities(String region, PageLink pageLink) { |
@@ -192,8 +239,18 @@ public class DefaultDataUpdateService implements DataUpdateService { | @@ -192,8 +239,18 @@ public class DefaultDataUpdateService implements DataUpdateService { | ||
192 | } | 239 | } |
193 | }; | 240 | }; |
194 | 241 | ||
195 | - private PaginatedUpdater<String, Tenant> tenantsEntityViewsUpdater = | ||
196 | - new PaginatedUpdater<String, Tenant>() { | 242 | + private final PaginatedUpdater<String, Tenant> tenantsEntityViewsUpdater = |
243 | + new PaginatedUpdater<>() { | ||
244 | + | ||
245 | + @Override | ||
246 | + protected String getName() { | ||
247 | + return "Tenants entity views updater"; | ||
248 | + } | ||
249 | + | ||
250 | + @Override | ||
251 | + protected boolean forceReportTotal() { | ||
252 | + return true; | ||
253 | + } | ||
197 | 254 | ||
198 | @Override | 255 | @Override |
199 | protected PageData<Tenant> findEntities(String region, PageLink pageLink) { | 256 | protected PageData<Tenant> findEntities(String region, PageLink pageLink) { |
@@ -261,4 +318,48 @@ public class DefaultDataUpdateService implements DataUpdateService { | @@ -261,4 +318,48 @@ public class DefaultDataUpdateService implements DataUpdateService { | ||
261 | }, MoreExecutors.directExecutor()); | 318 | }, MoreExecutors.directExecutor()); |
262 | } | 319 | } |
263 | 320 | ||
321 | + private final PaginatedUpdater<String, Tenant> tenantsAlarmsCustomerUpdater = | ||
322 | + new PaginatedUpdater<>() { | ||
323 | + | ||
324 | + @Override | ||
325 | + protected String getName() { | ||
326 | + return "Tenants alarms customer updater"; | ||
327 | + } | ||
328 | + | ||
329 | + @Override | ||
330 | + protected boolean forceReportTotal() { | ||
331 | + return true; | ||
332 | + } | ||
333 | + | ||
334 | + @Override | ||
335 | + protected PageData<Tenant> findEntities(String region, PageLink pageLink) { | ||
336 | + return tenantService.findTenants(pageLink); | ||
337 | + } | ||
338 | + | ||
339 | + @Override | ||
340 | + protected void updateEntity(Tenant tenant) { | ||
341 | + updateTenantAlarmsCustomer(tenant.getId()); | ||
342 | + } | ||
343 | + }; | ||
344 | + | ||
345 | + private void updateTenantAlarmsCustomer(TenantId tenantId) { | ||
346 | + AlarmQuery alarmQuery = new AlarmQuery(null, new TimePageLink(100), null, null, false); | ||
347 | + PageData<AlarmInfo> alarms = alarmDao.findAlarms(tenantId, alarmQuery); | ||
348 | + boolean hasNext = true; | ||
349 | + while (hasNext) { | ||
350 | + for (Alarm alarm : alarms.getData()) { | ||
351 | + if (alarm.getCustomerId() == null && alarm.getOriginator() != null) { | ||
352 | + alarm.setCustomerId(entityService.fetchEntityCustomerId(tenantId, alarm.getOriginator())); | ||
353 | + alarmDao.save(tenantId, alarm); | ||
354 | + } | ||
355 | + } | ||
356 | + if (alarms.hasNext()) { | ||
357 | + alarmQuery.setPageLink(alarmQuery.getPageLink().nextPageLink()); | ||
358 | + alarms = alarmDao.findAlarms(tenantId, alarmQuery); | ||
359 | + } else { | ||
360 | + hasNext = false; | ||
361 | + } | ||
362 | + } | ||
363 | + } | ||
364 | + | ||
264 | } | 365 | } |
@@ -15,16 +15,20 @@ | @@ -15,16 +15,20 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.service.install.update; | 16 | package org.thingsboard.server.service.install.update; |
17 | 17 | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
18 | import org.thingsboard.server.common.data.SearchTextBased; | 19 | import org.thingsboard.server.common.data.SearchTextBased; |
19 | import org.thingsboard.server.common.data.id.UUIDBased; | 20 | import org.thingsboard.server.common.data.id.UUIDBased; |
20 | import org.thingsboard.server.common.data.page.PageData; | 21 | import org.thingsboard.server.common.data.page.PageData; |
21 | import org.thingsboard.server.common.data.page.PageLink; | 22 | import org.thingsboard.server.common.data.page.PageLink; |
22 | 23 | ||
24 | +@Slf4j | ||
23 | public abstract class PaginatedUpdater<I, D extends SearchTextBased<? extends UUIDBased>> { | 25 | public abstract class PaginatedUpdater<I, D extends SearchTextBased<? extends UUIDBased>> { |
24 | 26 | ||
25 | private static final int DEFAULT_LIMIT = 100; | 27 | private static final int DEFAULT_LIMIT = 100; |
28 | + private int updated = 0; | ||
26 | 29 | ||
27 | public void updateEntities(I id) { | 30 | public void updateEntities(I id) { |
31 | + updated = 0; | ||
28 | PageLink pageLink = new PageLink(DEFAULT_LIMIT); | 32 | PageLink pageLink = new PageLink(DEFAULT_LIMIT); |
29 | boolean hasNext = true; | 33 | boolean hasNext = true; |
30 | while (hasNext) { | 34 | while (hasNext) { |
@@ -32,13 +36,25 @@ public abstract class PaginatedUpdater<I, D extends SearchTextBased<? extends UU | @@ -32,13 +36,25 @@ public abstract class PaginatedUpdater<I, D extends SearchTextBased<? extends UU | ||
32 | for (D entity : entities.getData()) { | 36 | for (D entity : entities.getData()) { |
33 | updateEntity(entity); | 37 | updateEntity(entity); |
34 | } | 38 | } |
39 | + updated += entities.getData().size(); | ||
35 | hasNext = entities.hasNext(); | 40 | hasNext = entities.hasNext(); |
36 | if (hasNext) { | 41 | if (hasNext) { |
42 | + log.info("{}: {} entities updated so far...", getName(), updated); | ||
37 | pageLink = pageLink.nextPageLink(); | 43 | pageLink = pageLink.nextPageLink(); |
44 | + } else { | ||
45 | + if (updated > DEFAULT_LIMIT || forceReportTotal()) { | ||
46 | + log.info("{}: {} total entities updated.", getName(), updated); | ||
47 | + } | ||
38 | } | 48 | } |
39 | } | 49 | } |
40 | } | 50 | } |
41 | 51 | ||
52 | + protected boolean forceReportTotal() { | ||
53 | + return false; | ||
54 | + } | ||
55 | + | ||
56 | + protected abstract String getName(); | ||
57 | + | ||
42 | protected abstract PageData<D> findEntities(I id, PageLink pageLink); | 58 | protected abstract PageData<D> findEntities(I id, PageLink pageLink); |
43 | 59 | ||
44 | protected abstract void updateEntity(D entity); | 60 | protected abstract void updateEntity(D entity); |
@@ -309,6 +309,8 @@ public class DefaultMailService implements MailService { | @@ -309,6 +309,8 @@ public class DefaultMailService implements MailService { | ||
309 | case EMAIL: | 309 | case EMAIL: |
310 | case SMS: | 310 | case SMS: |
311 | return "send"; | 311 | return "send"; |
312 | + case ALARM: | ||
313 | + return "create"; | ||
312 | default: | 314 | default: |
313 | throw new RuntimeException("Not implemented!"); | 315 | throw new RuntimeException("Not implemented!"); |
314 | } | 316 | } |
@@ -327,6 +329,8 @@ public class DefaultMailService implements MailService { | @@ -327,6 +329,8 @@ public class DefaultMailService implements MailService { | ||
327 | case EMAIL: | 329 | case EMAIL: |
328 | case SMS: | 330 | case SMS: |
329 | return "sent"; | 331 | return "sent"; |
332 | + case ALARM: | ||
333 | + return "created"; | ||
330 | default: | 334 | default: |
331 | throw new RuntimeException("Not implemented!"); | 335 | throw new RuntimeException("Not implemented!"); |
332 | } | 336 | } |
@@ -44,6 +44,7 @@ import java.util.Base64; | @@ -44,6 +44,7 @@ import java.util.Base64; | ||
44 | import java.util.Comparator; | 44 | import java.util.Comparator; |
45 | import java.util.List; | 45 | import java.util.List; |
46 | import java.util.stream.Collectors; | 46 | import java.util.stream.Collectors; |
47 | +import java.util.stream.Stream; | ||
47 | 48 | ||
48 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; | 49 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; |
49 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_SEARCH_TEXT; | 50 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_SEARCH_TEXT; |
@@ -130,7 +131,7 @@ public class DefaultTbResourceService implements TbResourceService { | @@ -130,7 +131,7 @@ public class DefaultTbResourceService implements TbResourceService { | ||
130 | List<TbResource> resources = resourceService.findTenantResourcesByResourceTypeAndObjectIds(tenantId, ResourceType.LWM2M_MODEL, | 131 | List<TbResource> resources = resourceService.findTenantResourcesByResourceTypeAndObjectIds(tenantId, ResourceType.LWM2M_MODEL, |
131 | objectIds); | 132 | objectIds); |
132 | return resources.stream() | 133 | return resources.stream() |
133 | - .map(this::toLwM2mObject) | 134 | + .flatMap(s -> Stream.ofNullable(toLwM2mObject(s))) |
134 | .sorted(getComparator(sortProperty, sortOrder)) | 135 | .sorted(getComparator(sortProperty, sortOrder)) |
135 | .collect(Collectors.toList()); | 136 | .collect(Collectors.toList()); |
136 | } | 137 | } |
@@ -141,7 +142,7 @@ public class DefaultTbResourceService implements TbResourceService { | @@ -141,7 +142,7 @@ public class DefaultTbResourceService implements TbResourceService { | ||
141 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | 142 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
142 | PageData<TbResource> resourcePageData = resourceService.findTenantResourcesByResourceTypeAndPageLink(tenantId, ResourceType.LWM2M_MODEL, pageLink); | 143 | PageData<TbResource> resourcePageData = resourceService.findTenantResourcesByResourceTypeAndPageLink(tenantId, ResourceType.LWM2M_MODEL, pageLink); |
143 | return resourcePageData.getData().stream() | 144 | return resourcePageData.getData().stream() |
144 | - .map(this::toLwM2mObject) | 145 | + .flatMap(s -> Stream.ofNullable(toLwM2mObject(s))) |
145 | .sorted(getComparator(sortProperty, sortOrder)) | 146 | .sorted(getComparator(sortProperty, sortOrder)) |
146 | .collect(Collectors.toList()); | 147 | .collect(Collectors.toList()); |
147 | } | 148 | } |
@@ -190,9 +191,14 @@ public class DefaultTbResourceService implements TbResourceService { | @@ -190,9 +191,14 @@ public class DefaultTbResourceService implements TbResourceService { | ||
190 | resources.add(lwM2MResourceObserve); | 191 | resources.add(lwM2MResourceObserve); |
191 | } | 192 | } |
192 | }); | 193 | }); |
193 | - instance.setResources(resources.toArray(LwM2mResourceObserve[]::new)); | ||
194 | - lwM2mObject.setInstances(new LwM2mInstance[]{instance}); | ||
195 | - return lwM2mObject; | 194 | + if (resources.size() > 0) { |
195 | + instance.setResources(resources.toArray(LwM2mResourceObserve[]::new)); | ||
196 | + lwM2mObject.setInstances(new LwM2mInstance[]{instance}); | ||
197 | + return lwM2mObject; | ||
198 | + } | ||
199 | + else { | ||
200 | + return null; | ||
201 | + } | ||
196 | } | 202 | } |
197 | } catch (IOException | InvalidDDFFileException e) { | 203 | } catch (IOException | InvalidDDFFileException e) { |
198 | log.error("Could not parse the XML of objectModel with name [{}]", resource.getSearchText(), e); | 204 | log.error("Could not parse the XML of objectModel with name [{}]", resource.getSearchText(), e); |
@@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j; | @@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j; | ||
23 | import org.checkerframework.checker.nullness.qual.Nullable; | 23 | import org.checkerframework.checker.nullness.qual.Nullable; |
24 | import org.springframework.beans.factory.annotation.Autowired; | 24 | import org.springframework.beans.factory.annotation.Autowired; |
25 | import org.springframework.stereotype.Service; | 25 | import org.springframework.stereotype.Service; |
26 | +import org.thingsboard.server.common.data.ApiUsageRecordKey; | ||
26 | import org.thingsboard.server.common.data.alarm.Alarm; | 27 | import org.thingsboard.server.common.data.alarm.Alarm; |
27 | import org.thingsboard.server.common.data.alarm.AlarmInfo; | 28 | import org.thingsboard.server.common.data.alarm.AlarmInfo; |
28 | import org.thingsboard.server.common.data.alarm.AlarmQuery; | 29 | import org.thingsboard.server.common.data.alarm.AlarmQuery; |
@@ -43,6 +44,8 @@ import org.thingsboard.server.dao.alarm.AlarmOperationResult; | @@ -43,6 +44,8 @@ import org.thingsboard.server.dao.alarm.AlarmOperationResult; | ||
43 | import org.thingsboard.server.dao.alarm.AlarmService; | 44 | import org.thingsboard.server.dao.alarm.AlarmService; |
44 | import org.thingsboard.server.gen.transport.TransportProtos; | 45 | import org.thingsboard.server.gen.transport.TransportProtos; |
45 | import org.thingsboard.server.queue.discovery.PartitionService; | 46 | import org.thingsboard.server.queue.discovery.PartitionService; |
47 | +import org.thingsboard.server.queue.usagestats.TbApiUsageClient; | ||
48 | +import org.thingsboard.server.service.apiusage.TbApiUsageStateService; | ||
46 | import org.thingsboard.server.service.queue.TbClusterService; | 49 | import org.thingsboard.server.service.queue.TbClusterService; |
47 | import org.thingsboard.server.service.subscription.SubscriptionManagerService; | 50 | import org.thingsboard.server.service.subscription.SubscriptionManagerService; |
48 | import org.thingsboard.server.service.subscription.TbSubscriptionUtils; | 51 | import org.thingsboard.server.service.subscription.TbSubscriptionUtils; |
@@ -58,12 +61,18 @@ import java.util.Optional; | @@ -58,12 +61,18 @@ import java.util.Optional; | ||
58 | public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService implements AlarmSubscriptionService { | 61 | public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService implements AlarmSubscriptionService { |
59 | 62 | ||
60 | private final AlarmService alarmService; | 63 | private final AlarmService alarmService; |
64 | + private final TbApiUsageClient apiUsageClient; | ||
65 | + private final TbApiUsageStateService apiUsageStateService; | ||
61 | 66 | ||
62 | public DefaultAlarmSubscriptionService(TbClusterService clusterService, | 67 | public DefaultAlarmSubscriptionService(TbClusterService clusterService, |
63 | PartitionService partitionService, | 68 | PartitionService partitionService, |
64 | - AlarmService alarmService) { | 69 | + AlarmService alarmService, |
70 | + TbApiUsageClient apiUsageClient, | ||
71 | + TbApiUsageStateService apiUsageStateService) { | ||
65 | super(clusterService, partitionService); | 72 | super(clusterService, partitionService); |
66 | this.alarmService = alarmService; | 73 | this.alarmService = alarmService; |
74 | + this.apiUsageClient = apiUsageClient; | ||
75 | + this.apiUsageStateService = apiUsageStateService; | ||
67 | } | 76 | } |
68 | 77 | ||
69 | @Autowired(required = false) | 78 | @Autowired(required = false) |
@@ -78,10 +87,13 @@ public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService | @@ -78,10 +87,13 @@ public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService | ||
78 | 87 | ||
79 | @Override | 88 | @Override |
80 | public Alarm createOrUpdateAlarm(Alarm alarm) { | 89 | public Alarm createOrUpdateAlarm(Alarm alarm) { |
81 | - AlarmOperationResult result = alarmService.createOrUpdateAlarm(alarm); | 90 | + AlarmOperationResult result = alarmService.createOrUpdateAlarm(alarm, apiUsageStateService.getApiUsageState(alarm.getTenantId()).isAlarmCreationEnabled()); |
82 | if (result.isSuccessful()) { | 91 | if (result.isSuccessful()) { |
83 | onAlarmUpdated(result); | 92 | onAlarmUpdated(result); |
84 | } | 93 | } |
94 | + if (result.isCreated()) { | ||
95 | + apiUsageClient.report(alarm.getTenantId(), null, ApiUsageRecordKey.CREATED_ALARMS_COUNT); | ||
96 | + } | ||
85 | return result.getAlarm(); | 97 | return result.getAlarm(); |
86 | } | 98 | } |
87 | 99 | ||
@@ -128,6 +140,11 @@ public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService | @@ -128,6 +140,11 @@ public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService | ||
128 | } | 140 | } |
129 | 141 | ||
130 | @Override | 142 | @Override |
143 | + public ListenableFuture<PageData<AlarmInfo>> findCustomerAlarms(TenantId tenantId, CustomerId customerId, AlarmQuery query) { | ||
144 | + return alarmService.findCustomerAlarms(tenantId, customerId, query); | ||
145 | + } | ||
146 | + | ||
147 | + @Override | ||
131 | public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, AlarmStatus alarmStatus) { | 148 | public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, AlarmStatus alarmStatus) { |
132 | return alarmService.findHighestAlarmSeverity(tenantId, entityId, alarmSearchStatus, alarmStatus); | 149 | return alarmService.findHighestAlarmSeverity(tenantId, entityId, alarmSearchStatus, alarmStatus); |
133 | } | 150 | } |
@@ -26,7 +26,7 @@ | @@ -26,7 +26,7 @@ | ||
26 | </appender> | 26 | </appender> |
27 | 27 | ||
28 | <logger name="org.thingsboard.server" level="INFO" /> | 28 | <logger name="org.thingsboard.server" level="INFO" /> |
29 | - <logger name="org.thingsboard.server.transport.snmp" level="TRACE" /> | 29 | + <logger name="org.thingsboard.server.transport.snmp" level="DEBUG" /> |
30 | 30 | ||
31 | <!-- <logger name="org.thingsboard.server.service.queue" level="TRACE" />--> | 31 | <!-- <logger name="org.thingsboard.server.service.queue" level="TRACE" />--> |
32 | <!-- <logger name="org.thingsboard.server.service.transport" level="TRACE" />--> | 32 | <!-- <logger name="org.thingsboard.server.service.transport" level="TRACE" />--> |
@@ -673,6 +673,8 @@ transport: | @@ -673,6 +673,8 @@ transport: | ||
673 | recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}" | 673 | recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}" |
674 | response_pool_size: "${LWM2M_RESPONSE_POOL_SIZE:100}" | 674 | response_pool_size: "${LWM2M_RESPONSE_POOL_SIZE:100}" |
675 | registered_pool_size: "${LWM2M_REGISTERED_POOL_SIZE:10}" | 675 | registered_pool_size: "${LWM2M_REGISTERED_POOL_SIZE:10}" |
676 | + registration_store_pool_size: "${LWM2M_REGISTRATION_STORE_POOL_SIZE:100}" | ||
677 | + clean_period_in_sec: "${LWM2M_CLEAN_PERIOD_IN_SEC:2}" | ||
676 | update_registered_pool_size: "${LWM2M_UPDATE_REGISTERED_POOL_SIZE:10}" | 678 | update_registered_pool_size: "${LWM2M_UPDATE_REGISTERED_POOL_SIZE:10}" |
677 | un_registered_pool_size: "${LWM2M_UN_REGISTERED_POOL_SIZE:10}" | 679 | un_registered_pool_size: "${LWM2M_UN_REGISTERED_POOL_SIZE:10}" |
678 | log_max_length: "${LWM2M_LOG_MAX_LENGTH:100}" | 680 | log_max_length: "${LWM2M_LOG_MAX_LENGTH:100}" |
@@ -313,7 +313,8 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | @@ -313,7 +313,8 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController | ||
313 | Collections.sort(loadedDeviceProfileInfos, deviceProfileInfoIdComparator); | 313 | Collections.sort(loadedDeviceProfileInfos, deviceProfileInfoIdComparator); |
314 | 314 | ||
315 | List<DeviceProfileInfo> deviceProfileInfos = deviceProfiles.stream().map(deviceProfile -> new DeviceProfileInfo(deviceProfile.getId(), | 315 | List<DeviceProfileInfo> deviceProfileInfos = deviceProfiles.stream().map(deviceProfile -> new DeviceProfileInfo(deviceProfile.getId(), |
316 | - deviceProfile.getName(), deviceProfile.getType(), deviceProfile.getTransportType())).collect(Collectors.toList()); | 316 | + deviceProfile.getName(), deviceProfile.getImage(), deviceProfile.getDefaultDashboardId(), |
317 | + deviceProfile.getType(), deviceProfile.getTransportType())).collect(Collectors.toList()); | ||
317 | 318 | ||
318 | Assert.assertEquals(deviceProfileInfos, loadedDeviceProfileInfos); | 319 | Assert.assertEquals(deviceProfileInfos, loadedDeviceProfileInfos); |
319 | 320 |
@@ -32,7 +32,6 @@ import org.thingsboard.server.common.data.page.PageLink; | @@ -32,7 +32,6 @@ import org.thingsboard.server.common.data.page.PageLink; | ||
32 | import org.thingsboard.server.common.data.security.Authority; | 32 | import org.thingsboard.server.common.data.security.Authority; |
33 | import org.thingsboard.server.controller.AbstractControllerTest; | 33 | import org.thingsboard.server.controller.AbstractControllerTest; |
34 | import org.thingsboard.server.dao.exception.DataValidationException; | 34 | import org.thingsboard.server.dao.exception.DataValidationException; |
35 | -import org.thingsboard.server.dao.service.AbstractServiceTest; | ||
36 | import org.thingsboard.server.dao.service.DaoSqlTest; | 35 | import org.thingsboard.server.dao.service.DaoSqlTest; |
37 | 36 | ||
38 | import java.util.ArrayList; | 37 | import java.util.ArrayList; |
@@ -57,7 +56,7 @@ public class BaseTbResourceServiceTest extends AbstractControllerTest { | @@ -57,7 +56,7 @@ public class BaseTbResourceServiceTest extends AbstractControllerTest { | ||
57 | "<Resources>\n" + | 56 | "<Resources>\n" + |
58 | "<Item ID=\"0\">\n" + | 57 | "<Item ID=\"0\">\n" + |
59 | "<Name>LWM2M</Name>\n" + | 58 | "<Name>LWM2M</Name>\n" + |
60 | - "<Operations></Operations>\n" + | 59 | + "<Operations>RW</Operations>\n" + |
61 | "<MultipleInstances>Single</MultipleInstances>\n" + | 60 | "<MultipleInstances>Single</MultipleInstances>\n" + |
62 | "<Mandatory>Mandatory</Mandatory>\n" + | 61 | "<Mandatory>Mandatory</Mandatory>\n" + |
63 | "<Type>String</Type>\n" + | 62 | "<Type>String</Type>\n" + |
@@ -177,7 +177,7 @@ public class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest { | @@ -177,7 +177,7 @@ public class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest { | ||
177 | executor = Executors.newScheduledThreadPool(10); | 177 | executor = Executors.newScheduledThreadPool(10); |
178 | loginTenantAdmin(); | 178 | loginTenantAdmin(); |
179 | 179 | ||
180 | - String[] resources = new String[]{"0.xml", "1.xml", "2.xml", "3.xml"}; | 180 | + String[] resources = new String[]{"1.xml", "2.xml", "3.xml"}; |
181 | for (String resourceName : resources) { | 181 | for (String resourceName : resources) { |
182 | TbResource lwModel = new TbResource(); | 182 | TbResource lwModel = new TbResource(); |
183 | lwModel.setResourceType(ResourceType.LWM2M_MODEL); | 183 | lwModel.setResourceType(ResourceType.LWM2M_MODEL); |
@@ -26,17 +26,21 @@ import java.util.List; | @@ -26,17 +26,21 @@ import java.util.List; | ||
26 | public class AlarmOperationResult { | 26 | public class AlarmOperationResult { |
27 | private final Alarm alarm; | 27 | private final Alarm alarm; |
28 | private final boolean successful; | 28 | private final boolean successful; |
29 | + private final boolean created; | ||
29 | private final List<EntityId> propagatedEntitiesList; | 30 | private final List<EntityId> propagatedEntitiesList; |
30 | 31 | ||
31 | public AlarmOperationResult(Alarm alarm, boolean successful) { | 32 | public AlarmOperationResult(Alarm alarm, boolean successful) { |
32 | - this.alarm = alarm; | ||
33 | - this.successful = successful; | ||
34 | - this.propagatedEntitiesList = Collections.emptyList(); | 33 | + this(alarm, successful, Collections.emptyList()); |
35 | } | 34 | } |
36 | 35 | ||
37 | public AlarmOperationResult(Alarm alarm, boolean successful, List<EntityId> propagatedEntitiesList) { | 36 | public AlarmOperationResult(Alarm alarm, boolean successful, List<EntityId> propagatedEntitiesList) { |
37 | + this(alarm, successful, false, propagatedEntitiesList); | ||
38 | + } | ||
39 | + | ||
40 | + public AlarmOperationResult(Alarm alarm, boolean successful, boolean created, List<EntityId> propagatedEntitiesList) { | ||
38 | this.alarm = alarm; | 41 | this.alarm = alarm; |
39 | this.successful = successful; | 42 | this.successful = successful; |
43 | + this.created = created; | ||
40 | this.propagatedEntitiesList = propagatedEntitiesList; | 44 | this.propagatedEntitiesList = propagatedEntitiesList; |
41 | } | 45 | } |
42 | } | 46 | } |
@@ -29,7 +29,6 @@ import org.thingsboard.server.common.data.id.EntityId; | @@ -29,7 +29,6 @@ import org.thingsboard.server.common.data.id.EntityId; | ||
29 | import org.thingsboard.server.common.data.id.TenantId; | 29 | import org.thingsboard.server.common.data.id.TenantId; |
30 | import org.thingsboard.server.common.data.page.PageData; | 30 | import org.thingsboard.server.common.data.page.PageData; |
31 | import org.thingsboard.server.common.data.query.AlarmData; | 31 | import org.thingsboard.server.common.data.query.AlarmData; |
32 | -import org.thingsboard.server.common.data.query.AlarmDataPageLink; | ||
33 | import org.thingsboard.server.common.data.query.AlarmDataQuery; | 32 | import org.thingsboard.server.common.data.query.AlarmDataQuery; |
34 | 33 | ||
35 | import java.util.Collection; | 34 | import java.util.Collection; |
@@ -41,6 +40,8 @@ public interface AlarmService { | @@ -41,6 +40,8 @@ public interface AlarmService { | ||
41 | 40 | ||
42 | AlarmOperationResult createOrUpdateAlarm(Alarm alarm); | 41 | AlarmOperationResult createOrUpdateAlarm(Alarm alarm); |
43 | 42 | ||
43 | + AlarmOperationResult createOrUpdateAlarm(Alarm alarm, boolean alarmCreationEnabled); | ||
44 | + | ||
44 | AlarmOperationResult deleteAlarm(TenantId tenantId, AlarmId alarmId); | 45 | AlarmOperationResult deleteAlarm(TenantId tenantId, AlarmId alarmId); |
45 | 46 | ||
46 | ListenableFuture<AlarmOperationResult> ackAlarm(TenantId tenantId, AlarmId alarmId, long ackTs); | 47 | ListenableFuture<AlarmOperationResult> ackAlarm(TenantId tenantId, AlarmId alarmId, long ackTs); |
@@ -53,6 +54,8 @@ public interface AlarmService { | @@ -53,6 +54,8 @@ public interface AlarmService { | ||
53 | 54 | ||
54 | ListenableFuture<PageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query); | 55 | ListenableFuture<PageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query); |
55 | 56 | ||
57 | + ListenableFuture<PageData<AlarmInfo>> findCustomerAlarms(TenantId tenantId, CustomerId customerId, AlarmQuery query); | ||
58 | + | ||
56 | AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, | 59 | AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, |
57 | AlarmStatus alarmStatus); | 60 | AlarmStatus alarmStatus); |
58 | 61 |
@@ -28,6 +28,8 @@ public interface EntityService { | @@ -28,6 +28,8 @@ public interface EntityService { | ||
28 | 28 | ||
29 | ListenableFuture<String> fetchEntityNameAsync(TenantId tenantId, EntityId entityId); | 29 | ListenableFuture<String> fetchEntityNameAsync(TenantId tenantId, EntityId entityId); |
30 | 30 | ||
31 | + CustomerId fetchEntityCustomerId(TenantId tenantId, EntityId entityId); | ||
32 | + | ||
31 | void deleteEntityRelations(TenantId tenantId, EntityId entityId); | 33 | void deleteEntityRelations(TenantId tenantId, EntityId entityId); |
32 | 34 | ||
33 | long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query); | 35 | long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query); |
@@ -23,7 +23,8 @@ public enum ApiFeature { | @@ -23,7 +23,8 @@ public enum ApiFeature { | ||
23 | RE("ruleEngineApiState", "Rule Engine execution"), | 23 | RE("ruleEngineApiState", "Rule Engine execution"), |
24 | JS("jsExecutionApiState", "JavaScript functions execution"), | 24 | JS("jsExecutionApiState", "JavaScript functions execution"), |
25 | EMAIL("emailApiState", "Email messages"), | 25 | EMAIL("emailApiState", "Email messages"), |
26 | - SMS("smsApiState", "SMS messages"); | 26 | + SMS("smsApiState", "SMS messages"), |
27 | + ALARM("alarmApiState", "Created alarms"); | ||
27 | 28 | ||
28 | @Getter | 29 | @Getter |
29 | private final String apiStateKey; | 30 | private final String apiStateKey; |
@@ -25,13 +25,16 @@ public enum ApiUsageRecordKey { | @@ -25,13 +25,16 @@ public enum ApiUsageRecordKey { | ||
25 | RE_EXEC_COUNT(ApiFeature.RE, "ruleEngineExecutionCount", "ruleEngineExecutionLimit"), | 25 | RE_EXEC_COUNT(ApiFeature.RE, "ruleEngineExecutionCount", "ruleEngineExecutionLimit"), |
26 | JS_EXEC_COUNT(ApiFeature.JS, "jsExecutionCount", "jsExecutionLimit"), | 26 | JS_EXEC_COUNT(ApiFeature.JS, "jsExecutionCount", "jsExecutionLimit"), |
27 | EMAIL_EXEC_COUNT(ApiFeature.EMAIL, "emailCount", "emailLimit"), | 27 | EMAIL_EXEC_COUNT(ApiFeature.EMAIL, "emailCount", "emailLimit"), |
28 | - SMS_EXEC_COUNT(ApiFeature.SMS, "smsCount", "smsLimit"); | 28 | + SMS_EXEC_COUNT(ApiFeature.SMS, "smsCount", "smsLimit"), |
29 | + CREATED_ALARMS_COUNT(ApiFeature.ALARM, "createdAlarmsCount", "createdAlarmsLimit"); | ||
30 | + | ||
29 | private static final ApiUsageRecordKey[] JS_RECORD_KEYS = {JS_EXEC_COUNT}; | 31 | private static final ApiUsageRecordKey[] JS_RECORD_KEYS = {JS_EXEC_COUNT}; |
30 | private static final ApiUsageRecordKey[] RE_RECORD_KEYS = {RE_EXEC_COUNT}; | 32 | private static final ApiUsageRecordKey[] RE_RECORD_KEYS = {RE_EXEC_COUNT}; |
31 | private static final ApiUsageRecordKey[] DB_RECORD_KEYS = {STORAGE_DP_COUNT}; | 33 | private static final ApiUsageRecordKey[] DB_RECORD_KEYS = {STORAGE_DP_COUNT}; |
32 | private static final ApiUsageRecordKey[] TRANSPORT_RECORD_KEYS = {TRANSPORT_MSG_COUNT, TRANSPORT_DP_COUNT}; | 34 | private static final ApiUsageRecordKey[] TRANSPORT_RECORD_KEYS = {TRANSPORT_MSG_COUNT, TRANSPORT_DP_COUNT}; |
33 | private static final ApiUsageRecordKey[] EMAIL_RECORD_KEYS = {EMAIL_EXEC_COUNT}; | 35 | private static final ApiUsageRecordKey[] EMAIL_RECORD_KEYS = {EMAIL_EXEC_COUNT}; |
34 | private static final ApiUsageRecordKey[] SMS_RECORD_KEYS = {SMS_EXEC_COUNT}; | 36 | private static final ApiUsageRecordKey[] SMS_RECORD_KEYS = {SMS_EXEC_COUNT}; |
37 | + private static final ApiUsageRecordKey[] ALARM_RECORD_KEYS = {CREATED_ALARMS_COUNT}; | ||
35 | 38 | ||
36 | @Getter | 39 | @Getter |
37 | private final ApiFeature apiFeature; | 40 | private final ApiFeature apiFeature; |
@@ -60,6 +63,8 @@ public enum ApiUsageRecordKey { | @@ -60,6 +63,8 @@ public enum ApiUsageRecordKey { | ||
60 | return EMAIL_RECORD_KEYS; | 63 | return EMAIL_RECORD_KEYS; |
61 | case SMS: | 64 | case SMS: |
62 | return SMS_RECORD_KEYS; | 65 | return SMS_RECORD_KEYS; |
66 | + case ALARM: | ||
67 | + return ALARM_RECORD_KEYS; | ||
63 | default: | 68 | default: |
64 | return new ApiUsageRecordKey[]{}; | 69 | return new ApiUsageRecordKey[]{}; |
65 | } | 70 | } |
@@ -25,34 +25,21 @@ import org.thingsboard.server.common.data.id.ApiUsageStateId; | @@ -25,34 +25,21 @@ import org.thingsboard.server.common.data.id.ApiUsageStateId; | ||
25 | 25 | ||
26 | @ToString | 26 | @ToString |
27 | @EqualsAndHashCode(callSuper = true) | 27 | @EqualsAndHashCode(callSuper = true) |
28 | +@Getter | ||
29 | +@Setter | ||
28 | public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenantId { | 30 | public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenantId { |
29 | 31 | ||
30 | private static final long serialVersionUID = 8250339805336035966L; | 32 | private static final long serialVersionUID = 8250339805336035966L; |
31 | 33 | ||
32 | - @Getter | ||
33 | - @Setter | ||
34 | private TenantId tenantId; | 34 | private TenantId tenantId; |
35 | - @Getter | ||
36 | - @Setter | ||
37 | private EntityId entityId; | 35 | private EntityId entityId; |
38 | - @Getter | ||
39 | - @Setter | ||
40 | private ApiUsageStateValue transportState; | 36 | private ApiUsageStateValue transportState; |
41 | - @Getter | ||
42 | - @Setter | ||
43 | private ApiUsageStateValue dbStorageState; | 37 | private ApiUsageStateValue dbStorageState; |
44 | - @Getter | ||
45 | - @Setter | ||
46 | private ApiUsageStateValue reExecState; | 38 | private ApiUsageStateValue reExecState; |
47 | - @Getter | ||
48 | - @Setter | ||
49 | private ApiUsageStateValue jsExecState; | 39 | private ApiUsageStateValue jsExecState; |
50 | - @Getter | ||
51 | - @Setter | ||
52 | private ApiUsageStateValue emailExecState; | 40 | private ApiUsageStateValue emailExecState; |
53 | - @Getter | ||
54 | - @Setter | ||
55 | private ApiUsageStateValue smsExecState; | 41 | private ApiUsageStateValue smsExecState; |
42 | + private ApiUsageStateValue alarmExecState; | ||
56 | 43 | ||
57 | public ApiUsageState() { | 44 | public ApiUsageState() { |
58 | super(); | 45 | super(); |
@@ -72,6 +59,7 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan | @@ -72,6 +59,7 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan | ||
72 | this.jsExecState = ur.getJsExecState(); | 59 | this.jsExecState = ur.getJsExecState(); |
73 | this.emailExecState = ur.getEmailExecState(); | 60 | this.emailExecState = ur.getEmailExecState(); |
74 | this.smsExecState = ur.getSmsExecState(); | 61 | this.smsExecState = ur.getSmsExecState(); |
62 | + this.alarmExecState = ur.getAlarmExecState(); | ||
75 | } | 63 | } |
76 | 64 | ||
77 | public boolean isTransportEnabled() { | 65 | public boolean isTransportEnabled() { |
@@ -97,4 +85,8 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan | @@ -97,4 +85,8 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan | ||
97 | public boolean isSmsSendEnabled(){ | 85 | public boolean isSmsSendEnabled(){ |
98 | return !ApiUsageStateValue.DISABLED.equals(smsExecState); | 86 | return !ApiUsageStateValue.DISABLED.equals(smsExecState); |
99 | } | 87 | } |
88 | + | ||
89 | + public boolean isAlarmCreationEnabled() { | ||
90 | + return alarmExecState != ApiUsageStateValue.DISABLED; | ||
91 | + } | ||
100 | } | 92 | } |
@@ -30,6 +30,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | @@ -30,6 +30,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | ||
30 | private TenantId tenantId; | 30 | private TenantId tenantId; |
31 | @NoXss | 31 | @NoXss |
32 | private String title; | 32 | private String title; |
33 | + private String image; | ||
33 | @Valid | 34 | @Valid |
34 | private Set<ShortCustomerInfo> assignedCustomers; | 35 | private Set<ShortCustomerInfo> assignedCustomers; |
35 | 36 | ||
@@ -45,6 +46,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | @@ -45,6 +46,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | ||
45 | super(dashboardInfo); | 46 | super(dashboardInfo); |
46 | this.tenantId = dashboardInfo.getTenantId(); | 47 | this.tenantId = dashboardInfo.getTenantId(); |
47 | this.title = dashboardInfo.getTitle(); | 48 | this.title = dashboardInfo.getTitle(); |
49 | + this.image = dashboardInfo.getImage(); | ||
48 | this.assignedCustomers = dashboardInfo.getAssignedCustomers(); | 50 | this.assignedCustomers = dashboardInfo.getAssignedCustomers(); |
49 | } | 51 | } |
50 | 52 | ||
@@ -64,6 +66,14 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | @@ -64,6 +66,14 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | ||
64 | this.title = title; | 66 | this.title = title; |
65 | } | 67 | } |
66 | 68 | ||
69 | + public String getImage() { | ||
70 | + return image; | ||
71 | + } | ||
72 | + | ||
73 | + public void setImage(String image) { | ||
74 | + this.image = image; | ||
75 | + } | ||
76 | + | ||
67 | public Set<ShortCustomerInfo> getAssignedCustomers() { | 77 | public Set<ShortCustomerInfo> getAssignedCustomers() { |
68 | return assignedCustomers; | 78 | return assignedCustomers; |
69 | } | 79 | } |
@@ -92,26 +92,6 @@ public class DataConstants { | @@ -92,26 +92,6 @@ public class DataConstants { | ||
92 | public static final String CLIENT_ID = "clientId"; | 92 | public static final String CLIENT_ID = "clientId"; |
93 | public static final String USERNAME = "username"; | 93 | public static final String USERNAME = "username"; |
94 | public static final String PASSWORD = "password"; | 94 | public static final String PASSWORD = "password"; |
95 | - | ||
96 | -//<<<<<<< HEAD | ||
97 | -//======= | ||
98 | -// //firmware | ||
99 | -// //telemetry | ||
100 | -// public static final String CURRENT_FIRMWARE_TITLE = "current_fw_title"; | ||
101 | -// public static final String CURRENT_FIRMWARE_VERSION = "current_fw_version"; | ||
102 | -// public static final String TARGET_FIRMWARE_TITLE = "target_fw_title"; | ||
103 | -// public static final String TARGET_FIRMWARE_VERSION = "target_fw_version"; | ||
104 | -// public static final String TARGET_FIRMWARE_TS = "target_fw_ts"; | ||
105 | -// public static final String FIRMWARE_STATE = "fw_state"; | ||
106 | -// | ||
107 | -// //attributes | ||
108 | -// //telemetry | ||
109 | -// public static final String FIRMWARE_TITLE = "fw_title"; | ||
110 | -// public static final String FIRMWARE_VERSION = "fw_version"; | ||
111 | -// public static final String FIRMWARE_SIZE = "fw_size"; | ||
112 | -// public static final String FIRMWARE_CHECKSUM = "fw_checksum"; | ||
113 | -// public static final String FIRMWARE_CHECKSUM_ALGORITHM = "fw_checksum_algorithm"; | ||
114 | -//>>>>>>> origin/master | ||
115 | public static final String EDGE_MSG_SOURCE = "edge"; | 95 | public static final String EDGE_MSG_SOURCE = "edge"; |
116 | public static final String MSG_SOURCE_KEY = "source"; | 96 | public static final String MSG_SOURCE_KEY = "source"; |
117 | 97 |
@@ -21,6 +21,7 @@ import lombok.Data; | @@ -21,6 +21,7 @@ import lombok.Data; | ||
21 | import lombok.EqualsAndHashCode; | 21 | import lombok.EqualsAndHashCode; |
22 | import lombok.extern.slf4j.Slf4j; | 22 | import lombok.extern.slf4j.Slf4j; |
23 | import org.thingsboard.server.common.data.device.profile.DeviceProfileData; | 23 | import org.thingsboard.server.common.data.device.profile.DeviceProfileData; |
24 | +import org.thingsboard.server.common.data.id.DashboardId; | ||
24 | import org.thingsboard.server.common.data.id.DeviceProfileId; | 25 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
25 | import org.thingsboard.server.common.data.id.FirmwareId; | 26 | import org.thingsboard.server.common.data.id.FirmwareId; |
26 | import org.thingsboard.server.common.data.id.RuleChainId; | 27 | import org.thingsboard.server.common.data.id.RuleChainId; |
@@ -43,11 +44,13 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | @@ -43,11 +44,13 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | ||
43 | private String name; | 44 | private String name; |
44 | @NoXss | 45 | @NoXss |
45 | private String description; | 46 | private String description; |
47 | + private String image; | ||
46 | private boolean isDefault; | 48 | private boolean isDefault; |
47 | private DeviceProfileType type; | 49 | private DeviceProfileType type; |
48 | private DeviceTransportType transportType; | 50 | private DeviceTransportType transportType; |
49 | private DeviceProfileProvisionType provisionType; | 51 | private DeviceProfileProvisionType provisionType; |
50 | private RuleChainId defaultRuleChainId; | 52 | private RuleChainId defaultRuleChainId; |
53 | + private DashboardId defaultDashboardId; | ||
51 | @NoXss | 54 | @NoXss |
52 | private String defaultQueueName; | 55 | private String defaultQueueName; |
53 | @Valid | 56 | @Valid |
@@ -74,8 +77,10 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | @@ -74,8 +77,10 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | ||
74 | this.tenantId = deviceProfile.getTenantId(); | 77 | this.tenantId = deviceProfile.getTenantId(); |
75 | this.name = deviceProfile.getName(); | 78 | this.name = deviceProfile.getName(); |
76 | this.description = deviceProfile.getDescription(); | 79 | this.description = deviceProfile.getDescription(); |
80 | + this.image = deviceProfile.getImage(); | ||
77 | this.isDefault = deviceProfile.isDefault(); | 81 | this.isDefault = deviceProfile.isDefault(); |
78 | this.defaultRuleChainId = deviceProfile.getDefaultRuleChainId(); | 82 | this.defaultRuleChainId = deviceProfile.getDefaultRuleChainId(); |
83 | + this.defaultDashboardId = deviceProfile.getDefaultDashboardId(); | ||
79 | this.defaultQueueName = deviceProfile.getDefaultQueueName(); | 84 | this.defaultQueueName = deviceProfile.getDefaultQueueName(); |
80 | this.setProfileData(deviceProfile.getProfileData()); | 85 | this.setProfileData(deviceProfile.getProfileData()); |
81 | this.provisionDeviceKey = deviceProfile.getProvisionDeviceKey(); | 86 | this.provisionDeviceKey = deviceProfile.getProvisionDeviceKey(); |
@@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; | @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; | ||
20 | import lombok.EqualsAndHashCode; | 20 | import lombok.EqualsAndHashCode; |
21 | import lombok.ToString; | 21 | import lombok.ToString; |
22 | import lombok.Value; | 22 | import lombok.Value; |
23 | +import org.thingsboard.server.common.data.id.DashboardId; | ||
23 | import org.thingsboard.server.common.data.id.EntityId; | 24 | import org.thingsboard.server.common.data.id.EntityId; |
24 | import org.thingsboard.server.common.data.id.EntityIdFactory; | 25 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
25 | 26 | ||
@@ -30,21 +31,29 @@ import java.util.UUID; | @@ -30,21 +31,29 @@ import java.util.UUID; | ||
30 | @ToString(callSuper = true) | 31 | @ToString(callSuper = true) |
31 | public class DeviceProfileInfo extends EntityInfo { | 32 | public class DeviceProfileInfo extends EntityInfo { |
32 | 33 | ||
34 | + private final String image; | ||
35 | + private final DashboardId defaultDashboardId; | ||
33 | private final DeviceProfileType type; | 36 | private final DeviceProfileType type; |
34 | private final DeviceTransportType transportType; | 37 | private final DeviceTransportType transportType; |
35 | 38 | ||
36 | @JsonCreator | 39 | @JsonCreator |
37 | public DeviceProfileInfo(@JsonProperty("id") EntityId id, | 40 | public DeviceProfileInfo(@JsonProperty("id") EntityId id, |
38 | @JsonProperty("name") String name, | 41 | @JsonProperty("name") String name, |
42 | + @JsonProperty("image") String image, | ||
43 | + @JsonProperty("defaultDashboardId") DashboardId defaultDashboardId, | ||
39 | @JsonProperty("type") DeviceProfileType type, | 44 | @JsonProperty("type") DeviceProfileType type, |
40 | @JsonProperty("transportType") DeviceTransportType transportType) { | 45 | @JsonProperty("transportType") DeviceTransportType transportType) { |
41 | super(id, name); | 46 | super(id, name); |
47 | + this.image = image; | ||
48 | + this.defaultDashboardId = defaultDashboardId; | ||
42 | this.type = type; | 49 | this.type = type; |
43 | this.transportType = transportType; | 50 | this.transportType = transportType; |
44 | } | 51 | } |
45 | 52 | ||
46 | - public DeviceProfileInfo(UUID uuid, String name, DeviceProfileType type, DeviceTransportType transportType) { | 53 | + public DeviceProfileInfo(UUID uuid, String name, String image, UUID defaultDashboardId, DeviceProfileType type, DeviceTransportType transportType) { |
47 | super(EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE_PROFILE, uuid), name); | 54 | super(EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE_PROFILE, uuid), name); |
55 | + this.image = image; | ||
56 | + this.defaultDashboardId = defaultDashboardId != null ? new DashboardId(defaultDashboardId) : null; | ||
48 | this.type = type; | 57 | this.type = type; |
49 | this.transportType = transportType; | 58 | this.transportType = transportType; |
50 | } | 59 | } |
@@ -21,9 +21,11 @@ import lombok.AllArgsConstructor; | @@ -21,9 +21,11 @@ import lombok.AllArgsConstructor; | ||
21 | import lombok.Builder; | 21 | import lombok.Builder; |
22 | import lombok.Data; | 22 | import lombok.Data; |
23 | import org.thingsboard.server.common.data.BaseData; | 23 | import org.thingsboard.server.common.data.BaseData; |
24 | +import org.thingsboard.server.common.data.HasCustomerId; | ||
24 | import org.thingsboard.server.common.data.HasName; | 25 | import org.thingsboard.server.common.data.HasName; |
25 | import org.thingsboard.server.common.data.HasTenantId; | 26 | import org.thingsboard.server.common.data.HasTenantId; |
26 | import org.thingsboard.server.common.data.id.AlarmId; | 27 | import org.thingsboard.server.common.data.id.AlarmId; |
28 | +import org.thingsboard.server.common.data.id.CustomerId; | ||
27 | import org.thingsboard.server.common.data.id.EntityId; | 29 | import org.thingsboard.server.common.data.id.EntityId; |
28 | import org.thingsboard.server.common.data.id.TenantId; | 30 | import org.thingsboard.server.common.data.id.TenantId; |
29 | 31 | ||
@@ -35,9 +37,10 @@ import java.util.List; | @@ -35,9 +37,10 @@ import java.util.List; | ||
35 | @Data | 37 | @Data |
36 | @Builder | 38 | @Builder |
37 | @AllArgsConstructor | 39 | @AllArgsConstructor |
38 | -public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId { | 40 | +public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId, HasCustomerId { |
39 | 41 | ||
40 | private TenantId tenantId; | 42 | private TenantId tenantId; |
43 | + private CustomerId customerId; | ||
41 | private String type; | 44 | private String type; |
42 | private EntityId originator; | 45 | private EntityId originator; |
43 | private AlarmSeverity severity; | 46 | private AlarmSeverity severity; |
@@ -62,6 +65,7 @@ public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId { | @@ -62,6 +65,7 @@ public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId { | ||
62 | super(alarm.getId()); | 65 | super(alarm.getId()); |
63 | this.createdTime = alarm.getCreatedTime(); | 66 | this.createdTime = alarm.getCreatedTime(); |
64 | this.tenantId = alarm.getTenantId(); | 67 | this.tenantId = alarm.getTenantId(); |
68 | + this.customerId = alarm.getCustomerId(); | ||
65 | this.type = alarm.getType(); | 69 | this.type = alarm.getType(); |
66 | this.originator = alarm.getOriginator(); | 70 | this.originator = alarm.getOriginator(); |
67 | this.severity = alarm.getSeverity(); | 71 | this.severity = alarm.getSeverity(); |
@@ -82,7 +82,7 @@ public class MqttTopics { | @@ -82,7 +82,7 @@ public class MqttTopics { | ||
82 | public static final String DEVICE_FIRMWARE_REQUEST_TOPIC_PATTERN = BASE_DEVICE_API_TOPIC_V2 + FIRMWARE + REQUEST + "/" + REQUEST_ID_PATTERN + CHUNK + CHUNK_PATTERN; | 82 | public static final String DEVICE_FIRMWARE_REQUEST_TOPIC_PATTERN = BASE_DEVICE_API_TOPIC_V2 + FIRMWARE + REQUEST + "/" + REQUEST_ID_PATTERN + CHUNK + CHUNK_PATTERN; |
83 | public static final String DEVICE_FIRMWARE_RESPONSES_TOPIC = BASE_DEVICE_API_TOPIC_V2 + FIRMWARE + RESPONSE + "/" + SUB_TOPIC + CHUNK + SUB_TOPIC; | 83 | public static final String DEVICE_FIRMWARE_RESPONSES_TOPIC = BASE_DEVICE_API_TOPIC_V2 + FIRMWARE + RESPONSE + "/" + SUB_TOPIC + CHUNK + SUB_TOPIC; |
84 | public static final String DEVICE_FIRMWARE_ERROR_TOPIC = BASE_DEVICE_API_TOPIC_V2 + FIRMWARE + ERROR; | 84 | public static final String DEVICE_FIRMWARE_ERROR_TOPIC = BASE_DEVICE_API_TOPIC_V2 + FIRMWARE + ERROR; |
85 | - public static final String DEVICE_FIRMWARE_RESPONSES_TOPIC_FORMAT = BASE_DEVICE_API_TOPIC_V2 + "%s" + RESPONSE + "/"+ "%s" + CHUNK + "%d"; | 85 | + public static final String DEVICE_FIRMWARE_RESPONSES_TOPIC_FORMAT = BASE_DEVICE_API_TOPIC_V2 + "/%s" + RESPONSE + "/"+ "%s" + CHUNK + "%d"; |
86 | 86 | ||
87 | public static final String DEVICE_SOFTWARE_REQUEST_TOPIC_PATTERN = BASE_DEVICE_API_TOPIC_V2 + SOFTWARE + REQUEST + "/" + REQUEST_ID_PATTERN + CHUNK + CHUNK_PATTERN; | 87 | public static final String DEVICE_SOFTWARE_REQUEST_TOPIC_PATTERN = BASE_DEVICE_API_TOPIC_V2 + SOFTWARE + REQUEST + "/" + REQUEST_ID_PATTERN + CHUNK + CHUNK_PATTERN; |
88 | public static final String DEVICE_SOFTWARE_RESPONSES_TOPIC = BASE_DEVICE_API_TOPIC_V2 + SOFTWARE + RESPONSE + "/" + SUB_TOPIC + CHUNK + SUB_TOPIC; | 88 | public static final String DEVICE_SOFTWARE_RESPONSES_TOPIC = BASE_DEVICE_API_TOPIC_V2 + SOFTWARE + RESPONSE + "/" + SUB_TOPIC + CHUNK + SUB_TOPIC; |
common/data/src/main/java/org/thingsboard/server/common/data/firmware/FirmwareUpdateStatus.java
renamed from
application/src/main/java/org/thingsboard/server/service/firmware/FirmwareUpdateStatus.java
@@ -13,7 +13,7 @@ | @@ -13,7 +13,7 @@ | ||
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -package org.thingsboard.server.service.firmware; | 16 | +package org.thingsboard.server.common.data.firmware; |
17 | 17 | ||
18 | public enum FirmwareUpdateStatus { | 18 | public enum FirmwareUpdateStatus { |
19 | QUEUED, INITIATED, DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED | 19 | QUEUED, INITIATED, DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED |
@@ -50,6 +50,7 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura | @@ -50,6 +50,7 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura | ||
50 | private int maxRuleNodeExecutionsPerMessage; | 50 | private int maxRuleNodeExecutionsPerMessage; |
51 | private long maxEmails; | 51 | private long maxEmails; |
52 | private long maxSms; | 52 | private long maxSms; |
53 | + private long maxCreatedAlarms; | ||
53 | 54 | ||
54 | private int defaultStorageTtlDays; | 55 | private int defaultStorageTtlDays; |
55 | 56 | ||
@@ -72,6 +73,8 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura | @@ -72,6 +73,8 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura | ||
72 | return maxEmails; | 73 | return maxEmails; |
73 | case SMS_EXEC_COUNT: | 74 | case SMS_EXEC_COUNT: |
74 | return maxSms; | 75 | return maxSms; |
76 | + case CREATED_ALARMS_COUNT: | ||
77 | + return maxCreatedAlarms; | ||
75 | } | 78 | } |
76 | return 0L; | 79 | return 0L; |
77 | } | 80 | } |
@@ -53,6 +53,10 @@ | @@ -53,6 +53,10 @@ | ||
53 | <artifactId>spring-context</artifactId> | 53 | <artifactId>spring-context</artifactId> |
54 | </dependency> | 54 | </dependency> |
55 | <dependency> | 55 | <dependency> |
56 | + <groupId>org.springframework.integration</groupId> | ||
57 | + <artifactId>spring-integration-redis</artifactId> | ||
58 | + </dependency> | ||
59 | + <dependency> | ||
56 | <groupId>org.slf4j</groupId> | 60 | <groupId>org.slf4j</groupId> |
57 | <artifactId>slf4j-api</artifactId> | 61 | <artifactId>slf4j-api</artifactId> |
58 | </dependency> | 62 | </dependency> |
@@ -46,6 +46,7 @@ import java.util.UUID; | @@ -46,6 +46,7 @@ import java.util.UUID; | ||
46 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.BOOTSTRAP_SERVER; | 46 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.BOOTSTRAP_SERVER; |
47 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR; | 47 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR; |
48 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; | 48 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; |
49 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_TELEMETRY; | ||
49 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_SERVER; | 50 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_SERVER; |
50 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SERVERS; | 51 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SERVERS; |
51 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getBootstrapParametersFromThingsboard; | 52 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getBootstrapParametersFromThingsboard; |
@@ -165,13 +166,13 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { | @@ -165,13 +166,13 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { | ||
165 | lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap); | 166 | lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap); |
166 | lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer); | 167 | lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer); |
167 | String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LW2M_INFO, store.getEndpoint()); | 168 | String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LW2M_INFO, store.getEndpoint()); |
168 | - helper.sendParametersOnThingsboardTelemetry(helper.getKvLogyToThingsboard(logMsg), sessionInfo); | 169 | + helper.sendParametersOnThingsboardTelemetry(helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo); |
169 | return lwM2MBootstrapConfig; | 170 | return lwM2MBootstrapConfig; |
170 | } else { | 171 | } else { |
171 | log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndpoint()); | 172 | log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndpoint()); |
172 | log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndpoint()); | 173 | log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndpoint()); |
173 | String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndpoint()); | 174 | String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndpoint()); |
174 | - helper.sendParametersOnThingsboardTelemetry(helper.getKvLogyToThingsboard(logMsg), sessionInfo); | 175 | + helper.sendParametersOnThingsboardTelemetry(helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo); |
175 | return null; | 176 | return null; |
176 | } | 177 | } |
177 | } | 178 | } |
@@ -65,6 +65,14 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { | @@ -65,6 +65,14 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { | ||
65 | private int registeredPoolSize; | 65 | private int registeredPoolSize; |
66 | 66 | ||
67 | @Getter | 67 | @Getter |
68 | + @Value("${transport.lwm2m.registration_store_pool_size:}") | ||
69 | + private int registrationStorePoolSize; | ||
70 | + | ||
71 | + @Getter | ||
72 | + @Value("${transport.lwm2m.clean_period_in_sec:}") | ||
73 | + private int cleanPeriodInSec; | ||
74 | + | ||
75 | + @Getter | ||
68 | @Value("${transport.lwm2m.update_registered_pool_size:}") | 76 | @Value("${transport.lwm2m.update_registered_pool_size:}") |
69 | private int updateRegisteredPoolSize; | 77 | private int updateRegisteredPoolSize; |
70 | 78 |
@@ -23,13 +23,12 @@ import com.google.gson.JsonElement; | @@ -23,13 +23,12 @@ import com.google.gson.JsonElement; | ||
23 | import com.google.gson.JsonObject; | 23 | import com.google.gson.JsonObject; |
24 | import com.google.gson.reflect.TypeToken; | 24 | import com.google.gson.reflect.TypeToken; |
25 | import lombok.extern.slf4j.Slf4j; | 25 | import lombok.extern.slf4j.Slf4j; |
26 | +import org.eclipse.leshan.core.model.ObjectModel; | ||
26 | import org.eclipse.leshan.core.model.ResourceModel; | 27 | import org.eclipse.leshan.core.model.ResourceModel; |
27 | -import org.eclipse.leshan.core.node.LwM2mMultipleResource; | ||
28 | import org.eclipse.leshan.core.node.LwM2mObject; | 28 | import org.eclipse.leshan.core.node.LwM2mObject; |
29 | import org.eclipse.leshan.core.node.LwM2mObjectInstance; | 29 | import org.eclipse.leshan.core.node.LwM2mObjectInstance; |
30 | import org.eclipse.leshan.core.node.LwM2mPath; | 30 | import org.eclipse.leshan.core.node.LwM2mPath; |
31 | import org.eclipse.leshan.core.node.LwM2mResource; | 31 | import org.eclipse.leshan.core.node.LwM2mResource; |
32 | -import org.eclipse.leshan.core.node.LwM2mSingleResource; | ||
33 | import org.eclipse.leshan.core.observation.Observation; | 32 | import org.eclipse.leshan.core.observation.Observation; |
34 | import org.eclipse.leshan.core.request.ContentFormat; | 33 | import org.eclipse.leshan.core.request.ContentFormat; |
35 | import org.eclipse.leshan.core.request.WriteRequest; | 34 | import org.eclipse.leshan.core.request.WriteRequest; |
@@ -56,6 +55,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent; | @@ -56,6 +55,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent; | ||
56 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; | 55 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
57 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | 56 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
58 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; | 57 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; |
58 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper; | ||
59 | import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor; | 59 | import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor; |
60 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; | 60 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
61 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; | 61 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; |
@@ -85,19 +85,21 @@ import java.util.stream.Collectors; | @@ -85,19 +85,21 @@ import java.util.stream.Collectors; | ||
85 | 85 | ||
86 | import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST; | 86 | import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST; |
87 | import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION; | 87 | import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION; |
88 | -import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; | 88 | +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.DOWNLOADED; |
89 | +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.UPDATING; | ||
89 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; | 90 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; |
90 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getValueFromKvProto; | 91 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getValueFromKvProto; |
91 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.CLIENT_NOT_AUTHORIZED; | 92 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.CLIENT_NOT_AUTHORIZED; |
92 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEVICE_ATTRIBUTES_REQUEST; | 93 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEVICE_ATTRIBUTES_REQUEST; |
93 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FR_OBJECT_ID; | ||
94 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FR_PATH_RESOURCE_VER_ID; | 94 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_ID; |
95 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID; | ||
95 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR; | 96 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR; |
96 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; | 97 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; |
98 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_TELEMETRY; | ||
97 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE; | 99 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE; |
98 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_STRATEGY_2; | 100 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_STRATEGY_2; |
99 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper; | ||
100 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER; | 101 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER; |
102 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER_All; | ||
101 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE; | 103 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE; |
102 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE; | 104 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE; |
103 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL; | 105 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL; |
@@ -105,6 +107,9 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L | @@ -105,6 +107,9 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L | ||
105 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.READ; | 107 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.READ; |
106 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_ATTRIBUTES; | 108 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_ATTRIBUTES; |
107 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE; | 109 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE; |
110 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_UPDATE; | ||
111 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_ID; | ||
112 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_RESULT_ID; | ||
108 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertJsonArrayToSet; | 113 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertJsonArrayToSet; |
109 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId; | 114 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId; |
110 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; | 115 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; |
@@ -119,19 +124,20 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -119,19 +124,20 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
119 | 124 | ||
120 | private ExecutorService registrationExecutor; | 125 | private ExecutorService registrationExecutor; |
121 | private ExecutorService updateRegistrationExecutor; | 126 | private ExecutorService updateRegistrationExecutor; |
122 | - private ExecutorService unregistrationExecutor; | 127 | + private ExecutorService unRegistrationExecutor; |
123 | private LwM2mValueConverterImpl converter; | 128 | private LwM2mValueConverterImpl converter; |
124 | 129 | ||
125 | private final TransportService transportService; | 130 | private final TransportService transportService; |
126 | private final LwM2mTransportContext context; | 131 | private final LwM2mTransportContext context; |
127 | - private final LwM2MTransportServerConfig config; | ||
128 | - private final FirmwareDataCache firmwareDataCache; | ||
129 | - private final LwM2mTransportServerHelper helper; | 132 | + public final LwM2MTransportServerConfig config; |
133 | + public final FirmwareDataCache firmwareDataCache; | ||
134 | + public final LwM2mTransportServerHelper helper; | ||
130 | private final LwM2MJsonAdaptor adaptor; | 135 | private final LwM2MJsonAdaptor adaptor; |
131 | private final LwM2mClientContext clientContext; | 136 | private final LwM2mClientContext clientContext; |
132 | private final LwM2mTransportRequest lwM2mTransportRequest; | 137 | private final LwM2mTransportRequest lwM2mTransportRequest; |
133 | private final TbLwM2MDtlsSessionStore sessionStore; | 138 | private final TbLwM2MDtlsSessionStore sessionStore; |
134 | 139 | ||
140 | + | ||
135 | public DefaultLwM2MTransportMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper, | 141 | public DefaultLwM2MTransportMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper, |
136 | LwM2mClientContext clientContext, | 142 | LwM2mClientContext clientContext, |
137 | @Lazy LwM2mTransportRequest lwM2mTransportRequest, | 143 | @Lazy LwM2mTransportRequest lwM2mTransportRequest, |
@@ -153,7 +159,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -153,7 +159,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
153 | this.context.getScheduler().scheduleAtFixedRate(this::reportActivity, new Random().nextInt((int) config.getSessionReportTimeout()), config.getSessionReportTimeout(), TimeUnit.MILLISECONDS); | 159 | this.context.getScheduler().scheduleAtFixedRate(this::reportActivity, new Random().nextInt((int) config.getSessionReportTimeout()), config.getSessionReportTimeout(), TimeUnit.MILLISECONDS); |
154 | this.registrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getRegisteredPoolSize(), "LwM2M registration"); | 160 | this.registrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getRegisteredPoolSize(), "LwM2M registration"); |
155 | this.updateRegistrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getUpdateRegisteredPoolSize(), "LwM2M update registration"); | 161 | this.updateRegistrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getUpdateRegisteredPoolSize(), "LwM2M update registration"); |
156 | - this.unregistrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getUnRegisteredPoolSize(), "LwM2M unregistration"); | 162 | + this.unRegistrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getUnRegisteredPoolSize(), "LwM2M unRegistration"); |
157 | this.converter = LwM2mValueConverterImpl.getInstance(); | 163 | this.converter = LwM2mValueConverterImpl.getInstance(); |
158 | } | 164 | } |
159 | 165 | ||
@@ -184,6 +190,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -184,6 +190,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
184 | transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null); | 190 | transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null); |
185 | transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null); | 191 | transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null); |
186 | this.getInfoFirmwareUpdate(lwM2MClient); | 192 | this.getInfoFirmwareUpdate(lwM2MClient); |
193 | + this.getInfoSoftwareUpdate(lwM2MClient); | ||
187 | this.initLwM2mFromClientValue(registration, lwM2MClient); | 194 | this.initLwM2mFromClientValue(registration, lwM2MClient); |
188 | this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration.getId()); | 195 | this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration.getId()); |
189 | } else { | 196 | } else { |
@@ -216,11 +223,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -216,11 +223,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
216 | request.send(); | 223 | request.send(); |
217 | } | 224 | } |
218 | } | 225 | } |
226 | + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client update Registration", registration.getId()); | ||
219 | } else { | 227 | } else { |
220 | log.error("Client: [{}] updatedReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null); | 228 | log.error("Client: [{}] updatedReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null); |
229 | + this.sendLogsToThingsboard(LOG_LW2M_ERROR + ": Client update Registration", registration.getId()); | ||
221 | } | 230 | } |
222 | } catch (Throwable t) { | 231 | } catch (Throwable t) { |
223 | log.error("[{}] endpoint [{}] error Unable update registration.", registration.getEndpoint(), t); | 232 | log.error("[{}] endpoint [{}] error Unable update registration.", registration.getEndpoint(), t); |
233 | + this.sendLogsToThingsboard(LOG_LW2M_ERROR + String.format(": Client update Registration, %s", t.getMessage()), registration.getId()); | ||
224 | } | 234 | } |
225 | }); | 235 | }); |
226 | } | 236 | } |
@@ -231,13 +241,15 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -231,13 +241,15 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
231 | * !!! Warn: if have not finishing unReg, then this operation will be finished on next Client`s connect | 241 | * !!! Warn: if have not finishing unReg, then this operation will be finished on next Client`s connect |
232 | */ | 242 | */ |
233 | public void unReg(Registration registration, Collection<Observation> observations) { | 243 | public void unReg(Registration registration, Collection<Observation> observations) { |
234 | - unregistrationExecutor.submit(() -> { | 244 | + unRegistrationExecutor.submit(() -> { |
235 | try { | 245 | try { |
236 | - this.setCancelObservations(registration); | 246 | + this.setCancelObservationsAll(registration); |
237 | this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId()); | 247 | this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId()); |
238 | this.closeClientSession(registration); | 248 | this.closeClientSession(registration); |
249 | + ; | ||
239 | } catch (Throwable t) { | 250 | } catch (Throwable t) { |
240 | log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t); | 251 | log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t); |
252 | + this.sendLogsToThingsboard(LOG_LW2M_ERROR + String.format(": Client Unable un Registration, %s", t.getMessage()), registration.getId()); | ||
241 | } | 253 | } |
242 | }); | 254 | }); |
243 | } | 255 | } |
@@ -263,13 +275,18 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -263,13 +275,18 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
263 | //TODO: associate endpointId with device information. | 275 | //TODO: associate endpointId with device information. |
264 | } | 276 | } |
265 | 277 | ||
278 | + /** | ||
279 | + * Cancel observation for All objects for this registration | ||
280 | + */ | ||
266 | @Override | 281 | @Override |
267 | - public void setCancelObservations(Registration registration) { | 282 | + public void setCancelObservationsAll(Registration registration) { |
268 | if (registration != null) { | 283 | if (registration != null) { |
269 | - Set<Observation> observations = context.getServer().getObservationService().getObservations(registration); | ||
270 | - observations.forEach(observation -> lwM2mTransportRequest.sendAllRequest(registration, | ||
271 | - convertPathFromObjectIdToIdVer(observation.getPath().toString(), registration), OBSERVE_CANCEL, | ||
272 | - null, null, this.config.getTimeout(), null)); | 284 | + lwM2mTransportRequest.sendAllRequest(registration, null, OBSERVE_CANCEL, |
285 | + null, null, this.config.getTimeout(), null); | ||
286 | +// Set<Observation> observations = context.getServer().getObservationService().getObservations(registration); | ||
287 | +// observations.forEach(observation -> lwM2mTransportRequest.sendAllRequest(registration, | ||
288 | +// convertPathFromObjectIdToIdVer(observation.getPath().toString(), registration), OBSERVE_CANCEL, | ||
289 | +// null, null, this.config.getTimeout(), null)); | ||
273 | } | 290 | } |
274 | } | 291 | } |
275 | 292 | ||
@@ -283,34 +300,43 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -283,34 +300,43 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
283 | @Override | 300 | @Override |
284 | public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) { | 301 | public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) { |
285 | if (response.getContent() != null) { | 302 | if (response.getContent() != null) { |
286 | - Object value = null; | ||
287 | - if (response.getContent() instanceof LwM2mObject) { | ||
288 | - LwM2mObject lwM2mObject = (LwM2mObject) response.getContent(); | ||
289 | - if (rpcRequest != null) { | ||
290 | - value = lwM2mObject.toString(); | 303 | + LwM2mClient lwM2MClient = clientContext.getOrRegister(registration); |
304 | + ObjectModel objectModelVersion = lwM2MClient.getObjectModel(path, this.config.getModelProvider()); | ||
305 | + if (objectModelVersion != null) { | ||
306 | + if (response.getContent() instanceof LwM2mObject) { | ||
307 | + LwM2mObject lwM2mObject = (LwM2mObject) response.getContent(); | ||
308 | + this.updateObjectResourceValue(registration, lwM2mObject, path); | ||
309 | + } else if (response.getContent() instanceof LwM2mObjectInstance) { | ||
310 | + LwM2mObjectInstance lwM2mObjectInstance = (LwM2mObjectInstance) response.getContent(); | ||
311 | + this.updateObjectInstanceResourceValue(registration, lwM2mObjectInstance, path); | ||
312 | + } else if (response.getContent() instanceof LwM2mResource) { | ||
313 | + LwM2mResource lwM2mResource = (LwM2mResource) response.getContent(); | ||
314 | + this.updateResourcesValue(registration, lwM2mResource, path); | ||
291 | } | 315 | } |
292 | - this.updateObjectResourceValue(registration, lwM2mObject, path); | ||
293 | - } else if (response.getContent() instanceof LwM2mObjectInstance) { | ||
294 | - LwM2mObjectInstance lwM2mObjectInstance = (LwM2mObjectInstance) response.getContent(); | ||
295 | - if (rpcRequest != null) { | ||
296 | - value = lwM2mObjectInstance.toString(); | ||
297 | - } | ||
298 | - this.updateObjectInstanceResourceValue(registration, lwM2mObjectInstance, path); | ||
299 | - } else if (response.getContent() instanceof LwM2mResource) { | ||
300 | - LwM2mResource lwM2mResource = (LwM2mResource) response.getContent(); | ||
301 | - if (rpcRequest != null) { | ||
302 | - value = lwM2mResource.isMultiInstances() ? ((LwM2mMultipleResource) lwM2mResource).toString() : | ||
303 | - ((LwM2mSingleResource) lwM2mResource).toString(); | ||
304 | - } | ||
305 | - this.updateResourcesValue(registration, lwM2mResource, path); | ||
306 | } | 316 | } |
307 | if (rpcRequest != null) { | 317 | if (rpcRequest != null) { |
308 | - rpcRequest.setValueMsg(String.format("%s", value)); | ||
309 | - this.sentRpcRequest(rpcRequest, response.getCode().getName(), (String) value, LOG_LW2M_VALUE); | 318 | + this.sendRpcRequestAfterReadResponse(registration, lwM2MClient, path, response, rpcRequest); |
310 | } | 319 | } |
311 | } | 320 | } |
312 | } | 321 | } |
313 | 322 | ||
323 | + private void sendRpcRequestAfterReadResponse(Registration registration, LwM2mClient lwM2MClient, String pathIdVer, ReadResponse response, | ||
324 | + Lwm2mClientRpcRequest rpcRequest) { | ||
325 | + Object value = null; | ||
326 | + if (response.getContent() instanceof LwM2mObject) { | ||
327 | + value = lwM2MClient.objectToString((LwM2mObject) response.getContent(), this.converter, pathIdVer); | ||
328 | + } else if (response.getContent() instanceof LwM2mObjectInstance) { | ||
329 | + value = lwM2MClient.instanceToString((LwM2mObjectInstance) response.getContent(), this.converter, pathIdVer); | ||
330 | + } else if (response.getContent() instanceof LwM2mResource) { | ||
331 | + value = lwM2MClient.resourceToString((LwM2mResource) response.getContent(), this.converter, pathIdVer); | ||
332 | + } | ||
333 | + String msg = String.format("%s: type operation %s path - %s value - %s", LOG_LW2M_INFO, | ||
334 | + READ, pathIdVer, value); | ||
335 | + this.sendLogsToThingsboard(msg, registration.getId()); | ||
336 | + rpcRequest.setValueMsg(String.format("%s", value)); | ||
337 | + this.sentRpcRequest(rpcRequest, response.getCode().getName(), (String) value, LOG_LW2M_VALUE); | ||
338 | + } | ||
339 | + | ||
314 | /** | 340 | /** |
315 | * Update - send request in change value resources in Client | 341 | * Update - send request in change value resources in Client |
316 | * 1. FirmwareUpdate: | 342 | * 1. FirmwareUpdate: |
@@ -330,9 +356,16 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -330,9 +356,16 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
330 | String pathName = tsKvProto.getKv().getKey(); | 356 | String pathName = tsKvProto.getKv().getKey(); |
331 | String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName); | 357 | String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName); |
332 | Object valueNew = getValueFromKvProto(tsKvProto.getKv()); | 358 | Object valueNew = getValueFromKvProto(tsKvProto.getKv()); |
333 | - //TODO: react on change of the firmware name. | ||
334 | - if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) { | 359 | + if ((FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) |
360 | + && (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion()))) | ||
361 | + || (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.TITLE).equals(pathName) | ||
362 | + && (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentTitle())))) { | ||
335 | this.getInfoFirmwareUpdate(lwM2MClient); | 363 | this.getInfoFirmwareUpdate(lwM2MClient); |
364 | + } else if ((FirmwareUtil.getAttributeKey(FirmwareType.SOFTWARE, FirmwareKey.VERSION).equals(pathName) | ||
365 | + && (!valueNew.equals(lwM2MClient.getSwUpdate().getCurrentVersion()))) | ||
366 | + || (FirmwareUtil.getAttributeKey(FirmwareType.SOFTWARE, FirmwareKey.TITLE).equals(pathName) | ||
367 | + && (!valueNew.equals(lwM2MClient.getSwUpdate().getCurrentTitle())))) { | ||
368 | + this.getInfoSoftwareUpdate(lwM2MClient); | ||
336 | } | 369 | } |
337 | if (pathIdVer != null) { | 370 | if (pathIdVer != null) { |
338 | ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.config | 371 | ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.config |
@@ -357,8 +390,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -357,8 +390,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
357 | msg.getSharedUpdatedList().forEach(tsKvProto -> { | 390 | msg.getSharedUpdatedList().forEach(tsKvProto -> { |
358 | String pathName = tsKvProto.getKv().getKey(); | 391 | String pathName = tsKvProto.getKv().getKey(); |
359 | Object valueNew = getValueFromKvProto(tsKvProto.getKv()); | 392 | Object valueNew = getValueFromKvProto(tsKvProto.getKv()); |
360 | - if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) { | ||
361 | - lwM2MClient.getFrUpdate().setCurrentFwVersion((String) valueNew); | 393 | + if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion())) { |
394 | + lwM2MClient.getFwUpdate().setCurrentVersion((String) valueNew); | ||
362 | } | 395 | } |
363 | }); | 396 | }); |
364 | log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo); | 397 | log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo); |
@@ -402,12 +435,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -402,12 +435,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
402 | } | 435 | } |
403 | 436 | ||
404 | @Override | 437 | @Override |
405 | - public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRequest, SessionInfoProto sessionInfo) { | 438 | + public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRpcRequestMsg, SessionInfoProto sessionInfo) { |
439 | + log.warn("4) RPC-OK finish to [{}]", toDeviceRpcRequestMsg); | ||
406 | Lwm2mClientRpcRequest lwm2mClientRpcRequest = null; | 440 | Lwm2mClientRpcRequest lwm2mClientRpcRequest = null; |
407 | try { | 441 | try { |
408 | - log.info("[{}] toDeviceRpcRequest", toDeviceRequest); | ||
409 | Registration registration = clientContext.getClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).getRegistration(); | 442 | Registration registration = clientContext.getClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).getRegistration(); |
410 | - lwm2mClientRpcRequest = this.getDeviceRpcRequest(toDeviceRequest, sessionInfo, registration); | 443 | + lwm2mClientRpcRequest = this.getDeviceRpcRequest(toDeviceRpcRequestMsg, sessionInfo, registration); |
411 | if (lwm2mClientRpcRequest.getErrorMsg() != null) { | 444 | if (lwm2mClientRpcRequest.getErrorMsg() != null) { |
412 | lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name()); | 445 | lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name()); |
413 | this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo); | 446 | this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo); |
@@ -459,12 +492,27 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -459,12 +492,27 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
459 | lwm2mClientRpcRequest.setValue(rpcRequest.get(lwm2mClientRpcRequest.valueKey).getAsString()); | 492 | lwm2mClientRpcRequest.setValue(rpcRequest.get(lwm2mClientRpcRequest.valueKey).getAsString()); |
460 | } | 493 | } |
461 | if (rpcRequest.has(lwm2mClientRpcRequest.paramsKey) && rpcRequest.get(lwm2mClientRpcRequest.paramsKey).isJsonObject()) { | 494 | if (rpcRequest.has(lwm2mClientRpcRequest.paramsKey) && rpcRequest.get(lwm2mClientRpcRequest.paramsKey).isJsonObject()) { |
462 | - lwm2mClientRpcRequest.setParams(new Gson().fromJson(rpcRequest.get(lwm2mClientRpcRequest.paramsKey) | 495 | + ConcurrentHashMap<String, Object> params = new Gson().fromJson(rpcRequest.get(lwm2mClientRpcRequest.paramsKey) |
496 | + .getAsJsonObject().toString(), new TypeToken<ConcurrentHashMap<String, Object>>() { | ||
497 | + }.getType()); | ||
498 | + if (WRITE_UPDATE == lwm2mClientRpcRequest.getTypeOper()) { | ||
499 | + ConcurrentHashMap<String, Object> paramsResourceId = convertParamsToResourceId(params, sessionInfo); | ||
500 | + if (paramsResourceId.size() > 0) { | ||
501 | + lwm2mClientRpcRequest.setParams(paramsResourceId); | ||
502 | + } | ||
503 | + } else { | ||
504 | + lwm2mClientRpcRequest.setParams(params); | ||
505 | + } | ||
506 | + } else if (rpcRequest.has(lwm2mClientRpcRequest.paramsKey) && rpcRequest.get(lwm2mClientRpcRequest.paramsKey).isJsonArray()) { | ||
507 | + new Gson().fromJson(rpcRequest.get(lwm2mClientRpcRequest.paramsKey) | ||
463 | .getAsJsonObject().toString(), new TypeToken<ConcurrentHashMap<String, Object>>() { | 508 | .getAsJsonObject().toString(), new TypeToken<ConcurrentHashMap<String, Object>>() { |
464 | - }.getType())); | 509 | + }.getType()); |
465 | } | 510 | } |
466 | lwm2mClientRpcRequest.setSessionInfo(sessionInfo); | 511 | lwm2mClientRpcRequest.setSessionInfo(sessionInfo); |
467 | - if (OBSERVE_READ_ALL != lwm2mClientRpcRequest.getTypeOper() && lwm2mClientRpcRequest.getTargetIdVer() == null) { | 512 | + if (!(OBSERVE_READ_ALL == lwm2mClientRpcRequest.getTypeOper() |
513 | + || DISCOVER_All == lwm2mClientRpcRequest.getTypeOper() | ||
514 | + || OBSERVE_CANCEL == lwm2mClientRpcRequest.getTypeOper()) | ||
515 | + && lwm2mClientRpcRequest.getTargetIdVer() == null) { | ||
468 | lwm2mClientRpcRequest.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " + | 516 | lwm2mClientRpcRequest.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " + |
469 | lwm2mClientRpcRequest.keyNameKey + " is null or bad format"); | 517 | lwm2mClientRpcRequest.keyNameKey + " is null or bad format"); |
470 | } | 518 | } |
@@ -488,6 +536,21 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -488,6 +536,21 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
488 | return lwm2mClientRpcRequest; | 536 | return lwm2mClientRpcRequest; |
489 | } | 537 | } |
490 | 538 | ||
539 | + private ConcurrentHashMap<String, Object> convertParamsToResourceId(ConcurrentHashMap<String, Object> params, | ||
540 | + SessionInfoProto sessionInfo) { | ||
541 | + ConcurrentHashMap<String, Object> paramsIdVer = new ConcurrentHashMap<>(); | ||
542 | + params.forEach((k, v) -> { | ||
543 | + String targetIdVer = this.getPresentPathIntoProfile(sessionInfo, k); | ||
544 | + if (targetIdVer != null) { | ||
545 | + LwM2mPath targetId = new LwM2mPath(convertPathFromIdVerToObjectId(targetIdVer)); | ||
546 | + if (targetId.isResource()) { | ||
547 | + paramsIdVer.put(String.valueOf(targetId.getResourceId()), v); | ||
548 | + } | ||
549 | + } | ||
550 | + }); | ||
551 | + return paramsIdVer; | ||
552 | + } | ||
553 | + | ||
491 | public void sentRpcRequest(Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) { | 554 | public void sentRpcRequest(Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) { |
492 | rpcRequest.setResponseCode(requestCode); | 555 | rpcRequest.setResponseCode(requestCode); |
493 | if (LOG_LW2M_ERROR.equals(typeMsg)) { | 556 | if (LOG_LW2M_ERROR.equals(typeMsg)) { |
@@ -561,7 +624,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -561,7 +624,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
561 | */ | 624 | */ |
562 | @Override | 625 | @Override |
563 | public void onAwakeDev(Registration registration) { | 626 | public void onAwakeDev(Registration registration) { |
564 | - log.info("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint()); | 627 | + log.trace("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint()); |
565 | this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is awake!", registration.getId()); | 628 | this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is awake!", registration.getId()); |
566 | //TODO: associate endpointId with device information. | 629 | //TODO: associate endpointId with device information. |
567 | } | 630 | } |
@@ -577,7 +640,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -577,7 +640,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
577 | if (logMsg.length() > 1024) { | 640 | if (logMsg.length() > 1024) { |
578 | logMsg = logMsg.substring(0, 1024); | 641 | logMsg = logMsg.substring(0, 1024); |
579 | } | 642 | } |
580 | - this.helper.sendParametersOnThingsboardTelemetry(this.helper.getKvLogyToThingsboard(logMsg), sessionInfo); | 643 | + this.helper.sendParametersOnThingsboardTelemetry(this.helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo); |
581 | } | 644 | } |
582 | } | 645 | } |
583 | 646 | ||
@@ -614,7 +677,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -614,7 +677,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
614 | /** | 677 | /** |
615 | * @param registration - | 678 | * @param registration - |
616 | * @param lwM2mObject - | 679 | * @param lwM2mObject - |
617 | - * @param pathIdVer - | 680 | + * @param pathIdVer - |
618 | */ | 681 | */ |
619 | private void updateObjectResourceValue(Registration registration, LwM2mObject lwM2mObject, String pathIdVer) { | 682 | private void updateObjectResourceValue(Registration registration, LwM2mObject lwM2mObject, String pathIdVer) { |
620 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)); | 683 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)); |
@@ -651,18 +714,63 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -651,18 +714,63 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
651 | private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) { | 714 | private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) { |
652 | LwM2mClient lwM2MClient = clientContext.getOrRegister(registration); | 715 | LwM2mClient lwM2MClient = clientContext.getOrRegister(registration); |
653 | if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.config.getModelProvider())) { | 716 | if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.config.getModelProvider())) { |
654 | - if (FR_PATH_RESOURCE_VER_ID.equals(convertPathFromIdVerToObjectId(path)) && | ||
655 | - lwM2MClient.getFrUpdate().getCurrentFwVersion() != null | ||
656 | - && !lwM2MClient.getFrUpdate().getCurrentFwVersion().equals(lwM2MClient.getFrUpdate().getClientFwVersion()) | ||
657 | - && lwM2MClient.isUpdateFw()) { | ||
658 | - | ||
659 | - /** version != null | ||
660 | - * set setClient_fw_version = value | ||
661 | - **/ | ||
662 | - lwM2MClient.setUpdateFw(false); | ||
663 | - lwM2MClient.getFrUpdate().setClientFwVersion(lwM2mResource.getValue().toString()); | ||
664 | - log.warn("updateFirmwareClient3"); | ||
665 | - this.updateFirmwareClient(lwM2MClient); | 717 | + /** version != null |
718 | + * set setClient_fw_info... = value | ||
719 | + **/ | ||
720 | + if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { | ||
721 | + lwM2MClient.getFwUpdate().initReadValue(this, lwM2mTransportRequest, path); | ||
722 | + } | ||
723 | + if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { | ||
724 | + lwM2MClient.getSwUpdate().initReadValue(this, lwM2mTransportRequest, path); | ||
725 | + } | ||
726 | + | ||
727 | + /** | ||
728 | + * Before operation Execute (FwUpdate) inspection Update Result : | ||
729 | + * - after finished operation Write result: success (FwUpdate): fw_state = DOWNLOADED | ||
730 | + * - before start operation Execute (FwUpdate) Update Result = 0 - Initial value | ||
731 | + * - start Execute (FwUpdate) | ||
732 | + * After finished operation Execute (FwUpdate) inspection Update Result : | ||
733 | + * - after start operation Execute (FwUpdate): fw_state = UPDATING | ||
734 | + * - after success finished operation Execute (FwUpdate) Update Result == 1 ("Firmware updated successfully") | ||
735 | + * - finished operation Execute (FwUpdate) | ||
736 | + */ | ||
737 | + if (lwM2MClient.getFwUpdate() != null | ||
738 | + && (convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) { | ||
739 | + if (DOWNLOADED.name().equals(lwM2MClient.getFwUpdate().getStateUpdate()) | ||
740 | + && lwM2MClient.getFwUpdate().conditionalFwExecuteStart()) { | ||
741 | + lwM2MClient.getFwUpdate().executeFwSwWare(this, lwM2mTransportRequest); | ||
742 | + } else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate()) | ||
743 | + && lwM2MClient.getFwUpdate().conditionalFwExecuteAfterSuccess()) { | ||
744 | + lwM2MClient.getFwUpdate().finishFwSwUpdate(this, true); | ||
745 | + } else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate()) | ||
746 | + && lwM2MClient.getFwUpdate().conditionalFwExecuteAfterError()) { | ||
747 | + lwM2MClient.getFwUpdate().finishFwSwUpdate(this, false); | ||
748 | + } | ||
749 | + } | ||
750 | + | ||
751 | + /** | ||
752 | + * Before operation Execute (SwUpdate) inspection Update Result : | ||
753 | + * - after finished operation Write result: success (SwUpdate): fw_state = DOWNLOADED | ||
754 | + * - before operation Execute (SwUpdate) Update Result = 3 - Successfully Downloaded and package integrity verified | ||
755 | + * - start Execute (SwUpdate) | ||
756 | + * After finished operation Execute (SwUpdate) inspection Update Result : | ||
757 | + * - after start operation Execute (SwUpdate): fw_state = UPDATING | ||
758 | + * - after success finished operation Execute (SwUpdate) Update Result == 2 "Software successfully installed."" | ||
759 | + * - after success finished operation Execute (SwUpdate) Update Result == 2 "Software successfully installed."" | ||
760 | + * - finished operation Execute (SwUpdate) | ||
761 | + */ | ||
762 | + if (lwM2MClient.getSwUpdate() != null | ||
763 | + && (convertPathFromObjectIdToIdVer(SW_RESULT_ID, registration).equals(path))) { | ||
764 | + if (DOWNLOADED.name().equals(lwM2MClient.getSwUpdate().getStateUpdate()) | ||
765 | + && lwM2MClient.getSwUpdate().conditionalSwUpdateExecute()) { | ||
766 | + lwM2MClient.getSwUpdate().executeFwSwWare(this, lwM2mTransportRequest); | ||
767 | + } else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate()) | ||
768 | + && lwM2MClient.getSwUpdate().conditionalSwExecuteAfterSuccess()) { | ||
769 | + lwM2MClient.getSwUpdate().finishFwSwUpdate(this, true); | ||
770 | + } else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate()) | ||
771 | + && lwM2MClient.getSwUpdate().conditionalSwExecuteAfterError()) { | ||
772 | + lwM2MClient.getSwUpdate().finishFwSwUpdate(this, false); | ||
773 | + } | ||
666 | } | 774 | } |
667 | Set<String> paths = new HashSet<>(); | 775 | Set<String> paths = new HashSet<>(); |
668 | paths.add(path); | 776 | paths.add(path); |
@@ -684,7 +792,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -684,7 +792,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
684 | */ | 792 | */ |
685 | private void updateAttrTelemetry(Registration registration, Set<String> paths) { | 793 | private void updateAttrTelemetry(Registration registration, Set<String> paths) { |
686 | try { | 794 | try { |
687 | - ResultsAddKeyValueProto results = getParametersFromProfile(registration, paths); | 795 | + ResultsAddKeyValueProto results = this.getParametersFromProfile(registration, paths); |
688 | SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(registration); | 796 | SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(registration); |
689 | if (results != null && sessionInfo != null) { | 797 | if (results != null && sessionInfo != null) { |
690 | if (results.getResultAttributes().size() > 0) { | 798 | if (results.getResultAttributes().size() > 0) { |
@@ -818,7 +926,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -818,7 +926,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
818 | Object finalvalueKvProto = valueKvProto; | 926 | Object finalvalueKvProto = valueKvProto; |
819 | Gson gson = new GsonBuilder().create(); | 927 | Gson gson = new GsonBuilder().create(); |
820 | resourceValue.getValues().forEach((k, v) -> { | 928 | resourceValue.getValues().forEach((k, v) -> { |
821 | - Object val = this.converter.convertValue(resourceValue.getValue(), currentType, expectedType, | 929 | + Object val = this.converter.convertValue(v, currentType, expectedType, |
822 | new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); | 930 | new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); |
823 | JsonElement element = gson.toJsonTree(val, val.getClass()); | 931 | JsonElement element = gson.toJsonTree(val, val.getClass()); |
824 | ((JsonObject) finalvalueKvProto).add(String.valueOf(k), element); | 932 | ((JsonObject) finalvalueKvProto).add(String.valueOf(k), element); |
@@ -910,7 +1018,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -910,7 +1018,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
910 | */ | 1018 | */ |
911 | private void onDeviceProfileUpdate(Set<String> registrationIds, DeviceProfile deviceProfile) { | 1019 | private void onDeviceProfileUpdate(Set<String> registrationIds, DeviceProfile deviceProfile) { |
912 | LwM2mClientProfile lwM2MClientProfileOld = clientContext.getProfiles().get(deviceProfile.getUuidId()).clone(); | 1020 | LwM2mClientProfile lwM2MClientProfileOld = clientContext.getProfiles().get(deviceProfile.getUuidId()).clone(); |
913 | - if (clientContext.toClientProfile(deviceProfile) != null) { | 1021 | + if (clientContext.profileUpdate(deviceProfile) != null) { |
914 | // #1 | 1022 | // #1 |
915 | JsonArray attributeOld = lwM2MClientProfileOld.getPostAttributeProfile(); | 1023 | JsonArray attributeOld = lwM2MClientProfileOld.getPostAttributeProfile(); |
916 | Set<String> attributeSetOld = convertJsonArrayToSet(attributeOld); | 1024 | Set<String> attributeSetOld = convertJsonArrayToSet(attributeOld); |
@@ -920,7 +1028,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -920,7 +1028,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
920 | JsonObject keyNameOld = lwM2MClientProfileOld.getPostKeyNameProfile(); | 1028 | JsonObject keyNameOld = lwM2MClientProfileOld.getPostKeyNameProfile(); |
921 | JsonObject attributeLwm2mOld = lwM2MClientProfileOld.getPostAttributeLwm2mProfile(); | 1029 | JsonObject attributeLwm2mOld = lwM2MClientProfileOld.getPostAttributeLwm2mProfile(); |
922 | 1030 | ||
923 | - LwM2mClientProfile lwM2MClientProfileNew = clientContext.getProfiles().get(deviceProfile.getUuidId()); | 1031 | + LwM2mClientProfile lwM2MClientProfileNew = clientContext.getProfiles().get(deviceProfile.getUuidId()).clone(); |
924 | JsonArray attributeNew = lwM2MClientProfileNew.getPostAttributeProfile(); | 1032 | JsonArray attributeNew = lwM2MClientProfileNew.getPostAttributeProfile(); |
925 | Set<String> attributeSetNew = convertJsonArrayToSet(attributeNew); | 1033 | Set<String> attributeSetNew = convertJsonArrayToSet(attributeNew); |
926 | JsonArray telemetryNew = lwM2MClientProfileNew.getPostTelemetryProfile(); | 1034 | JsonArray telemetryNew = lwM2MClientProfileNew.getPostTelemetryProfile(); |
@@ -968,8 +1076,6 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -968,8 +1076,6 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
968 | registrationIds.forEach(registrationId -> { | 1076 | registrationIds.forEach(registrationId -> { |
969 | Registration registration = clientContext.getRegistration(registrationId); | 1077 | Registration registration = clientContext.getRegistration(registrationId); |
970 | this.readObserveFromProfile(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ); | 1078 | this.readObserveFromProfile(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ); |
971 | - // send attr/telemetry to tingsboard for new path | ||
972 | - this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd()); | ||
973 | }); | 1079 | }); |
974 | } | 1080 | } |
975 | // #4.2 del | 1081 | // #4.2 del |
@@ -1248,7 +1354,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -1248,7 +1354,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
1248 | * @param registration - Registration LwM2M Client | 1354 | * @param registration - Registration LwM2M Client |
1249 | * @return - sessionInfo after access connect client | 1355 | * @return - sessionInfo after access connect client |
1250 | */ | 1356 | */ |
1251 | - private SessionInfoProto getSessionInfoOrCloseSession(Registration registration) { | 1357 | + public SessionInfoProto getSessionInfoOrCloseSession(Registration registration) { |
1252 | return getSessionInfoOrCloseSession(clientContext.getOrRegister(registration)); | 1358 | return getSessionInfoOrCloseSession(clientContext.getOrRegister(registration)); |
1253 | } | 1359 | } |
1254 | 1360 | ||
@@ -1296,7 +1402,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -1296,7 +1402,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
1296 | TransportProtos.GetAttributeRequestMsg getAttributeMsg = adaptor.convertToGetAttributes(null, keyNamesMap.values()); | 1402 | TransportProtos.GetAttributeRequestMsg getAttributeMsg = adaptor.convertToGetAttributes(null, keyNamesMap.values()); |
1297 | transportService.process(sessionInfo, getAttributeMsg, getAckCallback(lwM2MClient, getAttributeMsg.getRequestId(), DEVICE_ATTRIBUTES_REQUEST)); | 1403 | transportService.process(sessionInfo, getAttributeMsg, getAckCallback(lwM2MClient, getAttributeMsg.getRequestId(), DEVICE_ATTRIBUTES_REQUEST)); |
1298 | } catch (AdaptorException e) { | 1404 | } catch (AdaptorException e) { |
1299 | - log.warn("Failed to decode get attributes request", e); | 1405 | + log.trace("Failed to decode get attributes request", e); |
1300 | } | 1406 | } |
1301 | } | 1407 | } |
1302 | 1408 | ||
@@ -1304,62 +1410,72 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -1304,62 +1410,72 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
1304 | } | 1410 | } |
1305 | 1411 | ||
1306 | public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient) { | 1412 | public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient) { |
1307 | - SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient); | ||
1308 | - if (sessionInfo != null) { | ||
1309 | - TransportProtos.GetFirmwareRequestMsg getFirmwareRequestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder() | ||
1310 | - .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) | ||
1311 | - .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) | ||
1312 | - .setTenantIdMSB(sessionInfo.getTenantIdMSB()) | ||
1313 | - .setTenantIdLSB(sessionInfo.getTenantIdLSB()) | ||
1314 | - .setType(FirmwareType.FIRMWARE.name()) | ||
1315 | - .build(); | ||
1316 | - transportService.process(sessionInfo, getFirmwareRequestMsg, | ||
1317 | - new TransportServiceCallback<>() { | ||
1318 | - @Override | ||
1319 | - public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) { | ||
1320 | - if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())) { | ||
1321 | - lwM2MClient.getFrUpdate().setCurrentFwVersion(response.getVersion()); | ||
1322 | - lwM2MClient.getFrUpdate().setCurrentFwId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId()); | ||
1323 | - lwM2MClient.setUpdateFw(true); | ||
1324 | - readRequestToClientFirmwareVer(lwM2MClient.getRegistration()); | ||
1325 | - } else { | ||
1326 | - log.trace("Firmware [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString()); | 1413 | + if (lwM2MClient.getRegistration().getSupportedVersion(FW_ID) != null) { |
1414 | + SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient); | ||
1415 | + if (sessionInfo != null) { | ||
1416 | + DefaultLwM2MTransportMsgHandler serviceImpl = this; | ||
1417 | + transportService.process(sessionInfo, createFirmwareRequestMsg(sessionInfo, FirmwareType.FIRMWARE.name()), | ||
1418 | + new TransportServiceCallback<>() { | ||
1419 | + @Override | ||
1420 | + public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) { | ||
1421 | + if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus()) | ||
1422 | + && response.getType().equals(FirmwareType.FIRMWARE.name())) { | ||
1423 | + lwM2MClient.getFwUpdate().setCurrentVersion(response.getVersion()); | ||
1424 | + lwM2MClient.getFwUpdate().setCurrentTitle(response.getTitle()); | ||
1425 | + lwM2MClient.getFwUpdate().setCurrentId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId()); | ||
1426 | + lwM2MClient.getFwUpdate().sendReadObserveInfo(lwM2mTransportRequest); | ||
1427 | + } else { | ||
1428 | + log.trace("Firmware [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString()); | ||
1429 | + } | ||
1327 | } | 1430 | } |
1328 | - } | ||
1329 | 1431 | ||
1330 | - @Override | ||
1331 | - public void onError(Throwable e) { | ||
1332 | - log.trace("Failed to process credentials ", e); | ||
1333 | - } | ||
1334 | - }); | 1432 | + @Override |
1433 | + public void onError(Throwable e) { | ||
1434 | + log.trace("Failed to process firmwareUpdate ", e); | ||
1435 | + } | ||
1436 | + }); | ||
1437 | + } | ||
1335 | } | 1438 | } |
1336 | } | 1439 | } |
1337 | 1440 | ||
1338 | - /** | ||
1339 | - * @param registration | ||
1340 | - */ | ||
1341 | - public void readRequestToClientFirmwareVer(Registration registration) { | ||
1342 | - String pathIdVer = convertPathFromObjectIdToIdVer(FR_PATH_RESOURCE_VER_ID, registration); | ||
1343 | - lwM2mTransportRequest.sendAllRequest(registration, pathIdVer, READ, ContentFormat.TLV.getName(), | ||
1344 | - null, config.getTimeout(), null); | ||
1345 | - } | 1441 | + public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient) { |
1442 | + if (lwM2MClient.getRegistration().getSupportedVersion(SW_ID) != null) { | ||
1443 | + SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient); | ||
1444 | + if (sessionInfo != null) { | ||
1445 | + DefaultLwM2MTransportMsgHandler serviceImpl = this; | ||
1446 | + transportService.process(sessionInfo, createFirmwareRequestMsg(sessionInfo, FirmwareType.SOFTWARE.name()), | ||
1447 | + new TransportServiceCallback<>() { | ||
1448 | + @Override | ||
1449 | + public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) { | ||
1450 | + if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus()) | ||
1451 | + && response.getType().equals(FirmwareType.SOFTWARE.name())) { | ||
1452 | + lwM2MClient.getSwUpdate().setCurrentVersion(response.getVersion()); | ||
1453 | + lwM2MClient.getSwUpdate().setCurrentTitle(response.getTitle()); | ||
1454 | + lwM2MClient.getSwUpdate().setCurrentId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId()); | ||
1455 | + lwM2MClient.getSwUpdate().sendReadObserveInfo(lwM2mTransportRequest); | ||
1456 | + } else { | ||
1457 | + log.trace("Software [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString()); | ||
1458 | + } | ||
1459 | + } | ||
1346 | 1460 | ||
1347 | - /** | ||
1348 | - * @param lwM2MClient - | ||
1349 | - */ | ||
1350 | - public void updateFirmwareClient(LwM2mClient lwM2MClient) { | ||
1351 | - if (!lwM2MClient.getFrUpdate().getCurrentFwVersion().equals(lwM2MClient.getFrUpdate().getClientFwVersion())) { | ||
1352 | - int chunkSize = 0; | ||
1353 | - int chunk = 0; | ||
1354 | - byte[] firmwareChunk = firmwareDataCache.get(lwM2MClient.getFrUpdate().getCurrentFwId().toString(), chunkSize, chunk); | ||
1355 | - String verSupportedObject = lwM2MClient.getRegistration().getSupportedObject().get(FR_OBJECT_ID); | ||
1356 | - String targetIdVer = LWM2M_SEPARATOR_PATH + FR_OBJECT_ID + LWM2M_SEPARATOR_KEY + verSupportedObject + LWM2M_SEPARATOR_PATH + 0 + LWM2M_SEPARATOR_PATH + 0; | ||
1357 | - lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE.getName(), | ||
1358 | - firmwareChunk, config.getTimeout(), null); | ||
1359 | - log.warn("updateFirmwareClient [{}] [{}]", lwM2MClient.getFrUpdate().getCurrentFwVersion(), lwM2MClient.getFrUpdate().getClientFwVersion()); | 1461 | + @Override |
1462 | + public void onError(Throwable e) { | ||
1463 | + log.trace("Failed to process softwareUpdate ", e); | ||
1464 | + } | ||
1465 | + }); | ||
1466 | + } | ||
1360 | } | 1467 | } |
1361 | } | 1468 | } |
1362 | 1469 | ||
1470 | + private TransportProtos.GetFirmwareRequestMsg createFirmwareRequestMsg(SessionInfoProto sessionInfo, String nameFwSW) { | ||
1471 | + return TransportProtos.GetFirmwareRequestMsg.newBuilder() | ||
1472 | + .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) | ||
1473 | + .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) | ||
1474 | + .setTenantIdMSB(sessionInfo.getTenantIdMSB()) | ||
1475 | + .setTenantIdLSB(sessionInfo.getTenantIdLSB()) | ||
1476 | + .setType(nameFwSW) | ||
1477 | + .build(); | ||
1478 | + } | ||
1363 | 1479 | ||
1364 | /** | 1480 | /** |
1365 | * !!! sharedAttr === profileAttr !!! | 1481 | * !!! sharedAttr === profileAttr !!! |
@@ -1386,4 +1502,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | @@ -1386,4 +1502,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler | ||
1386 | objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId))); | 1502 | objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId))); |
1387 | } | 1503 | } |
1388 | 1504 | ||
1505 | + public LwM2MTransportServerConfig getConfig() { | ||
1506 | + return this.config; | ||
1507 | + } | ||
1508 | + | ||
1389 | } | 1509 | } |
@@ -28,6 +28,7 @@ import org.eclipse.leshan.server.californium.registration.CaliforniumRegistratio | @@ -28,6 +28,7 @@ import org.eclipse.leshan.server.californium.registration.CaliforniumRegistratio | ||
28 | import org.eclipse.leshan.server.model.LwM2mModelProvider; | 28 | import org.eclipse.leshan.server.model.LwM2mModelProvider; |
29 | import org.eclipse.leshan.server.security.EditableSecurityStore; | 29 | import org.eclipse.leshan.server.security.EditableSecurityStore; |
30 | import org.springframework.stereotype.Component; | 30 | import org.springframework.stereotype.Component; |
31 | +import org.thingsboard.common.util.ThingsBoardThreadFactory; | ||
31 | import org.thingsboard.server.common.data.StringUtils; | 32 | import org.thingsboard.server.common.data.StringUtils; |
32 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | 33 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
33 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; | 34 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; |
@@ -57,6 +58,8 @@ import java.security.spec.InvalidParameterSpecException; | @@ -57,6 +58,8 @@ import java.security.spec.InvalidParameterSpecException; | ||
57 | import java.security.spec.KeySpec; | 58 | import java.security.spec.KeySpec; |
58 | import java.security.spec.PKCS8EncodedKeySpec; | 59 | import java.security.spec.PKCS8EncodedKeySpec; |
59 | import java.util.Arrays; | 60 | import java.util.Arrays; |
61 | +import java.util.concurrent.Executors; | ||
62 | +import java.util.concurrent.ScheduledExecutorService; | ||
60 | 63 | ||
61 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256; | 64 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256; |
62 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; | 65 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; |
@@ -122,7 +125,6 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { | @@ -122,7 +125,6 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { | ||
122 | /* Use a magic converter to support bad type send by the UI. */ | 125 | /* Use a magic converter to support bad type send by the UI. */ |
123 | builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance())); | 126 | builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance())); |
124 | 127 | ||
125 | - | ||
126 | /* Create CoAP Config */ | 128 | /* Create CoAP Config */ |
127 | builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort())); | 129 | builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort())); |
128 | 130 |
@@ -86,21 +86,22 @@ public class LwM2mServerListener { | @@ -86,21 +86,22 @@ public class LwM2mServerListener { | ||
86 | 86 | ||
87 | @Override | 87 | @Override |
88 | public void cancelled(Observation observation) { | 88 | public void cancelled(Observation observation) { |
89 | - String msg = String.format("%s: Cancel Observation %s.", LOG_LW2M_INFO, observation.getPath()); | 89 | + String msg = String.format("%s: Canceled Observation %s.", LOG_LW2M_INFO, observation.getPath()); |
90 | service.sendLogsToThingsboard(msg, observation.getRegistrationId()); | 90 | service.sendLogsToThingsboard(msg, observation.getRegistrationId()); |
91 | - log.trace(msg); | 91 | + log.warn(msg); |
92 | } | 92 | } |
93 | 93 | ||
94 | @Override | 94 | @Override |
95 | public void onResponse(Observation observation, Registration registration, ObserveResponse response) { | 95 | public void onResponse(Observation observation, Registration registration, ObserveResponse response) { |
96 | if (registration != null) { | 96 | if (registration != null) { |
97 | - try { | ||
98 | - service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(), | ||
99 | - registration), response, null); | ||
100 | - } catch (Exception e) { | ||
101 | - log.error("Observation/Read onResponse", e); | ||
102 | - | ||
103 | - } | 97 | +// if (observation.getPath().isResource() || observation.getPath().isResourceInstance()) { |
98 | +// String msg = String.format("%s: Successful Observation %s.", LOG_LW2M_INFO, | ||
99 | +// observation.getPath()); | ||
100 | +// log.warn(msg); | ||
101 | +// service.sendLogsToThingsboard(msg, registration.getId()); | ||
102 | +// } | ||
103 | + service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(), | ||
104 | + registration), response, null); | ||
104 | } | 105 | } |
105 | } | 106 | } |
106 | 107 | ||
@@ -113,9 +114,8 @@ public class LwM2mServerListener { | @@ -113,9 +114,8 @@ public class LwM2mServerListener { | ||
113 | public void newObservation(Observation observation, Registration registration) { | 114 | public void newObservation(Observation observation, Registration registration) { |
114 | String msg = String.format("%s: Successful start newObservation %s.", LOG_LW2M_INFO, | 115 | String msg = String.format("%s: Successful start newObservation %s.", LOG_LW2M_INFO, |
115 | observation.getPath()); | 116 | observation.getPath()); |
117 | + log.warn(msg); | ||
116 | service.sendLogsToThingsboard(msg, registration.getId()); | 118 | service.sendLogsToThingsboard(msg, registration.getId()); |
117 | - log.trace(msg); | ||
118 | } | 119 | } |
119 | }; | 120 | }; |
120 | - | ||
121 | } | 121 | } |
@@ -21,6 +21,7 @@ import org.eclipse.leshan.server.registration.Registration; | @@ -21,6 +21,7 @@ import org.eclipse.leshan.server.registration.Registration; | ||
21 | import org.thingsboard.server.common.data.Device; | 21 | import org.thingsboard.server.common.data.Device; |
22 | import org.thingsboard.server.common.data.DeviceProfile; | 22 | import org.thingsboard.server.common.data.DeviceProfile; |
23 | import org.thingsboard.server.gen.transport.TransportProtos; | 23 | import org.thingsboard.server.gen.transport.TransportProtos; |
24 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; | ||
24 | import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest; | 25 | import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest; |
25 | 26 | ||
26 | import java.util.Collection; | 27 | import java.util.Collection; |
@@ -36,7 +37,7 @@ public interface LwM2mTransportMsgHandler { | @@ -36,7 +37,7 @@ public interface LwM2mTransportMsgHandler { | ||
36 | 37 | ||
37 | void onSleepingDev(Registration registration); | 38 | void onSleepingDev(Registration registration); |
38 | 39 | ||
39 | - void setCancelObservations(Registration registration); | 40 | + void setCancelObservationsAll(Registration registration); |
40 | 41 | ||
41 | void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest); | 42 | void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest); |
42 | 43 | ||
@@ -63,4 +64,6 @@ public interface LwM2mTransportMsgHandler { | @@ -63,4 +64,6 @@ public interface LwM2mTransportMsgHandler { | ||
63 | void onAwakeDev(Registration registration); | 64 | void onAwakeDev(Registration registration); |
64 | 65 | ||
65 | void sendLogsToThingsboard(String msg, String registrationId); | 66 | void sendLogsToThingsboard(String msg, String registrationId); |
67 | + | ||
68 | + LwM2MTransportServerConfig getConfig(); | ||
66 | } | 69 | } |
@@ -19,6 +19,7 @@ import lombok.RequiredArgsConstructor; | @@ -19,6 +19,7 @@ import lombok.RequiredArgsConstructor; | ||
19 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
20 | import org.eclipse.californium.core.coap.CoAP; | 20 | import org.eclipse.californium.core.coap.CoAP; |
21 | import org.eclipse.californium.core.coap.Response; | 21 | import org.eclipse.californium.core.coap.Response; |
22 | +import org.eclipse.leshan.core.Link; | ||
22 | import org.eclipse.leshan.core.model.ResourceModel; | 23 | import org.eclipse.leshan.core.model.ResourceModel; |
23 | import org.eclipse.leshan.core.node.LwM2mNode; | 24 | import org.eclipse.leshan.core.node.LwM2mNode; |
24 | import org.eclipse.leshan.core.node.LwM2mPath; | 25 | import org.eclipse.leshan.core.node.LwM2mPath; |
@@ -35,7 +36,6 @@ import org.eclipse.leshan.core.request.ObserveRequest; | @@ -35,7 +36,6 @@ import org.eclipse.leshan.core.request.ObserveRequest; | ||
35 | import org.eclipse.leshan.core.request.ReadRequest; | 36 | import org.eclipse.leshan.core.request.ReadRequest; |
36 | import org.eclipse.leshan.core.request.WriteRequest; | 37 | import org.eclipse.leshan.core.request.WriteRequest; |
37 | import org.eclipse.leshan.core.request.exception.ClientSleepingException; | 38 | import org.eclipse.leshan.core.request.exception.ClientSleepingException; |
38 | -import org.eclipse.leshan.core.response.CancelObservationResponse; | ||
39 | import org.eclipse.leshan.core.response.DeleteResponse; | 39 | import org.eclipse.leshan.core.response.DeleteResponse; |
40 | import org.eclipse.leshan.core.response.DiscoverResponse; | 40 | import org.eclipse.leshan.core.response.DiscoverResponse; |
41 | import org.eclipse.leshan.core.response.ExecuteResponse; | 41 | import org.eclipse.leshan.core.response.ExecuteResponse; |
@@ -68,15 +68,26 @@ import java.util.stream.Collectors; | @@ -68,15 +68,26 @@ import java.util.stream.Collectors; | ||
68 | import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT; | 68 | import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT; |
69 | import static org.eclipse.leshan.core.ResponseCode.BAD_REQUEST; | 69 | import static org.eclipse.leshan.core.ResponseCode.BAD_REQUEST; |
70 | import static org.eclipse.leshan.core.ResponseCode.NOT_FOUND; | 70 | import static org.eclipse.leshan.core.ResponseCode.NOT_FOUND; |
71 | +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.DOWNLOADED; | ||
72 | +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.FAILED; | ||
73 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getContentFormatByResourceModelType; | ||
71 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEFAULT_TIMEOUT; | 74 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEFAULT_TIMEOUT; |
72 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FR_PATH_RESOURCE_VER_ID; | 75 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID; |
76 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_ID; | ||
73 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR; | 77 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR; |
74 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; | 78 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; |
75 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE; | 79 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE; |
76 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper; | 80 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper; |
81 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER; | ||
82 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER_All; | ||
83 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE; | ||
77 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL; | 84 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL; |
78 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_READ_ALL; | 85 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_READ_ALL; |
79 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.RESPONSE_CHANNEL; | 86 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE; |
87 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_UPDATE; | ||
88 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.RESPONSE_REQUEST_CHANNEL; | ||
89 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_INSTALL_ID; | ||
90 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_PACKAGE_ID; | ||
80 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId; | 91 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId; |
81 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; | 92 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; |
82 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.createWriteAttributeRequest; | 93 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.createWriteAttributeRequest; |
@@ -86,20 +97,20 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.c | @@ -86,20 +97,20 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.c | ||
86 | @TbLwM2mTransportComponent | 97 | @TbLwM2mTransportComponent |
87 | @RequiredArgsConstructor | 98 | @RequiredArgsConstructor |
88 | public class LwM2mTransportRequest { | 99 | public class LwM2mTransportRequest { |
89 | - private ExecutorService executorResponse; | 100 | + private ExecutorService responseRequestExecutor; |
90 | 101 | ||
91 | public LwM2mValueConverterImpl converter; | 102 | public LwM2mValueConverterImpl converter; |
92 | 103 | ||
93 | private final LwM2mTransportContext context; | 104 | private final LwM2mTransportContext context; |
94 | private final LwM2MTransportServerConfig config; | 105 | private final LwM2MTransportServerConfig config; |
95 | private final LwM2mClientContext lwM2mClientContext; | 106 | private final LwM2mClientContext lwM2mClientContext; |
96 | - private final DefaultLwM2MTransportMsgHandler serviceImpl; | 107 | + private final DefaultLwM2MTransportMsgHandler handler; |
97 | 108 | ||
98 | @PostConstruct | 109 | @PostConstruct |
99 | public void init() { | 110 | public void init() { |
100 | this.converter = LwM2mValueConverterImpl.getInstance(); | 111 | this.converter = LwM2mValueConverterImpl.getInstance(); |
101 | - executorResponse = Executors.newFixedThreadPool(this.config.getResponsePoolSize(), | ||
102 | - new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL))); | 112 | + responseRequestExecutor = Executors.newFixedThreadPool(this.config.getResponsePoolSize(), |
113 | + new NamedThreadFactory(String.format("LwM2M %s channel response after request", RESPONSE_REQUEST_CHANNEL))); | ||
103 | } | 114 | } |
104 | 115 | ||
105 | /** | 116 | /** |
@@ -115,154 +126,186 @@ public class LwM2mTransportRequest { | @@ -115,154 +126,186 @@ public class LwM2mTransportRequest { | ||
115 | String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { | 126 | String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { |
116 | try { | 127 | try { |
117 | String target = convertPathFromIdVerToObjectId(targetIdVer); | 128 | String target = convertPathFromIdVerToObjectId(targetIdVer); |
118 | - DownlinkRequest request = null; | ||
119 | ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT; | 129 | ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT; |
120 | LwM2mClient lwM2MClient = this.lwM2mClientContext.getOrRegister(registration); | 130 | LwM2mClient lwM2MClient = this.lwM2mClientContext.getOrRegister(registration); |
121 | LwM2mPath resultIds = target != null ? new LwM2mPath(target) : null; | 131 | LwM2mPath resultIds = target != null ? new LwM2mPath(target) : null; |
122 | if (!OBSERVE_READ_ALL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0 && lwM2MClient != null) { | 132 | if (!OBSERVE_READ_ALL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0 && lwM2MClient != null) { |
123 | if (lwM2MClient.isValidObjectVersion(targetIdVer)) { | 133 | if (lwM2MClient.isValidObjectVersion(targetIdVer)) { |
124 | timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT; | 134 | timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT; |
125 | - ResourceModel resourceModel = null; | ||
126 | - switch (typeOper) { | ||
127 | - case READ: | ||
128 | - request = new ReadRequest(contentFormat, target); | ||
129 | - break; | ||
130 | - case DISCOVER: | ||
131 | - request = new DiscoverRequest(target); | ||
132 | - break; | ||
133 | - case OBSERVE: | ||
134 | - if (resultIds.isResource()) { | ||
135 | - request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId()); | ||
136 | - } else if (resultIds.isObjectInstance()) { | ||
137 | - request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId()); | ||
138 | - } else if (resultIds.getObjectId() >= 0) { | ||
139 | - request = new ObserveRequest(contentFormat, resultIds.getObjectId()); | ||
140 | - } | ||
141 | - break; | ||
142 | - case OBSERVE_CANCEL: | ||
143 | - /* | ||
144 | - lwM2MTransportRequest.sendAllRequest(lwServer, registration, path, POST_TYPE_OPER_OBSERVE_CANCEL, null, null, null, null, context.getTimeout()); | ||
145 | - At server side this will not remove the observation from the observation store, to do it you need to use | ||
146 | - {@code ObservationService#cancelObservation()} | ||
147 | - */ | ||
148 | - context.getServer().getObservationService().cancelObservations(registration, target); | ||
149 | - break; | ||
150 | - case EXECUTE: | ||
151 | - resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config | ||
152 | - .getModelProvider()); | ||
153 | - if (params != null && !resourceModel.multiple) { | ||
154 | - request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resourceModel.type, ResourceModel.Type.STRING, resultIds)); | ||
155 | - } else { | ||
156 | - request = new ExecuteRequest(target); | ||
157 | - } | ||
158 | - break; | ||
159 | - case WRITE_REPLACE: | ||
160 | - // Request to write a <b>String Single-Instance Resource</b> using the TLV content format. | ||
161 | - resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()); | ||
162 | - if (contentFormat.equals(ContentFormat.TLV)) { | ||
163 | - request = this.getWriteRequestSingleResource(null, resultIds.getObjectId(), | ||
164 | - resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModel.type, | ||
165 | - registration, rpcRequest); | ||
166 | - } | ||
167 | - // Mode.REPLACE && Request to write a <b>String Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON) | ||
168 | - else if (!contentFormat.equals(ContentFormat.TLV)) { | ||
169 | - request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), | ||
170 | - resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModel.type, | ||
171 | - registration, rpcRequest); | ||
172 | - } | ||
173 | - break; | ||
174 | - case WRITE_UPDATE: | ||
175 | - if (resultIds.isResource()) { | ||
176 | - /** | ||
177 | - * send request: path = '/3/0' node == wM2mObjectInstance | ||
178 | - * with params == "\"resources\": {15: resource:{id:15. value:'+01'...}} | ||
179 | - **/ | ||
180 | - Collection<LwM2mResource> resources = lwM2MClient.getNewOneResourceForInstance( | ||
181 | - targetIdVer, params, | ||
182 | - this.config.getModelProvider(), | ||
183 | - this.converter); | ||
184 | - request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), | ||
185 | - resultIds.getObjectInstanceId(), resources); | ||
186 | - } | ||
187 | - | ||
188 | - /** | ||
189 | - * params = "{\"id\":0,\"resources\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}" | ||
190 | - * | ||
191 | - * int rscId = resultIds.getObjectInstanceId(); | ||
192 | - */ | ||
193 | - | ||
194 | - else if (resultIds.isObjectInstance()) { | ||
195 | - if (((ConcurrentHashMap) params).size() > 0) { | ||
196 | - Collection<LwM2mResource> resources = lwM2MClient.getNewManyResourcesForInstance( | ||
197 | - targetIdVer, params, | ||
198 | - this.config.getModelProvider(), | ||
199 | - this.converter); | ||
200 | - request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), | ||
201 | - resultIds.getObjectInstanceId(), resources); | ||
202 | - } | ||
203 | - } else if (resultIds.getObjectId() >= 0) { | ||
204 | - request = new ObserveRequest(resultIds.getObjectId()); | ||
205 | - } | ||
206 | - break; | ||
207 | - case WRITE_ATTRIBUTES: | ||
208 | - request = createWriteAttributeRequest(target, params); | ||
209 | - break; | ||
210 | - case DELETE: | ||
211 | - request = new DeleteRequest(target); | ||
212 | - break; | ||
213 | - } | ||
214 | - | 135 | + DownlinkRequest request = createRequest (registration, lwM2MClient, typeOper, contentFormat, target, |
136 | + targetIdVer, resultIds, params, rpcRequest); | ||
215 | if (request != null) { | 137 | if (request != null) { |
216 | try { | 138 | try { |
217 | this.sendRequest(registration, lwM2MClient, request, timeoutInMs, rpcRequest); | 139 | this.sendRequest(registration, lwM2MClient, request, timeoutInMs, rpcRequest); |
218 | } catch (ClientSleepingException e) { | 140 | } catch (ClientSleepingException e) { |
219 | DownlinkRequest finalRequest = request; | 141 | DownlinkRequest finalRequest = request; |
220 | long finalTimeoutInMs = timeoutInMs; | 142 | long finalTimeoutInMs = timeoutInMs; |
221 | - lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, rpcRequest)); | 143 | + Lwm2mClientRpcRequest finalRpcRequest = rpcRequest; |
144 | + lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, finalRpcRequest)); | ||
222 | } catch (Exception e) { | 145 | } catch (Exception e) { |
223 | log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper.name(), e); | 146 | log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper.name(), e); |
224 | } | 147 | } |
225 | - } else if (OBSERVE_CANCEL == typeOper) { | ||
226 | - log.trace("[{}], [{}] - [{}] SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer); | ||
227 | - if (rpcRequest != null) { | ||
228 | - rpcRequest.setInfoMsg(null); | ||
229 | - serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), null, null); | 148 | + } |
149 | + else if (WRITE_UPDATE.name().equals(typeOper.name())) { | ||
150 | + Lwm2mClientRpcRequest rpcRequestClone = (Lwm2mClientRpcRequest) rpcRequest.clone(); | ||
151 | + if (rpcRequestClone != null) { | ||
152 | + String errorMsg = String.format("Path %s params is not valid", targetIdVer); | ||
153 | + handler.sentRpcRequest(rpcRequestClone, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR); | ||
154 | + rpcRequest = null; | ||
230 | } | 155 | } |
231 | - } else { | 156 | + } |
157 | + else if (!OBSERVE_CANCEL.name().equals(typeOper.name())) { | ||
232 | log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer); | 158 | log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer); |
233 | if (rpcRequest != null) { | 159 | if (rpcRequest != null) { |
160 | + ResourceModel resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()); | ||
234 | String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null"; | 161 | String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null"; |
235 | - serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); | 162 | + handler.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); |
236 | } | 163 | } |
237 | } | 164 | } |
238 | } else if (rpcRequest != null) { | 165 | } else if (rpcRequest != null) { |
239 | String errorMsg = String.format("Path %s not found in object version", targetIdVer); | 166 | String errorMsg = String.format("Path %s not found in object version", targetIdVer); |
240 | - serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); | 167 | + handler.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); |
168 | + } | ||
169 | + } else if (OBSERVE_READ_ALL.name().equals(typeOper.name()) || DISCOVER_All.name().equals(typeOper.name())) { | ||
170 | + Set<String> paths; | ||
171 | + if (OBSERVE_READ_ALL.name().equals(typeOper.name())) { | ||
172 | + Set<Observation> observations = context.getServer().getObservationService().getObservations(registration); | ||
173 | + paths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet()); | ||
174 | + } else { | ||
175 | + assert registration != null; | ||
176 | + Link[] objectLinks = registration.getSortedObjectLinks(); | ||
177 | + paths = Arrays.stream(objectLinks).map(Link::toString).collect(Collectors.toUnmodifiableSet()); | ||
178 | + String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO, | ||
179 | + typeOper.name(), paths); | ||
180 | + handler.sendLogsToThingsboard(msg, registration.getId()); | ||
241 | } | 181 | } |
242 | - } else if (OBSERVE_READ_ALL.name().equals(typeOper.name())) { | ||
243 | - Set<Observation> observations = context.getServer().getObservationService().getObservations(registration); | ||
244 | - Set<String> observationPaths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet()); | ||
245 | - String msg = String.format("%s: type operation %s observation paths - %s", LOG_LW2M_INFO, | ||
246 | - OBSERVE_READ_ALL.type, observationPaths); | ||
247 | - serviceImpl.sendLogsToThingsboard(msg, registration.getId()); | ||
248 | - log.trace("[{}] [{}], [{}]", typeOper.name(), registration.getEndpoint(), msg); | ||
249 | if (rpcRequest != null) { | 182 | if (rpcRequest != null) { |
250 | - String valueMsg = String.format("Observation paths - %s", observationPaths); | ||
251 | - serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE); | 183 | + String valueMsg = String.format("Paths - %s", paths); |
184 | + handler.sentRpcRequest(rpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE); | ||
252 | } | 185 | } |
186 | + } else if (OBSERVE_CANCEL.name().equals(typeOper.name())) { | ||
187 | + int observeCancelCnt = context.getServer().getObservationService().cancelObservations(registration); | ||
188 | + String observeCancelMsgAll = String.format("%s: type operation %s paths: All count: %d", LOG_LW2M_INFO, | ||
189 | + OBSERVE_CANCEL.name(), observeCancelCnt); | ||
190 | + this.afterObserveCancel(registration, observeCancelCnt, observeCancelMsgAll, rpcRequest); | ||
253 | } | 191 | } |
254 | } catch (Exception e) { | 192 | } catch (Exception e) { |
255 | String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR, | 193 | String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR, |
256 | typeOper.name(), e.getMessage()); | 194 | typeOper.name(), e.getMessage()); |
257 | - serviceImpl.sendLogsToThingsboard(msg, registration.getId()); | ||
258 | - try { | ||
259 | - throw new Exception(e); | ||
260 | - } catch (Exception exception) { | ||
261 | - exception.printStackTrace(); | 195 | + handler.sendLogsToThingsboard(msg, registration.getId()); |
196 | + if (rpcRequest != null) { | ||
197 | + String errorMsg = String.format("Path %s type operation %s %s", targetIdVer, typeOper.name(), e.getMessage()); | ||
198 | + handler.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); | ||
262 | } | 199 | } |
263 | } | 200 | } |
264 | } | 201 | } |
265 | 202 | ||
203 | + private DownlinkRequest createRequest (Registration registration, LwM2mClient lwM2MClient, LwM2mTypeOper typeOper, | ||
204 | + ContentFormat contentFormat, String target, String targetIdVer, | ||
205 | + LwM2mPath resultIds, Object params, Lwm2mClientRpcRequest rpcRequest) { | ||
206 | + DownlinkRequest request = null; | ||
207 | + switch (typeOper) { | ||
208 | + case READ: | ||
209 | + request = new ReadRequest(contentFormat, target); | ||
210 | + break; | ||
211 | + case DISCOVER: | ||
212 | + request = new DiscoverRequest(target); | ||
213 | + break; | ||
214 | + case OBSERVE: | ||
215 | + String msg = String.format("%s: Send Observation %s.", LOG_LW2M_INFO, targetIdVer); | ||
216 | + log.warn(msg); | ||
217 | + if (resultIds.isResource()) { | ||
218 | + Set<Observation> observations = context.getServer().getObservationService().getObservations(registration); | ||
219 | + Set<Observation> paths = observations.stream().filter(observation -> observation.getPath().equals(resultIds)).collect(Collectors.toSet()); | ||
220 | + if (paths.size() == 0) { | ||
221 | + request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId()); | ||
222 | + } else { | ||
223 | + request = new ReadRequest(contentFormat, target); | ||
224 | + } | ||
225 | + } else if (resultIds.isObjectInstance()) { | ||
226 | + request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId()); | ||
227 | + } else if (resultIds.getObjectId() >= 0) { | ||
228 | + request = new ObserveRequest(contentFormat, resultIds.getObjectId()); | ||
229 | + } | ||
230 | + break; | ||
231 | + case OBSERVE_CANCEL: | ||
232 | + /* | ||
233 | + lwM2MTransportRequest.sendAllRequest(lwServer, registration, path, POST_TYPE_OPER_OBSERVE_CANCEL, null, null, null, null, context.getTimeout()); | ||
234 | + At server side this will not remove the observation from the observation store, to do it you need to use | ||
235 | + {@code ObservationService#cancelObservation()} | ||
236 | + */ | ||
237 | + int observeCancelCnt = context.getServer().getObservationService().cancelObservations(registration, target); | ||
238 | + String observeCancelMsg = String.format("%s: type operation %s paths: %s count: %d", LOG_LW2M_INFO, | ||
239 | + OBSERVE_CANCEL.name(), target, observeCancelCnt); | ||
240 | + this.afterObserveCancel(registration, observeCancelCnt, observeCancelMsg, rpcRequest); | ||
241 | + break; | ||
242 | + case EXECUTE: | ||
243 | + ResourceModel resourceModelExe = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()); | ||
244 | + if (params != null && !resourceModelExe.multiple) { | ||
245 | + request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resourceModelExe.type, ResourceModel.Type.STRING, resultIds)); | ||
246 | + } else { | ||
247 | + request = new ExecuteRequest(target); | ||
248 | + } | ||
249 | + break; | ||
250 | + case WRITE_REPLACE: | ||
251 | + /** | ||
252 | + * Request to write a <b>String Single-Instance Resource</b> using the TLV content format. | ||
253 | + * Type from resourceModel -> STRING, INTEGER, FLOAT, BOOLEAN, OPAQUE, TIME, OBJLNK | ||
254 | + * contentFormat -> TLV, TLV, TLV, TLV, OPAQUE, TLV, LINK | ||
255 | + * JSON, TEXT; | ||
256 | + **/ | ||
257 | + ResourceModel resourceModelWrite = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()); | ||
258 | + contentFormat = getContentFormatByResourceModelType(resourceModelWrite, contentFormat); | ||
259 | + request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), | ||
260 | + resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModelWrite.type, | ||
261 | + registration, rpcRequest); | ||
262 | + break; | ||
263 | + case WRITE_UPDATE: | ||
264 | + if (resultIds.isResource()) { | ||
265 | + /** | ||
266 | + * send request: path = '/3/0' node == wM2mObjectInstance | ||
267 | + * with params == "\"resources\": {15: resource:{id:15. value:'+01'...}} | ||
268 | + **/ | ||
269 | + Collection<LwM2mResource> resources = lwM2MClient.getNewResourceForInstance( | ||
270 | + targetIdVer, params, | ||
271 | + this.config.getModelProvider(), | ||
272 | + this.converter); | ||
273 | + contentFormat = getContentFormatByResourceModelType(lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()), | ||
274 | + contentFormat); | ||
275 | + request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), | ||
276 | + resultIds.getObjectInstanceId(), resources); | ||
277 | + } | ||
278 | + /** | ||
279 | + * params = "{\"id\":0,\"resources\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}" | ||
280 | + * int rscId = resultIds.getObjectInstanceId(); | ||
281 | + * contentFormat – Format of the payload (TLV or JSON). | ||
282 | + */ | ||
283 | + else if (resultIds.isObjectInstance()) { | ||
284 | + if (((ConcurrentHashMap) params).size() > 0) { | ||
285 | + Collection<LwM2mResource> resources = lwM2MClient.getNewResourcesForInstance( | ||
286 | + targetIdVer, params, | ||
287 | + this.config.getModelProvider(), | ||
288 | + this.converter); | ||
289 | + if (resources.size() > 0) { | ||
290 | + contentFormat = contentFormat.equals(ContentFormat.JSON) ? contentFormat : ContentFormat.TLV; | ||
291 | + request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), | ||
292 | + resultIds.getObjectInstanceId(), resources); | ||
293 | + } | ||
294 | + } | ||
295 | + } else if (resultIds.getObjectId() >= 0) { | ||
296 | + request = new ObserveRequest(resultIds.getObjectId()); | ||
297 | + } | ||
298 | + break; | ||
299 | + case WRITE_ATTRIBUTES: | ||
300 | + request = createWriteAttributeRequest(target, params); | ||
301 | + break; | ||
302 | + case DELETE: | ||
303 | + request = new DeleteRequest(target); | ||
304 | + break; | ||
305 | + } | ||
306 | + return request; | ||
307 | + } | ||
308 | + | ||
266 | /** | 309 | /** |
267 | * @param registration - | 310 | * @param registration - |
268 | * @param request - | 311 | * @param request - |
@@ -273,52 +316,66 @@ public class LwM2mTransportRequest { | @@ -273,52 +316,66 @@ public class LwM2mTransportRequest { | ||
273 | private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, | 316 | private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, |
274 | long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { | 317 | long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { |
275 | context.getServer().send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> { | 318 | context.getServer().send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> { |
319 | + | ||
276 | if (!lwM2MClient.isInit()) { | 320 | if (!lwM2MClient.isInit()) { |
277 | - lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); | 321 | + lwM2MClient.initReadValue(this.handler, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); |
278 | } | 322 | } |
279 | if (CoAP.ResponseCode.isSuccess(((Response) response.getCoapResponse()).getCode())) { | 323 | if (CoAP.ResponseCode.isSuccess(((Response) response.getCoapResponse()).getCode())) { |
280 | this.handleResponse(registration, request.getPath().toString(), response, request, rpcRequest); | 324 | this.handleResponse(registration, request.getPath().toString(), response, request, rpcRequest); |
281 | } else { | 325 | } else { |
282 | String msg = String.format("%s: SendRequest %s: CoapCode - %s Lwm2m code - %d name - %s Resource path - %s", LOG_LW2M_ERROR, request.getClass().getName().toString(), | 326 | String msg = String.format("%s: SendRequest %s: CoapCode - %s Lwm2m code - %d name - %s Resource path - %s", LOG_LW2M_ERROR, request.getClass().getName().toString(), |
283 | ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(), response.getCode().getName(), request.getPath().toString()); | 327 | ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(), response.getCode().getName(), request.getPath().toString()); |
284 | - serviceImpl.sendLogsToThingsboard(msg, registration.getId()); | 328 | + handler.sendLogsToThingsboard(msg, registration.getId()); |
285 | log.error("[{}] [{}], [{}] - [{}] [{}] error SendRequest", request.getClass().getName().toString(), registration.getEndpoint(), | 329 | log.error("[{}] [{}], [{}] - [{}] [{}] error SendRequest", request.getClass().getName().toString(), registration.getEndpoint(), |
286 | ((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString()); | 330 | ((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString()); |
287 | if (!lwM2MClient.isInit()) { | 331 | if (!lwM2MClient.isInit()) { |
288 | - lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); | 332 | + lwM2MClient.initReadValue(this.handler, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); |
289 | } | 333 | } |
334 | + /** Not Found */ | ||
290 | if (rpcRequest != null) { | 335 | if (rpcRequest != null) { |
291 | - serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR); | 336 | + handler.sentRpcRequest(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR); |
292 | } | 337 | } |
293 | - /* Not Found | ||
294 | - set setClient_fw_version = empty | ||
295 | - */ | ||
296 | - if (FR_PATH_RESOURCE_VER_ID.equals(request.getPath().toString()) && lwM2MClient.isUpdateFw()) { | ||
297 | - lwM2MClient.setUpdateFw(false); | ||
298 | - lwM2MClient.getFrUpdate().setClientFwVersion(""); | ||
299 | - log.warn("updateFirmwareClient1"); | ||
300 | - serviceImpl.updateFirmwareClient(lwM2MClient); | 338 | + /** Not Found |
339 | + set setClient_fw_info... = empty | ||
340 | + **/ | ||
341 | + if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { | ||
342 | + lwM2MClient.getFwUpdate().initReadValue(handler, this, request.getPath().toString()); | ||
343 | + } | ||
344 | + if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { | ||
345 | + lwM2MClient.getSwUpdate().initReadValue(handler, this, request.getPath().toString()); | ||
346 | + } | ||
347 | + if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { | ||
348 | + this.afterWriteFwSWUpdateError(registration, request, response.getErrorMessage()); | ||
349 | + } | ||
350 | + if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) { | ||
351 | + this.afterExecuteFwSwUpdateError(registration, request, response.getErrorMessage()); | ||
301 | } | 352 | } |
302 | } | 353 | } |
303 | }, e -> { | 354 | }, e -> { |
304 | - /* version == null | ||
305 | - set setClient_fw_version = empty | ||
306 | - */ | ||
307 | - if (FR_PATH_RESOURCE_VER_ID.equals(request.getPath().toString()) && lwM2MClient.isUpdateFw()) { | ||
308 | - lwM2MClient.setUpdateFw(false); | ||
309 | - lwM2MClient.getFrUpdate().setClientFwVersion(""); | ||
310 | - log.warn("updateFirmwareClient2"); | ||
311 | - serviceImpl.updateFirmwareClient(lwM2MClient); | 355 | + /** version == null |
356 | + set setClient_fw_info... = empty | ||
357 | + **/ | ||
358 | + if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { | ||
359 | + lwM2MClient.getFwUpdate().initReadValue(handler, this, request.getPath().toString()); | ||
360 | + } | ||
361 | + if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { | ||
362 | + lwM2MClient.getSwUpdate().initReadValue(handler, this, request.getPath().toString()); | ||
363 | + } | ||
364 | + if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { | ||
365 | + this.afterWriteFwSWUpdateError(registration, request, e.getMessage()); | ||
366 | + } | ||
367 | + if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) { | ||
368 | + this.afterExecuteFwSwUpdateError(registration, request, e.getMessage()); | ||
312 | } | 369 | } |
313 | if (!lwM2MClient.isInit()) { | 370 | if (!lwM2MClient.isInit()) { |
314 | - lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); | 371 | + lwM2MClient.initReadValue(this.handler, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); |
315 | } | 372 | } |
316 | String msg = String.format("%s: SendRequest %s: Resource path - %s msg error - %s", | 373 | String msg = String.format("%s: SendRequest %s: Resource path - %s msg error - %s", |
317 | LOG_LW2M_ERROR, request.getClass().getName().toString(), request.getPath().toString(), e.getMessage()); | 374 | LOG_LW2M_ERROR, request.getClass().getName().toString(), request.getPath().toString(), e.getMessage()); |
318 | - serviceImpl.sendLogsToThingsboard(msg, registration.getId()); | 375 | + handler.sendLogsToThingsboard(msg, registration.getId()); |
319 | log.error("[{}] [{}] - [{}] error SendRequest", request.getClass().getName().toString(), request.getPath().toString(), e.toString()); | 376 | log.error("[{}] [{}] - [{}] error SendRequest", request.getClass().getName().toString(), request.getPath().toString(), e.toString()); |
320 | if (rpcRequest != null) { | 377 | if (rpcRequest != null) { |
321 | - serviceImpl.sentRpcRequest(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR); | 378 | + handler.sentRpcRequest(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR); |
322 | } | 379 | } |
323 | }); | 380 | }); |
324 | } | 381 | } |
@@ -360,11 +417,11 @@ public class LwM2mTransportRequest { | @@ -360,11 +417,11 @@ public class LwM2mTransportRequest { | ||
360 | String patn = "/" + objectId + "/" + instanceId + "/" + resourceId; | 417 | String patn = "/" + objectId + "/" + instanceId + "/" + resourceId; |
361 | String msg = String.format(LOG_LW2M_ERROR + ": NumberFormatException: Resource path - %s type - %s value - %s msg error - %s SendRequest to Client", | 418 | String msg = String.format(LOG_LW2M_ERROR + ": NumberFormatException: Resource path - %s type - %s value - %s msg error - %s SendRequest to Client", |
362 | patn, type, value, e.toString()); | 419 | patn, type, value, e.toString()); |
363 | - serviceImpl.sendLogsToThingsboard(msg, registration.getId()); | 420 | + handler.sendLogsToThingsboard(msg, registration.getId()); |
364 | log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString()); | 421 | log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString()); |
365 | if (rpcRequest != null) { | 422 | if (rpcRequest != null) { |
366 | String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value); | 423 | String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value); |
367 | - serviceImpl.sentRpcRequest(rpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR); | 424 | + handler.sentRpcRequest(rpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR); |
368 | } | 425 | } |
369 | return null; | 426 | return null; |
370 | } | 427 | } |
@@ -372,7 +429,7 @@ public class LwM2mTransportRequest { | @@ -372,7 +429,7 @@ public class LwM2mTransportRequest { | ||
372 | 429 | ||
373 | private void handleResponse(Registration registration, final String path, LwM2mResponse response, | 430 | private void handleResponse(Registration registration, final String path, LwM2mResponse response, |
374 | DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { | 431 | DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { |
375 | - executorResponse.submit(() -> { | 432 | + responseRequestExecutor.submit(() -> { |
376 | try { | 433 | try { |
377 | this.sendResponse(registration, path, response, request, rpcRequest); | 434 | this.sendResponse(registration, path, response, request, rpcRequest); |
378 | } catch (Exception e) { | 435 | } catch (Exception e) { |
@@ -391,39 +448,37 @@ public class LwM2mTransportRequest { | @@ -391,39 +448,37 @@ public class LwM2mTransportRequest { | ||
391 | private void sendResponse(Registration registration, String path, LwM2mResponse response, | 448 | private void sendResponse(Registration registration, String path, LwM2mResponse response, |
392 | DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { | 449 | DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { |
393 | String pathIdVer = convertPathFromObjectIdToIdVer(path, registration); | 450 | String pathIdVer = convertPathFromObjectIdToIdVer(path, registration); |
451 | + String msgLog = ""; | ||
394 | if (response instanceof ReadResponse) { | 452 | if (response instanceof ReadResponse) { |
395 | - serviceImpl.onUpdateValueAfterReadResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest); | ||
396 | - } else if (response instanceof CancelObservationResponse) { | ||
397 | - log.info("[{}] Path [{}] CancelObservationResponse 3_Send", pathIdVer, response); | ||
398 | - | 453 | + handler.onUpdateValueAfterReadResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest); |
399 | } else if (response instanceof DeleteResponse) { | 454 | } else if (response instanceof DeleteResponse) { |
400 | - log.info("[{}] Path [{}] DeleteResponse 5_Send", pathIdVer, response); | 455 | + log.warn("[{}] Path [{}] DeleteResponse 5_Send", pathIdVer, response); |
401 | } else if (response instanceof DiscoverResponse) { | 456 | } else if (response instanceof DiscoverResponse) { |
402 | - log.info("[{}] [{}] - [{}] [{}] Discovery value: [{}]", registration.getEndpoint(), | ||
403 | - ((Response) response.getCoapResponse()).getCode(), response.getCode(), | ||
404 | - request.getPath().toString(), ((DiscoverResponse) response).getObjectLinks()); | 457 | + String discoverValue = Link.serialize(((DiscoverResponse)response).getObjectLinks()); |
458 | + msgLog = String.format("%s: type operation: %s path: %s value: %s", | ||
459 | + LOG_LW2M_INFO, DISCOVER.name(), request.getPath().toString(), discoverValue); | ||
460 | + handler.sendLogsToThingsboard(msgLog, registration.getId()); | ||
461 | + log.warn("DiscoverResponse: [{}]", (DiscoverResponse) response); | ||
405 | if (rpcRequest != null) { | 462 | if (rpcRequest != null) { |
406 | - String discoveryMsg = String.format("%s", | ||
407 | - Arrays.stream(((DiscoverResponse) response).getObjectLinks()).collect(Collectors.toSet())); | ||
408 | - serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), discoveryMsg, LOG_LW2M_VALUE); | 463 | + handler.sentRpcRequest(rpcRequest, response.getCode().getName(), discoverValue, LOG_LW2M_VALUE); |
409 | } | 464 | } |
410 | } else if (response instanceof ExecuteResponse) { | 465 | } else if (response instanceof ExecuteResponse) { |
411 | - log.info("[{}] Path [{}] ExecuteResponse 7_Send", pathIdVer, response); | 466 | + log.warn("[{}] Path [{}] ExecuteResponse 7_Send", pathIdVer, response); |
412 | } else if (response instanceof WriteAttributesResponse) { | 467 | } else if (response instanceof WriteAttributesResponse) { |
413 | - log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response); | 468 | + log.warn("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response); |
414 | } else if (response instanceof WriteResponse) { | 469 | } else if (response instanceof WriteResponse) { |
415 | - log.info("[{}] Path [{}] WriteResponse 9_Send", pathIdVer, response); | 470 | + log.warn("[{}] Path [{}] WriteResponse 9_Send", pathIdVer, response); |
416 | this.infoWriteResponse(registration, response, request); | 471 | this.infoWriteResponse(registration, response, request); |
417 | - serviceImpl.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request); | 472 | + handler.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request); |
418 | } | 473 | } |
419 | if (rpcRequest != null) { | 474 | if (rpcRequest != null) { |
420 | if (response instanceof ExecuteResponse | 475 | if (response instanceof ExecuteResponse |
421 | || response instanceof WriteAttributesResponse | 476 | || response instanceof WriteAttributesResponse |
422 | || response instanceof DeleteResponse) { | 477 | || response instanceof DeleteResponse) { |
423 | rpcRequest.setInfoMsg(null); | 478 | rpcRequest.setInfoMsg(null); |
424 | - serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, null); | 479 | + handler.sentRpcRequest(rpcRequest, response.getCode().getName(), null, null); |
425 | } else if (response instanceof WriteResponse) { | 480 | } else if (response instanceof WriteResponse) { |
426 | - serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, LOG_LW2M_INFO); | 481 | + handler.sentRpcRequest(rpcRequest, response.getCode().getName(), null, LOG_LW2M_INFO); |
427 | } | 482 | } |
428 | } | 483 | } |
429 | } | 484 | } |
@@ -447,21 +502,73 @@ public class LwM2mTransportRequest { | @@ -447,21 +502,73 @@ public class LwM2mTransportRequest { | ||
447 | Math.min(valueLength, config.getLogMaxLength()))); | 502 | Math.min(valueLength, config.getLogMaxLength()))); |
448 | } | 503 | } |
449 | value = valueLength > config.getLogMaxLength() ? value + "..." : value; | 504 | value = valueLength > config.getLogMaxLength() ? value + "..." : value; |
450 | - msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path - %s length - %s value - %s", | 505 | + msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path: %s length: %s value: %s", |
451 | LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), valueLength, value); | 506 | LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), valueLength, value); |
452 | } else { | 507 | } else { |
453 | value = this.converter.convertValue(singleResource.getValue(), | 508 | value = this.converter.convertValue(singleResource.getValue(), |
454 | singleResource.getType(), ResourceModel.Type.STRING, request.getPath()); | 509 | singleResource.getType(), ResourceModel.Type.STRING, request.getPath()); |
455 | - msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path - %s value - %s", | 510 | + msg = String.format("%s: Update finished successfully. Lwm2m code: %d Resource path: %s value: %s", |
456 | LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), value); | 511 | LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), value); |
457 | } | 512 | } |
458 | if (msg != null) { | 513 | if (msg != null) { |
459 | - serviceImpl.sendLogsToThingsboard(msg, registration.getId()); | ||
460 | - log.warn("[{}] [{}] [{}] - [{}] [{}] Update finished successfully: [{}]", request.getClass().getName(), registration.getEndpoint(), | ||
461 | - ((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString(), value); | 514 | + handler.sendLogsToThingsboard(msg, registration.getId()); |
515 | + if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { | ||
516 | + this.afterWriteSuccessFwSwUpdate(registration, request); | ||
517 | + } | ||
462 | } | 518 | } |
463 | } catch (Exception e) { | 519 | } catch (Exception e) { |
464 | log.trace("Fail convert value from request to string. ", e); | 520 | log.trace("Fail convert value from request to string. ", e); |
465 | } | 521 | } |
466 | } | 522 | } |
523 | + | ||
524 | + /** | ||
525 | + * After finish operation FwSwUpdate Write (success): | ||
526 | + * fw_state/sw_state = DOWNLOADED | ||
527 | + * send operation Execute | ||
528 | + */ | ||
529 | + private void afterWriteSuccessFwSwUpdate(Registration registration, DownlinkRequest request) { | ||
530 | + LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); | ||
531 | + if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) { | ||
532 | + lwM2MClient.getFwUpdate().setStateUpdate(DOWNLOADED.name()); | ||
533 | + lwM2MClient.getFwUpdate().sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null); | ||
534 | + } | ||
535 | + if (request.getPath().toString().equals(SW_PACKAGE_ID) && lwM2MClient.getSwUpdate() != null) { | ||
536 | + lwM2MClient.getSwUpdate().setStateUpdate(DOWNLOADED.name()); | ||
537 | + lwM2MClient.getSwUpdate().sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null); | ||
538 | + } | ||
539 | + } | ||
540 | + | ||
541 | + /** | ||
542 | + * After finish operation FwSwUpdate Write (error): fw_state = FAILED | ||
543 | + */ | ||
544 | + private void afterWriteFwSWUpdateError(Registration registration, DownlinkRequest request, String msgError) { | ||
545 | + LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); | ||
546 | + if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) { | ||
547 | + lwM2MClient.getFwUpdate().setStateUpdate(FAILED.name()); | ||
548 | + lwM2MClient.getFwUpdate().sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError); | ||
549 | + } | ||
550 | + if (request.getPath().toString().equals(SW_PACKAGE_ID) && lwM2MClient.getSwUpdate() != null) { | ||
551 | + lwM2MClient.getSwUpdate().setStateUpdate(FAILED.name()); | ||
552 | + lwM2MClient.getSwUpdate().sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError); | ||
553 | + } | ||
554 | + } | ||
555 | + | ||
556 | + private void afterExecuteFwSwUpdateError(Registration registration, DownlinkRequest request, String msgError) { | ||
557 | + LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); | ||
558 | + if (request.getPath().toString().equals(FW_UPDATE_ID) && lwM2MClient.getFwUpdate() != null) { | ||
559 | + lwM2MClient.getFwUpdate().sendLogs(handler, EXECUTE.name(), LOG_LW2M_ERROR, msgError); | ||
560 | + } | ||
561 | + if (request.getPath().toString().equals(SW_INSTALL_ID) && lwM2MClient.getSwUpdate() != null) { | ||
562 | + lwM2MClient.getSwUpdate().sendLogs(handler, EXECUTE.name(), LOG_LW2M_ERROR, msgError); | ||
563 | + } | ||
564 | + } | ||
565 | + | ||
566 | + private void afterObserveCancel(Registration registration, int observeCancelCnt, String observeCancelMsg, Lwm2mClientRpcRequest rpcRequest) { | ||
567 | + handler.sendLogsToThingsboard(observeCancelMsg, registration.getId()); | ||
568 | + log.warn("[{}]", observeCancelMsg); | ||
569 | + if (rpcRequest != null) { | ||
570 | + rpcRequest.setInfoMsg(String.format("Count: %d", observeCancelCnt)); | ||
571 | + handler.sentRpcRequest(rpcRequest, CONTENT.name(), null, LOG_LW2M_INFO); | ||
572 | + } | ||
573 | + } | ||
467 | } | 574 | } |
@@ -38,6 +38,7 @@ import org.eclipse.leshan.core.model.InvalidDDFFileException; | @@ -38,6 +38,7 @@ import org.eclipse.leshan.core.model.InvalidDDFFileException; | ||
38 | import org.eclipse.leshan.core.model.ObjectModel; | 38 | import org.eclipse.leshan.core.model.ObjectModel; |
39 | import org.eclipse.leshan.core.model.ResourceModel; | 39 | import org.eclipse.leshan.core.model.ResourceModel; |
40 | import org.eclipse.leshan.core.node.codec.CodecException; | 40 | import org.eclipse.leshan.core.node.codec.CodecException; |
41 | +import org.eclipse.leshan.core.request.ContentFormat; | ||
41 | import org.springframework.stereotype.Component; | 42 | import org.springframework.stereotype.Component; |
42 | import org.thingsboard.server.common.transport.TransportServiceCallback; | 43 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
43 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; | 44 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
@@ -54,7 +55,6 @@ import java.util.ArrayList; | @@ -54,7 +55,6 @@ import java.util.ArrayList; | ||
54 | import java.util.List; | 55 | import java.util.List; |
55 | 56 | ||
56 | import static org.thingsboard.server.gen.transport.TransportProtos.KeyValueType.BOOLEAN_V; | 57 | import static org.thingsboard.server.gen.transport.TransportProtos.KeyValueType.BOOLEAN_V; |
57 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_TELEMETRY; | ||
58 | 58 | ||
59 | @Slf4j | 59 | @Slf4j |
60 | @Component | 60 | @Component |
@@ -69,7 +69,7 @@ public class LwM2mTransportServerHelper { | @@ -69,7 +69,7 @@ public class LwM2mTransportServerHelper { | ||
69 | * send to Thingsboard Attribute || Telemetry | 69 | * send to Thingsboard Attribute || Telemetry |
70 | * | 70 | * |
71 | * @param msg - JsonObject: [{name: value}] | 71 | * @param msg - JsonObject: [{name: value}] |
72 | - * @return - dummy | 72 | + * @return - dummyWriteReplace {\"targetIdVer\":\"/19_1.0/0/0\",\"value\":0082} |
73 | */ | 73 | */ |
74 | private <T> TransportServiceCallback<Void> getPubAckCallbackSendAttrTelemetry(final T msg) { | 74 | private <T> TransportServiceCallback<Void> getPubAckCallbackSendAttrTelemetry(final T msg) { |
75 | return new TransportServiceCallback<>() { | 75 | return new TransportServiceCallback<>() { |
@@ -136,16 +136,16 @@ public class LwM2mTransportServerHelper { | @@ -136,16 +136,16 @@ public class LwM2mTransportServerHelper { | ||
136 | } | 136 | } |
137 | 137 | ||
138 | /** | 138 | /** |
139 | - * | ||
140 | - * @param logMsg - info about Logs | 139 | + * @param value - info about Logs |
141 | * @return- KeyValueProto for telemetry (Logs) | 140 | * @return- KeyValueProto for telemetry (Logs) |
142 | */ | 141 | */ |
143 | - public List<TransportProtos.KeyValueProto> getKvLogyToThingsboard(String logMsg) { | 142 | + public List<TransportProtos.KeyValueProto> getKvStringtoThingsboard(String key, String value) { |
144 | List<TransportProtos.KeyValueProto> result = new ArrayList<>(); | 143 | List<TransportProtos.KeyValueProto> result = new ArrayList<>(); |
144 | + value = value.replaceAll("<", "").replaceAll(">", ""); | ||
145 | result.add(TransportProtos.KeyValueProto.newBuilder() | 145 | result.add(TransportProtos.KeyValueProto.newBuilder() |
146 | - .setKey(LOG_LW2M_TELEMETRY) | 146 | + .setKey(key) |
147 | .setType(TransportProtos.KeyValueType.STRING_V) | 147 | .setType(TransportProtos.KeyValueType.STRING_V) |
148 | - .setStringV(logMsg).build()); | 148 | + .setStringV(value).build()); |
149 | return result; | 149 | return result; |
150 | } | 150 | } |
151 | 151 | ||
@@ -181,8 +181,7 @@ public class LwM2mTransportServerHelper { | @@ -181,8 +181,7 @@ public class LwM2mTransportServerHelper { | ||
181 | } | 181 | } |
182 | 182 | ||
183 | /** | 183 | /** |
184 | - * | ||
185 | - * @param currentType - | 184 | + * @param currentType - |
186 | * @param resourcePath - | 185 | * @param resourcePath - |
187 | * @return | 186 | * @return |
188 | */ | 187 | */ |
@@ -204,6 +203,28 @@ public class LwM2mTransportServerHelper { | @@ -204,6 +203,28 @@ public class LwM2mTransportServerHelper { | ||
204 | throw new CodecException("Invalid ResourceModel_Type for resource %s, got %s", resourcePath, currentType); | 203 | throw new CodecException("Invalid ResourceModel_Type for resource %s, got %s", resourcePath, currentType); |
205 | } | 204 | } |
206 | 205 | ||
206 | + public static ContentFormat convertResourceModelTypeToContentFormat(ResourceModel.Type type) { | ||
207 | + switch (type) { | ||
208 | + case BOOLEAN: | ||
209 | + case STRING: | ||
210 | + case TIME: | ||
211 | + case INTEGER: | ||
212 | + case FLOAT: | ||
213 | + return ContentFormat.TLV; | ||
214 | + case OPAQUE: | ||
215 | + return ContentFormat.OPAQUE; | ||
216 | + case OBJLNK: | ||
217 | + return ContentFormat.LINK; | ||
218 | + default: | ||
219 | + } | ||
220 | + throw new CodecException("Invalid ResourceModel_Type for %s ContentFormat.", type); | ||
221 | + } | ||
222 | + | ||
223 | + public static ContentFormat getContentFormatByResourceModelType(ResourceModel resourceModel, ContentFormat contentFormat) { | ||
224 | + return contentFormat.equals(ContentFormat.TLV) ? convertResourceModelTypeToContentFormat(resourceModel.type) : | ||
225 | + contentFormat; | ||
226 | + } | ||
227 | + | ||
207 | public static Object getValueFromKvProto(TransportProtos.KeyValueProto kv) { | 228 | public static Object getValueFromKvProto(TransportProtos.KeyValueProto kv) { |
208 | switch (kv.getType()) { | 229 | switch (kv.getType()) { |
209 | case BOOLEAN_V: | 230 | case BOOLEAN_V: |
@@ -43,6 +43,7 @@ import org.eclipse.leshan.server.registration.Registration; | @@ -43,6 +43,7 @@ import org.eclipse.leshan.server.registration.Registration; | ||
43 | import org.nustaq.serialization.FSTConfiguration; | 43 | import org.nustaq.serialization.FSTConfiguration; |
44 | import org.thingsboard.server.common.data.DeviceProfile; | 44 | import org.thingsboard.server.common.data.DeviceProfile; |
45 | import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; | 45 | import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; |
46 | +import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus; | ||
46 | import org.thingsboard.server.common.data.id.TenantId; | 47 | import org.thingsboard.server.common.data.id.TenantId; |
47 | import org.thingsboard.server.common.transport.TransportServiceCallback; | 48 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
48 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; | 49 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
@@ -70,6 +71,12 @@ import static org.eclipse.leshan.core.model.ResourceModel.Type.OBJLNK; | @@ -70,6 +71,12 @@ import static org.eclipse.leshan.core.model.ResourceModel.Type.OBJLNK; | ||
70 | import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; | 71 | import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; |
71 | import static org.eclipse.leshan.core.model.ResourceModel.Type.STRING; | 72 | import static org.eclipse.leshan.core.model.ResourceModel.Type.STRING; |
72 | import static org.eclipse.leshan.core.model.ResourceModel.Type.TIME; | 73 | import static org.eclipse.leshan.core.model.ResourceModel.Type.TIME; |
74 | +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.DOWNLOADED; | ||
75 | +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.DOWNLOADING; | ||
76 | +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.FAILED; | ||
77 | +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.UPDATED; | ||
78 | +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.UPDATING; | ||
79 | +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.VERIFIED; | ||
73 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; | 80 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; |
74 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; | 81 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; |
75 | 82 | ||
@@ -97,7 +104,8 @@ public class LwM2mTransportUtil { | @@ -97,7 +104,8 @@ public class LwM2mTransportUtil { | ||
97 | 104 | ||
98 | public static final long DEFAULT_TIMEOUT = 2 * 60 * 1000L; // 2min in ms | 105 | public static final long DEFAULT_TIMEOUT = 2 * 60 * 1000L; // 2min in ms |
99 | 106 | ||
100 | - public static final String LOG_LW2M_TELEMETRY = "logLwm2m"; | 107 | + public static final String |
108 | + LOG_LW2M_TELEMETRY = "LwM2MLog"; | ||
101 | public static final String LOG_LW2M_INFO = "info"; | 109 | public static final String LOG_LW2M_INFO = "info"; |
102 | public static final String LOG_LW2M_ERROR = "error"; | 110 | public static final String LOG_LW2M_ERROR = "error"; |
103 | public static final String LOG_LW2M_WARN = "warn"; | 111 | public static final String LOG_LW2M_WARN = "warn"; |
@@ -107,11 +115,41 @@ public class LwM2mTransportUtil { | @@ -107,11 +115,41 @@ public class LwM2mTransportUtil { | ||
107 | public static final int LWM2M_STRATEGY_2 = 2; | 115 | public static final int LWM2M_STRATEGY_2 = 2; |
108 | 116 | ||
109 | public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized"; | 117 | public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized"; |
110 | - | ||
111 | - public static final Integer FR_OBJECT_ID = 5; | ||
112 | - public static final Integer FR_RESOURCE_VER_ID = 7; | ||
113 | - public static final String FR_PATH_RESOURCE_VER_ID = LWM2M_SEPARATOR_PATH + FR_OBJECT_ID + LWM2M_SEPARATOR_PATH | ||
114 | - + "0" + LWM2M_SEPARATOR_PATH + FR_RESOURCE_VER_ID; | 118 | + public static final String LWM2M_VERSION_DEFAULT = "1.0"; |
119 | + | ||
120 | + // FirmWare | ||
121 | + public static final String FW_UPDATE = "Firmware update"; | ||
122 | + public static final Integer FW_ID = 5; | ||
123 | + // Package W | ||
124 | + public static final String FW_PACKAGE_ID = "/5/0/0"; | ||
125 | + // State R | ||
126 | + public static final String FW_STATE_ID = "/5/0/3"; | ||
127 | + // Update Result R | ||
128 | + public static final String FW_RESULT_ID = "/5/0/5"; | ||
129 | + // PkgName R | ||
130 | + public static final String FW_NAME_ID = "/5/0/6"; | ||
131 | + // PkgVersion R | ||
132 | + public static final String FW_VER_ID = "/5/0/7"; | ||
133 | + // Update E | ||
134 | + public static final String FW_UPDATE_ID = "/5/0/2"; | ||
135 | + | ||
136 | + // SoftWare | ||
137 | + public static final String SW_UPDATE = "Software update"; | ||
138 | + public static final Integer SW_ID = 9; | ||
139 | + // Package W | ||
140 | + public static final String SW_PACKAGE_ID = "/9/0/2"; | ||
141 | + // Update State R | ||
142 | + public static final String SW_UPDATE_STATE_ID = "/9/0/7"; | ||
143 | + // Update Result R | ||
144 | + public static final String SW_RESULT_ID = "/9/0/9"; | ||
145 | + // PkgName R | ||
146 | + public static final String SW_NAME_ID = "/9/0/0"; | ||
147 | + // PkgVersion R | ||
148 | + public static final String SW_VER_ID = "/9/0/1"; | ||
149 | + // Install E | ||
150 | + public static final String SW_INSTALL_ID = "/9/0/4"; | ||
151 | + // Uninstall E | ||
152 | + public static final String SW_UN_INSTALL_ID = "/9/0/6"; | ||
115 | 153 | ||
116 | public enum LwM2mTypeServer { | 154 | public enum LwM2mTypeServer { |
117 | BOOTSTRAP(0, "bootstrap"), | 155 | BOOTSTRAP(0, "bootstrap"), |
@@ -144,19 +182,20 @@ public class LwM2mTransportUtil { | @@ -144,19 +182,20 @@ public class LwM2mTransportUtil { | ||
144 | */ | 182 | */ |
145 | READ(0, "Read"), | 183 | READ(0, "Read"), |
146 | DISCOVER(1, "Discover"), | 184 | DISCOVER(1, "Discover"), |
147 | - OBSERVE_READ_ALL(2, "ObserveReadAll"), | 185 | + DISCOVER_All(2, "DiscoverAll"), |
186 | + OBSERVE_READ_ALL(3, "ObserveReadAll"), | ||
148 | /** | 187 | /** |
149 | * POST | 188 | * POST |
150 | */ | 189 | */ |
151 | - OBSERVE(3, "Observe"), | ||
152 | - OBSERVE_CANCEL(4, "ObserveCancel"), | ||
153 | - EXECUTE(5, "Execute"), | 190 | + OBSERVE(4, "Observe"), |
191 | + OBSERVE_CANCEL(5, "ObserveCancel"), | ||
192 | + EXECUTE(6, "Execute"), | ||
154 | /** | 193 | /** |
155 | * Replaces the Object Instance or the Resource(s) with the new value provided in the “Write” operation. (see | 194 | * Replaces the Object Instance or the Resource(s) with the new value provided in the “Write” operation. (see |
156 | * section 5.3.3 of the LW M2M spec). | 195 | * section 5.3.3 of the LW M2M spec). |
157 | * if all resources are to be replaced | 196 | * if all resources are to be replaced |
158 | */ | 197 | */ |
159 | - WRITE_REPLACE(6, "WriteReplace"), | 198 | + WRITE_REPLACE(7, "WriteReplace"), |
160 | /* | 199 | /* |
161 | PUT | 200 | PUT |
162 | */ | 201 | */ |
@@ -165,11 +204,18 @@ public class LwM2mTransportUtil { | @@ -165,11 +204,18 @@ public class LwM2mTransportUtil { | ||
165 | * 5.3.3 of the LW M2M spec). | 204 | * 5.3.3 of the LW M2M spec). |
166 | * if this is a partial update request | 205 | * if this is a partial update request |
167 | */ | 206 | */ |
168 | - WRITE_UPDATE(7, "WriteUpdate"), | ||
169 | - WRITE_ATTRIBUTES(8, "WriteAttributes"), | ||
170 | - DELETE(9, "Delete"); | ||
171 | - | ||
172 | -// READ_INFO_FW(10, "ReadInfoFirmware"); | 207 | + WRITE_UPDATE(8, "WriteUpdate"), |
208 | + WRITE_ATTRIBUTES(9, "WriteAttributes"), | ||
209 | + DELETE(10, "Delete"), | ||
210 | + | ||
211 | + // only for RPC | ||
212 | + FW_READ_INFO(11, "FirmwareReadInfo"), | ||
213 | + FW_UPDATE(12, "FirmwareUpdate"), | ||
214 | + FW_UPDATE_URL(14, "FirmwareUpdateUrl"), | ||
215 | + SW_READ_INFO(15, "SoftwareReadInfo"), | ||
216 | + SW_UPDATE(16, "SoftwareUpdate"), | ||
217 | + SW_UPDATE_URL(17, "SoftwareUpdateUrl"), | ||
218 | + SW_UNINSTALL(18, "SoftwareUninstall"); | ||
173 | 219 | ||
174 | public int code; | 220 | public int code; |
175 | public String type; | 221 | public String type; |
@@ -189,10 +235,290 @@ public class LwM2mTransportUtil { | @@ -189,10 +235,290 @@ public class LwM2mTransportUtil { | ||
189 | } | 235 | } |
190 | } | 236 | } |
191 | 237 | ||
238 | + /** | ||
239 | + * /** State R | ||
240 | + * 0: Idle (before downloading or after successful updating) | ||
241 | + * 1: Downloading (The data sequence is on the way) | ||
242 | + * 2: Downloaded | ||
243 | + * 3: Updating | ||
244 | + */ | ||
245 | + public enum StateFw { | ||
246 | + IDLE(0, "Idle"), | ||
247 | + DOWNLOADING(1, "Downloading"), | ||
248 | + DOWNLOADED(2, "Downloaded"), | ||
249 | + UPDATING(3, "Updating"); | ||
250 | + | ||
251 | + public int code; | ||
252 | + public String type; | ||
253 | + | ||
254 | + StateFw(int code, String type) { | ||
255 | + this.code = code; | ||
256 | + this.type = type; | ||
257 | + } | ||
258 | + | ||
259 | + public static StateFw fromStateFwByType(String type) { | ||
260 | + for (StateFw to : StateFw.values()) { | ||
261 | + if (to.type.equals(type)) { | ||
262 | + return to; | ||
263 | + } | ||
264 | + } | ||
265 | + throw new IllegalArgumentException(String.format("Unsupported FW State type : %s", type)); | ||
266 | + } | ||
267 | + | ||
268 | + public static StateFw fromStateFwByCode(int code) { | ||
269 | + for (StateFw to : StateFw.values()) { | ||
270 | + if (to.code == code) { | ||
271 | + return to; | ||
272 | + } | ||
273 | + } | ||
274 | + throw new IllegalArgumentException(String.format("Unsupported FW State code : %s", code)); | ||
275 | + } | ||
276 | + } | ||
277 | + | ||
278 | + /** | ||
279 | + * FW Update Result | ||
280 | + * 0: Initial value. Once the updating process is initiated (Download /Update), this Resource MUST be reset to Initial value. | ||
281 | + * 1: Firmware updated successfully. | ||
282 | + * 2: Not enough flash memory for the new firmware package. | ||
283 | + * 3: Out of RAM during downloading process. | ||
284 | + * 4: Connection lost during downloading process. | ||
285 | + * 5: Integrity check failure for new downloaded package. | ||
286 | + * 6: Unsupported package type. | ||
287 | + * 7: Invalid URI. | ||
288 | + * 8: Firmware update failed. | ||
289 | + * 9: Unsupported protocol. | ||
290 | + */ | ||
291 | + public enum UpdateResultFw { | ||
292 | + INITIAL(0, "Initial value", false), | ||
293 | + UPDATE_SUCCESSFULLY(1, "Firmware updated successfully", false), | ||
294 | + NOT_ENOUGH(2, "Not enough flash memory for the new firmware package", false), | ||
295 | + OUT_OFF_MEMORY(3, "Out of RAM during downloading process", false), | ||
296 | + CONNECTION_LOST(4, "Connection lost during downloading process", true), | ||
297 | + INTEGRITY_CHECK_FAILURE(5, "Integrity check failure for new downloaded package", true), | ||
298 | + UNSUPPORTED_TYPE(6, "Unsupported package type", false), | ||
299 | + INVALID_URI(7, "Invalid URI", false), | ||
300 | + UPDATE_FAILED(8, "Firmware update failed", false), | ||
301 | + UNSUPPORTED_PROTOCOL(9, "Unsupported protocol", false); | ||
302 | + | ||
303 | + public int code; | ||
304 | + public String type; | ||
305 | + public boolean isAgain; | ||
306 | + | ||
307 | + UpdateResultFw(int code, String type, boolean isAgain) { | ||
308 | + this.code = code; | ||
309 | + this.type = type; | ||
310 | + this.isAgain = isAgain; | ||
311 | + } | ||
312 | + | ||
313 | + public static UpdateResultFw fromUpdateResultFwByType(String type) { | ||
314 | + for (UpdateResultFw to : UpdateResultFw.values()) { | ||
315 | + if (to.type.equals(type)) { | ||
316 | + return to; | ||
317 | + } | ||
318 | + } | ||
319 | + throw new IllegalArgumentException(String.format("Unsupported FW Update Result type : %s", type)); | ||
320 | + } | ||
321 | + | ||
322 | + public static UpdateResultFw fromUpdateResultFwByCode(int code) { | ||
323 | + for (UpdateResultFw to : UpdateResultFw.values()) { | ||
324 | + if (to.code == code) { | ||
325 | + return to; | ||
326 | + } | ||
327 | + } | ||
328 | + throw new IllegalArgumentException(String.format("Unsupported FW Update Result code : %s", code)); | ||
329 | + } | ||
330 | + } | ||
331 | + | ||
332 | + /** | ||
333 | + * FirmwareUpdateStatus { | ||
334 | + * DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED | ||
335 | + */ | ||
336 | + public static FirmwareUpdateStatus EqualsFwSateToFirmwareUpdateStatus(StateFw stateFw, UpdateResultFw updateResultFw) { | ||
337 | + switch (updateResultFw) { | ||
338 | + case INITIAL: | ||
339 | + switch (stateFw) { | ||
340 | + case IDLE: | ||
341 | + return VERIFIED; | ||
342 | + case DOWNLOADING: | ||
343 | + return DOWNLOADING; | ||
344 | + case DOWNLOADED: | ||
345 | + return DOWNLOADED; | ||
346 | + case UPDATING: | ||
347 | + return UPDATING; | ||
348 | + } | ||
349 | + case UPDATE_SUCCESSFULLY: | ||
350 | + return UPDATED; | ||
351 | + case NOT_ENOUGH: | ||
352 | + case OUT_OFF_MEMORY: | ||
353 | + case CONNECTION_LOST: | ||
354 | + case INTEGRITY_CHECK_FAILURE: | ||
355 | + case UNSUPPORTED_TYPE: | ||
356 | + case INVALID_URI: | ||
357 | + case UPDATE_FAILED: | ||
358 | + case UNSUPPORTED_PROTOCOL: | ||
359 | + return FAILED; | ||
360 | + default: | ||
361 | + throw new CodecException("Invalid value stateFw %s %s for FirmwareUpdateStatus.", stateFw.name(), updateResultFw.name()); | ||
362 | + } | ||
363 | + } | ||
364 | + | ||
365 | + /** | ||
366 | + * SW Update State R | ||
367 | + * 0: INITIAL Before downloading. (see 5.1.2.1) | ||
368 | + * 1: DOWNLOAD STARTED The downloading process has started and is on-going. (see 5.1.2.2) | ||
369 | + * 2: DOWNLOADED The package has been completely downloaded (see 5.1.2.3) | ||
370 | + * 3: DELIVERED In that state, the package has been correctly downloaded and is ready to be installed. (see 5.1.2.4) | ||
371 | + * If executing the Install Resource failed, the state remains at DELIVERED. | ||
372 | + * If executing the Install Resource was successful, the state changes from DELIVERED to INSTALLED. | ||
373 | + * After executing the UnInstall Resource, the state changes to INITIAL. | ||
374 | + * 4: INSTALLED | ||
375 | + */ | ||
376 | + public enum UpdateStateSw { | ||
377 | + INITIAL(0, "Initial"), | ||
378 | + DOWNLOAD_STARTED(1, "DownloadStarted"), | ||
379 | + DOWNLOADED(2, "Downloaded"), | ||
380 | + DELIVERED(3, "Delivered"), | ||
381 | + INSTALLED(4, "Installed"); | ||
382 | + | ||
383 | + public int code; | ||
384 | + public String type; | ||
385 | + | ||
386 | + UpdateStateSw(int code, String type) { | ||
387 | + this.code = code; | ||
388 | + this.type = type; | ||
389 | + } | ||
390 | + | ||
391 | + public static UpdateStateSw fromUpdateStateSwByType(String type) { | ||
392 | + for (UpdateStateSw to : UpdateStateSw.values()) { | ||
393 | + if (to.type.equals(type)) { | ||
394 | + return to; | ||
395 | + } | ||
396 | + } | ||
397 | + throw new IllegalArgumentException(String.format("Unsupported SW State type : %s", type)); | ||
398 | + } | ||
399 | + | ||
400 | + public static UpdateStateSw fromUpdateStateSwByCode(int code) { | ||
401 | + for (UpdateStateSw to : UpdateStateSw.values()) { | ||
402 | + if (to.code == code) { | ||
403 | + return to; | ||
404 | + } | ||
405 | + } | ||
406 | + throw new IllegalArgumentException(String.format("Unsupported SW State type : %s", code)); | ||
407 | + } | ||
408 | + } | ||
409 | + | ||
410 | + /** | ||
411 | + * SW Update Result | ||
412 | + * Contains the result of downloading or installing/uninstalling the software | ||
413 | + * 0: Initial value. | ||
414 | + * - Prior to download any new package in the Device, Update Result MUST be reset to this initial value. | ||
415 | + * - One side effect of executing the Uninstall resource is to reset Update Result to this initial value "0". | ||
416 | + * 1: Downloading. | ||
417 | + * - The package downloading process is on-going. | ||
418 | + * 2: Software successfully installed. | ||
419 | + * 3: Successfully Downloaded and package integrity verified | ||
420 | + * (( 4-49, for expansion, of other scenarios)) | ||
421 | + * ** Failed | ||
422 | + * 50: Not enough storage for the new software package. | ||
423 | + * 51: Out of memory during downloading process. | ||
424 | + * 52: Connection lost during downloading process. | ||
425 | + * 53: Package integrity check failure. | ||
426 | + * 54: Unsupported package type. | ||
427 | + * 56: Invalid URI | ||
428 | + * 57: Device defined update error | ||
429 | + * 58: Software installation failure | ||
430 | + * 59: Uninstallation Failure during forUpdate(arg=0) | ||
431 | + * 60-200 : (for expansion, selection to be in blocks depending on new introduction of features) | ||
432 | + * This Resource MAY be reported by sending Observe operation. | ||
433 | + */ | ||
434 | + public enum UpdateResultSw { | ||
435 | + INITIAL(0, "Initial value", false), | ||
436 | + DOWNLOADING(1, "Downloading", false), | ||
437 | + SUCCESSFULLY_INSTALLED(2, "Software successfully installed", false), | ||
438 | + SUCCESSFULLY_DOWNLOADED_VERIFIED(3, "Successfully Downloaded and package integrity verified", false), | ||
439 | + NOT_ENOUGH_STORAGE(50, "Not enough storage for the new software package", true), | ||
440 | + OUT_OFF_MEMORY(51, "Out of memory during downloading process", true), | ||
441 | + CONNECTION_LOST(52, "Connection lost during downloading process", false), | ||
442 | + PACKAGE_CHECK_FAILURE(53, "Package integrity check failure.", false), | ||
443 | + UNSUPPORTED_PACKAGE_TYPE(54, "Unsupported package type", false), | ||
444 | + INVALID_URI(56, "Invalid URI", true), | ||
445 | + UPDATE_ERROR(57, "Device defined update error", true), | ||
446 | + INSTALL_FAILURE(58, "Software installation failure", true), | ||
447 | + UN_INSTALL_FAILURE(59, "Uninstallation Failure during forUpdate(arg=0)", true); | ||
448 | + | ||
449 | + public int code; | ||
450 | + public String type; | ||
451 | + public boolean isAgain; | ||
452 | + | ||
453 | + UpdateResultSw(int code, String type, boolean isAgain) { | ||
454 | + this.code = code; | ||
455 | + this.type = type; | ||
456 | + this.isAgain = isAgain; | ||
457 | + } | ||
458 | + | ||
459 | + public static UpdateResultSw fromUpdateResultSwByType(String type) { | ||
460 | + for (UpdateResultSw to : UpdateResultSw.values()) { | ||
461 | + if (to.type.equals(type)) { | ||
462 | + return to; | ||
463 | + } | ||
464 | + } | ||
465 | + throw new IllegalArgumentException(String.format("Unsupported SW Update Result type : %s", type)); | ||
466 | + } | ||
467 | + | ||
468 | + public static UpdateResultSw fromUpdateResultSwByCode(int code) { | ||
469 | + for (UpdateResultSw to : UpdateResultSw.values()) { | ||
470 | + if (to.code == code) { | ||
471 | + return to; | ||
472 | + } | ||
473 | + } | ||
474 | + throw new IllegalArgumentException(String.format("Unsupported SW Update Result code : %s", code)); | ||
475 | + } | ||
476 | + } | ||
477 | + | ||
478 | + /** | ||
479 | + * FirmwareUpdateStatus { | ||
480 | + * DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED | ||
481 | + */ | ||
482 | + public static FirmwareUpdateStatus EqualsSwSateToFirmwareUpdateStatus(UpdateStateSw updateStateSw, UpdateResultSw updateResultSw) { | ||
483 | + switch (updateResultSw) { | ||
484 | + case INITIAL: | ||
485 | + switch (updateStateSw) { | ||
486 | + case INITIAL: | ||
487 | + case DOWNLOAD_STARTED: | ||
488 | + return DOWNLOADING; | ||
489 | + case DOWNLOADED: | ||
490 | + return DOWNLOADED; | ||
491 | + case DELIVERED: | ||
492 | + return VERIFIED; | ||
493 | + } | ||
494 | + case DOWNLOADING: | ||
495 | + return DOWNLOADING; | ||
496 | + case SUCCESSFULLY_INSTALLED: | ||
497 | + return UPDATED; | ||
498 | + case SUCCESSFULLY_DOWNLOADED_VERIFIED: | ||
499 | + return VERIFIED; | ||
500 | + case NOT_ENOUGH_STORAGE: | ||
501 | + case OUT_OFF_MEMORY: | ||
502 | + case CONNECTION_LOST: | ||
503 | + case PACKAGE_CHECK_FAILURE: | ||
504 | + case UNSUPPORTED_PACKAGE_TYPE: | ||
505 | + case INVALID_URI: | ||
506 | + case UPDATE_ERROR: | ||
507 | + case INSTALL_FAILURE: | ||
508 | + case UN_INSTALL_FAILURE: | ||
509 | + return FAILED; | ||
510 | + default: | ||
511 | + throw new CodecException("Invalid value stateFw %s %s for FirmwareUpdateStatus.", updateStateSw.name(), updateResultSw.name()); | ||
512 | + } | ||
513 | + } | ||
514 | + | ||
192 | public static final String EVENT_AWAKE = "AWAKE"; | 515 | public static final String EVENT_AWAKE = "AWAKE"; |
516 | + public static final String RESPONSE_REQUEST_CHANNEL = "RESP_REQ"; | ||
193 | public static final String RESPONSE_CHANNEL = "RESP"; | 517 | public static final String RESPONSE_CHANNEL = "RESP"; |
518 | + public static final String OBSERVE_CHANNEL = "OBSERVE"; | ||
194 | 519 | ||
195 | - public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath resourcePath) throws CodecException { | 520 | + public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath |
521 | + resourcePath) throws CodecException { | ||
196 | switch (type) { | 522 | switch (type) { |
197 | case BOOLEAN: | 523 | case BOOLEAN: |
198 | case INTEGER: | 524 | case INTEGER: |
@@ -256,7 +582,7 @@ public class LwM2mTransportUtil { | @@ -256,7 +582,7 @@ public class LwM2mTransportUtil { | ||
256 | * "/3_1.0/0/9": {"pmax": 45}, "/3_1.2": {ver": "3_1.2"}} | 582 | * "/3_1.0/0/9": {"pmax": 45}, "/3_1.2": {ver": "3_1.2"}} |
257 | */ | 583 | */ |
258 | public static LwM2mClientProfile toLwM2MClientProfile(DeviceProfile deviceProfile) { | 584 | public static LwM2mClientProfile toLwM2MClientProfile(DeviceProfile deviceProfile) { |
259 | - if (deviceProfile != null && ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties().size() > 0) { | 585 | + if (((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties().size() > 0) { |
260 | Object profile = ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties(); | 586 | Object profile = ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties(); |
261 | try { | 587 | try { |
262 | ObjectMapper mapper = new ObjectMapper(); | 588 | ObjectMapper mapper = new ObjectMapper(); |
@@ -375,7 +701,8 @@ public class LwM2mTransportUtil { | @@ -375,7 +701,8 @@ public class LwM2mTransportUtil { | ||
375 | return StringUtils.join(linkedListOut, ""); | 701 | return StringUtils.join(linkedListOut, ""); |
376 | } | 702 | } |
377 | 703 | ||
378 | - public static <T> TransportServiceCallback<Void> getAckCallback(LwM2mClient lwM2MClient, int requestId, String typeTopic) { | 704 | + public static <T> TransportServiceCallback<Void> getAckCallback(LwM2mClient lwM2MClient, |
705 | + int requestId, String typeTopic) { | ||
379 | return new TransportServiceCallback<Void>() { | 706 | return new TransportServiceCallback<Void>() { |
380 | @Override | 707 | @Override |
381 | public void onSuccess(Void dummy) { | 708 | public void onSuccess(Void dummy) { |
@@ -420,7 +747,8 @@ public class LwM2mTransportUtil { | @@ -420,7 +747,8 @@ public class LwM2mTransportUtil { | ||
420 | return null; | 747 | return null; |
421 | } | 748 | } |
422 | 749 | ||
423 | - public static String validPathIdVer(String pathIdVer, Registration registration) throws IllegalArgumentException { | 750 | + public static String validPathIdVer(String pathIdVer, Registration registration) throws |
751 | + IllegalArgumentException { | ||
424 | if (!pathIdVer.contains(LWM2M_SEPARATOR_PATH)) { | 752 | if (!pathIdVer.contains(LWM2M_SEPARATOR_PATH)) { |
425 | throw new IllegalArgumentException(String.format("Error:")); | 753 | throw new IllegalArgumentException(String.format("Error:")); |
426 | } else { | 754 | } else { |
@@ -436,6 +764,7 @@ public class LwM2mTransportUtil { | @@ -436,6 +764,7 @@ public class LwM2mTransportUtil { | ||
436 | 764 | ||
437 | public static String convertPathFromObjectIdToIdVer(String path, Registration registration) { | 765 | public static String convertPathFromObjectIdToIdVer(String path, Registration registration) { |
438 | String ver = registration.getSupportedObject().get(new LwM2mPath(path).getObjectId()); | 766 | String ver = registration.getSupportedObject().get(new LwM2mPath(path).getObjectId()); |
767 | + ver = ver != null ? ver : LWM2M_VERSION_DEFAULT; | ||
439 | try { | 768 | try { |
440 | String[] keyArray = path.split(LWM2M_SEPARATOR_PATH); | 769 | String[] keyArray = path.split(LWM2M_SEPARATOR_PATH); |
441 | if (keyArray.length > 1) { | 770 | if (keyArray.length > 1) { |
@@ -531,7 +860,7 @@ public class LwM2mTransportUtil { | @@ -531,7 +860,7 @@ public class LwM2mTransportUtil { | ||
531 | case "ObjectLink": | 860 | case "ObjectLink": |
532 | return OBJLNK; | 861 | return OBJLNK; |
533 | default: | 862 | default: |
534 | - return null; | 863 | + return null; |
535 | } | 864 | } |
536 | } | 865 | } |
537 | } | 866 | } |
@@ -82,7 +82,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { | @@ -82,7 +82,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { | ||
82 | if (objectModel != null) | 82 | if (objectModel != null) |
83 | return objectModel.resources.get(resourceId); | 83 | return objectModel.resources.get(resourceId); |
84 | else | 84 | else |
85 | - log.warn("TbResources (Object model) with id [{}/0/{}] not found on the server", objectId, resourceId); | 85 | + log.trace("TbResources (Object model) with id [{}/0/{}] not found on the server", objectId, resourceId); |
86 | return null; | 86 | return null; |
87 | } catch (Exception e) { | 87 | } catch (Exception e) { |
88 | log.error("", e); | 88 | log.error("", e); |
@@ -64,7 +64,6 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor { | @@ -64,7 +64,6 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor { | ||
64 | } | 64 | } |
65 | return result.build(); | 65 | return result.build(); |
66 | } catch (RuntimeException e) { | 66 | } catch (RuntimeException e) { |
67 | - log.warn("Failed to decode get attributes request", e); | ||
68 | throw new AdaptorException(e); | 67 | throw new AdaptorException(e); |
69 | } | 68 | } |
70 | } | 69 | } |
@@ -18,7 +18,11 @@ package org.thingsboard.server.transport.lwm2m.server.client; | @@ -18,7 +18,11 @@ package org.thingsboard.server.transport.lwm2m.server.client; | ||
18 | import lombok.Getter; | 18 | import lombok.Getter; |
19 | import lombok.Setter; | 19 | import lombok.Setter; |
20 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
21 | +import org.eclipse.leshan.core.model.ObjectModel; | ||
21 | import org.eclipse.leshan.core.model.ResourceModel; | 22 | import org.eclipse.leshan.core.model.ResourceModel; |
23 | +import org.eclipse.leshan.core.node.LwM2mMultipleResource; | ||
24 | +import org.eclipse.leshan.core.node.LwM2mObject; | ||
25 | +import org.eclipse.leshan.core.node.LwM2mObjectInstance; | ||
22 | import org.eclipse.leshan.core.node.LwM2mPath; | 26 | import org.eclipse.leshan.core.node.LwM2mPath; |
23 | import org.eclipse.leshan.core.node.LwM2mResource; | 27 | import org.eclipse.leshan.core.node.LwM2mResource; |
24 | import org.eclipse.leshan.core.node.LwM2mSingleResource; | 28 | import org.eclipse.leshan.core.node.LwM2mSingleResource; |
@@ -28,9 +32,9 @@ import org.eclipse.leshan.server.security.SecurityInfo; | @@ -28,9 +32,9 @@ import org.eclipse.leshan.server.security.SecurityInfo; | ||
28 | import org.thingsboard.server.common.data.Device; | 32 | import org.thingsboard.server.common.data.Device; |
29 | import org.thingsboard.server.common.data.DeviceProfile; | 33 | import org.thingsboard.server.common.data.DeviceProfile; |
30 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; | 34 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
35 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
31 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; | 36 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
32 | import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; | 37 | import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; |
33 | -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; | ||
34 | import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2MTransportMsgHandler; | 38 | import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2MTransportMsgHandler; |
35 | import org.thingsboard.server.transport.lwm2m.server.LwM2mQueuedRequest; | 39 | import org.thingsboard.server.transport.lwm2m.server.LwM2mQueuedRequest; |
36 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; | 40 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; |
@@ -47,11 +51,14 @@ import java.util.concurrent.ConcurrentLinkedQueue; | @@ -47,11 +51,14 @@ import java.util.concurrent.ConcurrentLinkedQueue; | ||
47 | import java.util.concurrent.CopyOnWriteArrayList; | 51 | import java.util.concurrent.CopyOnWriteArrayList; |
48 | import java.util.stream.Collectors; | 52 | import java.util.stream.Collectors; |
49 | 53 | ||
54 | +import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; | ||
55 | +import static org.eclipse.leshan.core.model.ResourceModel.Type.STRING; | ||
50 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; | 56 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; |
51 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.TRANSPORT_DEFAULT_LWM2M_VERSION; | 57 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.TRANSPORT_DEFAULT_LWM2M_VERSION; |
52 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId; | 58 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId; |
53 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getVerFromPathIdVerOrId; | 59 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; |
54 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.equalsResourceTypeGetSimpleName; | 60 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.equalsResourceTypeGetSimpleName; |
61 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getVerFromPathIdVerOrId; | ||
55 | 62 | ||
56 | @Slf4j | 63 | @Slf4j |
57 | public class LwM2mClient implements Cloneable { | 64 | public class LwM2mClient implements Cloneable { |
@@ -75,25 +82,27 @@ public class LwM2mClient implements Cloneable { | @@ -75,25 +82,27 @@ public class LwM2mClient implements Cloneable { | ||
75 | private UUID profileId; | 82 | private UUID profileId; |
76 | @Getter | 83 | @Getter |
77 | @Setter | 84 | @Setter |
78 | - private volatile LwM2mFirmwareUpdate frUpdate; | 85 | + private volatile LwM2mFwSwUpdate fwUpdate; |
86 | + @Getter | ||
87 | + @Setter | ||
88 | + private volatile LwM2mFwSwUpdate swUpdate; | ||
79 | @Getter | 89 | @Getter |
80 | @Setter | 90 | @Setter |
81 | private Registration registration; | 91 | private Registration registration; |
82 | 92 | ||
83 | private ValidateDeviceCredentialsResponse credentials; | 93 | private ValidateDeviceCredentialsResponse credentials; |
94 | + | ||
84 | @Getter | 95 | @Getter |
85 | private final Map<String, ResourceValue> resources; | 96 | private final Map<String, ResourceValue> resources; |
86 | @Getter | 97 | @Getter |
87 | private final Map<String, TsKvProto> delayedRequests; | 98 | private final Map<String, TsKvProto> delayedRequests; |
88 | @Getter | 99 | @Getter |
100 | + @Setter | ||
89 | private final List<String> pendingReadRequests; | 101 | private final List<String> pendingReadRequests; |
90 | @Getter | 102 | @Getter |
91 | private final Queue<LwM2mQueuedRequest> queuedRequests; | 103 | private final Queue<LwM2mQueuedRequest> queuedRequests; |
92 | @Getter | 104 | @Getter |
93 | private boolean init; | 105 | private boolean init; |
94 | - @Getter | ||
95 | - @Setter | ||
96 | - private volatile boolean updateFw; | ||
97 | 106 | ||
98 | public Object clone() throws CloneNotSupportedException { | 107 | public Object clone() throws CloneNotSupportedException { |
99 | return super.clone(); | 108 | return super.clone(); |
@@ -110,9 +119,10 @@ public class LwM2mClient implements Cloneable { | @@ -110,9 +119,10 @@ public class LwM2mClient implements Cloneable { | ||
110 | this.profileId = profileId; | 119 | this.profileId = profileId; |
111 | this.sessionId = sessionId; | 120 | this.sessionId = sessionId; |
112 | this.init = false; | 121 | this.init = false; |
113 | - this.updateFw = false; | ||
114 | this.queuedRequests = new ConcurrentLinkedQueue<>(); | 122 | this.queuedRequests = new ConcurrentLinkedQueue<>(); |
115 | - this.frUpdate = new LwM2mFirmwareUpdate(); | 123 | + |
124 | + this.fwUpdate = new LwM2mFwSwUpdate(this, FirmwareType.FIRMWARE); | ||
125 | + this.swUpdate = new LwM2mFwSwUpdate(this, FirmwareType.SOFTWARE); | ||
116 | if (this.credentials != null && this.credentials.hasDeviceInfo()) { | 126 | if (this.credentials != null && this.credentials.hasDeviceInfo()) { |
117 | this.session = createSession(nodeId, sessionId, credentials); | 127 | this.session = createSession(nodeId, sessionId, credentials); |
118 | this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB()); | 128 | this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB()); |
@@ -165,15 +175,15 @@ public class LwM2mClient implements Cloneable { | @@ -165,15 +175,15 @@ public class LwM2mClient implements Cloneable { | ||
165 | .build(); | 175 | .build(); |
166 | } | 176 | } |
167 | 177 | ||
168 | - public boolean saveResourceValue(String pathRez, LwM2mResource rez, LwM2mModelProvider modelProvider) { | ||
169 | - if (this.resources.get(pathRez) != null && this.resources.get(pathRez).getResourceModel() != null) { | ||
170 | - this.resources.get(pathRez).setLwM2mResource(rez); | 178 | + public boolean saveResourceValue(String pathRezIdVer, LwM2mResource rez, LwM2mModelProvider modelProvider) { |
179 | + if (this.resources.get(pathRezIdVer) != null && this.resources.get(pathRezIdVer).getResourceModel() != null) { | ||
180 | + this.resources.get(pathRezIdVer).setLwM2mResource(rez); | ||
171 | return true; | 181 | return true; |
172 | } else { | 182 | } else { |
173 | - LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez)); | 183 | + LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer)); |
174 | ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()); | 184 | ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()); |
175 | if (resourceModel != null) { | 185 | if (resourceModel != null) { |
176 | - this.resources.put(pathRez, new ResourceValue(rez, resourceModel)); | 186 | + this.resources.put(pathRezIdVer, new ResourceValue(rez, resourceModel)); |
177 | return true; | 187 | return true; |
178 | } else { | 188 | } else { |
179 | return false; | 189 | return false; |
@@ -181,6 +191,24 @@ public class LwM2mClient implements Cloneable { | @@ -181,6 +191,24 @@ public class LwM2mClient implements Cloneable { | ||
181 | } | 191 | } |
182 | } | 192 | } |
183 | 193 | ||
194 | + public Object getResourceValue(String pathRezIdVer, String pathRezId) { | ||
195 | + String pathRez = pathRezIdVer == null ? convertPathFromObjectIdToIdVer(pathRezId, this.registration) : pathRezIdVer; | ||
196 | + if (this.resources.get(pathRez) != null) { | ||
197 | + return this.resources.get(pathRez).getLwM2mResource().isMultiInstances() ? | ||
198 | + this.resources.get(pathRez).getLwM2mResource().getValues() : | ||
199 | + this.resources.get(pathRez).getLwM2mResource().getValue(); | ||
200 | + } | ||
201 | + return null; | ||
202 | + } | ||
203 | + | ||
204 | + public Object getResourceName (String pathRezIdVer, String pathRezId) { | ||
205 | + String pathRez = pathRezIdVer == null ? convertPathFromObjectIdToIdVer(pathRezId, this.registration) : pathRezIdVer; | ||
206 | + if (this.resources.get(pathRez) != null) { | ||
207 | + return this.resources.get(pathRez).getResourceModel().name; | ||
208 | + } | ||
209 | + return null; | ||
210 | + } | ||
211 | + | ||
184 | public ResourceModel getResourceModel(String pathIdVer, LwM2mModelProvider modelProvider) { | 212 | public ResourceModel getResourceModel(String pathIdVer, LwM2mModelProvider modelProvider) { |
185 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)); | 213 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)); |
186 | String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); | 214 | String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); |
@@ -189,8 +217,55 @@ public class LwM2mClient implements Cloneable { | @@ -189,8 +217,55 @@ public class LwM2mClient implements Cloneable { | ||
189 | .getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()) : null; | 217 | .getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()) : null; |
190 | } | 218 | } |
191 | 219 | ||
192 | - public Collection<LwM2mResource> getNewOneResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider, | ||
193 | - LwM2mValueConverterImpl converter) { | 220 | + public ObjectModel getObjectModel(String pathIdVer, LwM2mModelProvider modelProvider) { |
221 | + LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)); | ||
222 | + String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); | ||
223 | + String verRez = getVerFromPathIdVerOrId(pathIdVer); | ||
224 | + return verRez == null || verRez.equals(verSupportedObject) ? modelProvider.getObjectModel(registration) | ||
225 | + .getObjectModel(pathIds.getObjectId()) : null; | ||
226 | + } | ||
227 | + | ||
228 | + public String objectToString (LwM2mObject lwM2mObject, LwM2mValueConverterImpl converter, String pathIdVer) { | ||
229 | + StringBuilder builder = new StringBuilder(); | ||
230 | + builder.append("LwM2mObject [id=").append(lwM2mObject.getId()).append(", instances={"); | ||
231 | + lwM2mObject.getInstances().forEach((instId, inst) -> { | ||
232 | + builder.append(instId).append("=").append(this.instanceToString(inst, converter, pathIdVer)).append(", "); | ||
233 | + }); | ||
234 | + int startInd = builder.lastIndexOf(", "); | ||
235 | + if (startInd > 0) { | ||
236 | + builder.delete(startInd, startInd + 2); | ||
237 | + } | ||
238 | + builder.append("}]"); | ||
239 | + return builder.toString(); | ||
240 | + } | ||
241 | + public String instanceToString (LwM2mObjectInstance objectInstance, LwM2mValueConverterImpl converter, String pathIdVer) { | ||
242 | + StringBuilder builder = new StringBuilder(); | ||
243 | + builder.append("LwM2mObjectInstance [id=").append(objectInstance.getId()).append(", resources={"); | ||
244 | + objectInstance.getResources().forEach((resId, res) -> { | ||
245 | + builder.append(resId).append("=").append(this.resourceToString (res, converter, pathIdVer)).append(", "); | ||
246 | + }); | ||
247 | + int startInd = builder.lastIndexOf(", "); | ||
248 | + if (startInd > 0) { | ||
249 | + builder.delete(startInd, startInd + 2); | ||
250 | + } | ||
251 | + builder.append("}]"); | ||
252 | + return builder.toString(); | ||
253 | + } | ||
254 | + | ||
255 | + public String resourceToString (LwM2mResource lwM2mResource, LwM2mValueConverterImpl converter, String pathIdVer) { | ||
256 | + if (!OPAQUE.equals(lwM2mResource.getType())) { | ||
257 | + return lwM2mResource.isMultiInstances() ? ((LwM2mMultipleResource) lwM2mResource).toString() : | ||
258 | + ((LwM2mSingleResource) lwM2mResource).toString(); | ||
259 | + } | ||
260 | + else { | ||
261 | + return String.format("LwM2mSingleResource [id=%s, value=%s, type=%s]", lwM2mResource.getId(), | ||
262 | + converter.convertValue(lwM2mResource.getValue(), | ||
263 | + OPAQUE, STRING, new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))), lwM2mResource.getType().name()); | ||
264 | + } | ||
265 | + } | ||
266 | + | ||
267 | + public Collection<LwM2mResource> getNewResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider, | ||
268 | + LwM2mValueConverterImpl converter) { | ||
194 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer)); | 269 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer)); |
195 | Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet(); | 270 | Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet(); |
196 | Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration) | 271 | Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration) |
@@ -204,8 +279,8 @@ public class LwM2mClient implements Cloneable { | @@ -204,8 +279,8 @@ public class LwM2mClient implements Cloneable { | ||
204 | return resources; | 279 | return resources; |
205 | } | 280 | } |
206 | 281 | ||
207 | - public Collection<LwM2mResource> getNewManyResourcesForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider, | ||
208 | - LwM2mValueConverterImpl converter) { | 282 | + public Collection<LwM2mResource> getNewResourcesForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider, |
283 | + LwM2mValueConverterImpl converter) { | ||
209 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer)); | 284 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer)); |
210 | Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet(); | 285 | Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet(); |
211 | Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration) | 286 | Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration) |
@@ -55,7 +55,7 @@ public interface LwM2mClientContext { | @@ -55,7 +55,7 @@ public interface LwM2mClientContext { | ||
55 | 55 | ||
56 | Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles); | 56 | Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles); |
57 | 57 | ||
58 | - LwM2mClientProfile toClientProfile(DeviceProfile deviceProfile); | 58 | + LwM2mClientProfile profileUpdate(DeviceProfile deviceProfile); |
59 | 59 | ||
60 | Set<String> getSupportedIdVerInClient(Registration registration); | 60 | Set<String> getSupportedIdVerInClient(Registration registration); |
61 | 61 |
@@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
16 | package org.thingsboard.server.transport.lwm2m.server.client; | 16 | package org.thingsboard.server.transport.lwm2m.server.client; |
17 | 17 | ||
18 | import lombok.RequiredArgsConstructor; | 18 | import lombok.RequiredArgsConstructor; |
19 | +import lombok.extern.slf4j.Slf4j; | ||
19 | import org.eclipse.leshan.core.node.LwM2mPath; | 20 | import org.eclipse.leshan.core.node.LwM2mPath; |
20 | import org.eclipse.leshan.server.registration.Registration; | 21 | import org.eclipse.leshan.server.registration.Registration; |
21 | import org.eclipse.leshan.server.security.EditableSecurityStore; | 22 | import org.eclipse.leshan.server.security.EditableSecurityStore; |
@@ -40,6 +41,7 @@ import java.util.concurrent.ConcurrentHashMap; | @@ -40,6 +41,7 @@ import java.util.concurrent.ConcurrentHashMap; | ||
40 | import static org.eclipse.leshan.core.SecurityMode.NO_SEC; | 41 | import static org.eclipse.leshan.core.SecurityMode.NO_SEC; |
41 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; | 42 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; |
42 | 43 | ||
44 | +@Slf4j | ||
43 | @Service | 45 | @Service |
44 | @TbLwM2mTransportComponent | 46 | @TbLwM2mTransportComponent |
45 | @RequiredArgsConstructor | 47 | @RequiredArgsConstructor |
@@ -112,8 +114,12 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { | @@ -112,8 +114,12 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { | ||
112 | EndpointSecurityInfo securityInfo = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(endpoint, LwM2mTransportUtil.LwM2mTypeServer.CLIENT); | 114 | EndpointSecurityInfo securityInfo = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(endpoint, LwM2mTransportUtil.LwM2mTypeServer.CLIENT); |
113 | if (securityInfo.getSecurityMode() != null) { | 115 | if (securityInfo.getSecurityMode() != null) { |
114 | if (securityInfo.getDeviceProfile() != null) { | 116 | if (securityInfo.getDeviceProfile() != null) { |
115 | - toClientProfile(securityInfo.getDeviceProfile()); | ||
116 | - UUID profileUuid = securityInfo.getDeviceProfile().getUuidId(); | 117 | + UUID profileUuid = profileUpdate(securityInfo.getDeviceProfile())!= null ? |
118 | + securityInfo.getDeviceProfile().getUuidId() : null; | ||
119 | + // TODO: for tests bug. | ||
120 | + if (profileUuid== null) { | ||
121 | + log.warn("input parameters toClientProfile if the result is null: [{}]", securityInfo.getDeviceProfile()); | ||
122 | + } | ||
117 | LwM2mClient client; | 123 | LwM2mClient client; |
118 | if (securityInfo.getSecurityInfo() != null) { | 124 | if (securityInfo.getSecurityInfo() != null) { |
119 | client = new LwM2mClient(context.getNodeId(), securityInfo.getSecurityInfo().getEndpoint(), | 125 | client = new LwM2mClient(context.getNodeId(), securityInfo.getSecurityInfo().getEndpoint(), |
@@ -141,7 +147,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { | @@ -141,7 +147,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { | ||
141 | LwM2mClient client = new LwM2mClient(context.getNodeId(), registration.getEndpoint(), null, null, credentials, credentials.getDeviceProfile().getUuidId(), UUID.randomUUID()); | 147 | LwM2mClient client = new LwM2mClient(context.getNodeId(), registration.getEndpoint(), null, null, credentials, credentials.getDeviceProfile().getUuidId(), UUID.randomUUID()); |
142 | lwM2mClientsByEndpoint.put(registration.getEndpoint(), client); | 148 | lwM2mClientsByEndpoint.put(registration.getEndpoint(), client); |
143 | lwM2mClientsByRegistrationId.put(registration.getId(), client); | 149 | lwM2mClientsByRegistrationId.put(registration.getId(), client); |
144 | - toClientProfile(credentials.getDeviceProfile()); | 150 | + profileUpdate(credentials.getDeviceProfile()); |
145 | } | 151 | } |
146 | 152 | ||
147 | @Override | 153 | @Override |
@@ -170,13 +176,16 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { | @@ -170,13 +176,16 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { | ||
170 | } | 176 | } |
171 | 177 | ||
172 | @Override | 178 | @Override |
173 | - public LwM2mClientProfile toClientProfile(DeviceProfile deviceProfile) { | ||
174 | - LwM2mClientProfile lwM2MClientProfile = profiles.get(deviceProfile.getUuidId()); | ||
175 | - if (lwM2MClientProfile == null) { | ||
176 | - lwM2MClientProfile = LwM2mTransportUtil.toLwM2MClientProfile(deviceProfile); | 179 | + public LwM2mClientProfile profileUpdate(DeviceProfile deviceProfile) { |
180 | + LwM2mClientProfile lwM2MClientProfile = deviceProfile != null ? | ||
181 | + LwM2mTransportUtil.toLwM2MClientProfile(deviceProfile) : null; | ||
182 | + if (lwM2MClientProfile != null) { | ||
177 | profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile); | 183 | profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile); |
184 | + return lwM2MClientProfile; | ||
185 | + } | ||
186 | + else { | ||
187 | + return null; | ||
178 | } | 188 | } |
179 | - return lwM2MClientProfile; | ||
180 | } | 189 | } |
181 | 190 | ||
182 | /** | 191 | /** |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFirmwareUpdate.java
deleted
100644 → 0
1 | -/** | ||
2 | - * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.thingsboard.server.transport.lwm2m.server.client; | ||
17 | - | ||
18 | -import lombok.Data; | ||
19 | - | ||
20 | -import java.util.UUID; | ||
21 | - | ||
22 | -@Data | ||
23 | -public class LwM2mFirmwareUpdate { | ||
24 | - private volatile String clientFwVersion; | ||
25 | - private volatile String currentFwVersion; | ||
26 | - private volatile UUID currentFwId; | ||
27 | -} |
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.transport.lwm2m.server.client; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | +import lombok.Setter; | ||
20 | +import lombok.extern.slf4j.Slf4j; | ||
21 | +import org.apache.commons.lang3.StringUtils; | ||
22 | +import org.eclipse.leshan.core.request.ContentFormat; | ||
23 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
24 | +import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus; | ||
25 | +import org.thingsboard.server.gen.transport.TransportProtos; | ||
26 | +import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2MTransportMsgHandler; | ||
27 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportRequest; | ||
28 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; | ||
29 | + | ||
30 | +import java.util.ArrayList; | ||
31 | +import java.util.List; | ||
32 | +import java.util.UUID; | ||
33 | +import java.util.concurrent.CopyOnWriteArrayList; | ||
34 | + | ||
35 | +import static org.thingsboard.server.common.data.firmware.FirmwareKey.STATE; | ||
36 | +import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE; | ||
37 | +import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE; | ||
38 | +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.UPDATING; | ||
39 | +import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getAttributeKey; | ||
40 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_NAME_ID; | ||
41 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID; | ||
42 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID; | ||
43 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_STATE_ID; | ||
44 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE; | ||
45 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_ID; | ||
46 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_VER_ID; | ||
47 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR; | ||
48 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; | ||
49 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE; | ||
50 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE; | ||
51 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE; | ||
52 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_INSTALL_ID; | ||
53 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_NAME_ID; | ||
54 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_PACKAGE_ID; | ||
55 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_RESULT_ID; | ||
56 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_UN_INSTALL_ID; | ||
57 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_UPDATE; | ||
58 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_UPDATE_STATE_ID; | ||
59 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_VER_ID; | ||
60 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; | ||
61 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.splitCamelCaseString; | ||
62 | + | ||
63 | +@Slf4j | ||
64 | +public class LwM2mFwSwUpdate { | ||
65 | + // 5/0/6 PkgName | ||
66 | + // 9/0/0 PkgName | ||
67 | + @Getter | ||
68 | + @Setter | ||
69 | + private volatile String currentTitle; | ||
70 | + // 5/0/7 PkgVersion | ||
71 | + // 9/0/1 PkgVersion | ||
72 | + @Getter | ||
73 | + @Setter | ||
74 | + private volatile String currentVersion; | ||
75 | + @Getter | ||
76 | + @Setter | ||
77 | + private volatile UUID currentId; | ||
78 | + @Getter | ||
79 | + @Setter | ||
80 | + private volatile String stateUpdate; | ||
81 | + @Getter | ||
82 | + private String pathPackageId; | ||
83 | + @Getter | ||
84 | + private String pathStateId; | ||
85 | + @Getter | ||
86 | + private String pathResultId; | ||
87 | + @Getter | ||
88 | + private String pathNameId; | ||
89 | + @Getter | ||
90 | + private String pathVerId; | ||
91 | + @Getter | ||
92 | + private String pathInstallId; | ||
93 | + @Getter | ||
94 | + private String pathUnInstallId; | ||
95 | + @Getter | ||
96 | + private String wUpdate; | ||
97 | + @Getter | ||
98 | + @Setter | ||
99 | + private volatile boolean infoFwSwUpdate = false; | ||
100 | + private final FirmwareType type; | ||
101 | + @Getter | ||
102 | + LwM2mClient lwM2MClient; | ||
103 | + @Getter | ||
104 | + @Setter | ||
105 | + private final List<String> pendingInfoRequestsStart; | ||
106 | + | ||
107 | + public LwM2mFwSwUpdate(LwM2mClient lwM2MClient, FirmwareType type) { | ||
108 | + this.lwM2MClient = lwM2MClient; | ||
109 | + this.pendingInfoRequestsStart = new CopyOnWriteArrayList<>(); | ||
110 | + this.type = type; | ||
111 | + this.stateUpdate = null; | ||
112 | + this.initPathId(); | ||
113 | + } | ||
114 | + | ||
115 | + private void initPathId() { | ||
116 | + if (FIRMWARE.equals(this.type)) { | ||
117 | + this.pathPackageId = FW_PACKAGE_ID; | ||
118 | + this.pathStateId = FW_STATE_ID; | ||
119 | + this.pathResultId = FW_RESULT_ID; | ||
120 | + this.pathNameId = FW_NAME_ID; | ||
121 | + this.pathVerId = FW_VER_ID; | ||
122 | + this.pathInstallId = FW_UPDATE_ID; | ||
123 | + this.wUpdate = FW_UPDATE; | ||
124 | + } else if (SOFTWARE.equals(this.type)) { | ||
125 | + this.pathPackageId = SW_PACKAGE_ID; | ||
126 | + this.pathStateId = SW_UPDATE_STATE_ID; | ||
127 | + this.pathResultId = SW_RESULT_ID; | ||
128 | + this.pathNameId = SW_NAME_ID; | ||
129 | + this.pathVerId = SW_VER_ID; | ||
130 | + this.pathInstallId = SW_INSTALL_ID; | ||
131 | + this.pathUnInstallId = SW_UN_INSTALL_ID; | ||
132 | + this.wUpdate = SW_UPDATE; | ||
133 | + } | ||
134 | + } | ||
135 | + | ||
136 | + public void initReadValue(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request, String pathIdVer) { | ||
137 | + if (pathIdVer != null) { | ||
138 | + this.pendingInfoRequestsStart.remove(pathIdVer); | ||
139 | + } | ||
140 | + if (this.pendingInfoRequestsStart.size() == 0) { | ||
141 | + this.infoFwSwUpdate = false; | ||
142 | + if (!FirmwareUpdateStatus.DOWNLOADING.name().equals(this.stateUpdate)) { | ||
143 | + boolean conditionalStart = this.type.equals(FIRMWARE) ? this.conditionalFwUpdateStart() : | ||
144 | + this.conditionalSwUpdateStart(); | ||
145 | + if (conditionalStart) { | ||
146 | + this.writeFwSwWare(handler, request); | ||
147 | + } | ||
148 | + } | ||
149 | + } | ||
150 | + } | ||
151 | + | ||
152 | + /** | ||
153 | + * Send FsSw to Lwm2mClient: | ||
154 | + * before operation Write: fw_state = DOWNLOADING | ||
155 | + */ | ||
156 | + private void writeFwSwWare(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) { | ||
157 | + this.stateUpdate = FirmwareUpdateStatus.DOWNLOADING.name(); | ||
158 | +// this.observeStateUpdate(); | ||
159 | + this.sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null); | ||
160 | + int chunkSize = 0; | ||
161 | + int chunk = 0; | ||
162 | + byte[] firmwareChunk = handler.firmwareDataCache.get(this.currentId.toString(), chunkSize, chunk); | ||
163 | + String targetIdVer = convertPathFromObjectIdToIdVer(this.pathPackageId, this.lwM2MClient.getRegistration()); | ||
164 | + request.sendAllRequest(lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE.getName(), | ||
165 | + firmwareChunk, handler.config.getTimeout(), null); | ||
166 | + } | ||
167 | + | ||
168 | + public void sendLogs(DefaultLwM2MTransportMsgHandler handler, String typeOper, String typeInfo, String msgError) { | ||
169 | + this.sendSateOnThingsBoard(handler); | ||
170 | + String msg = String.format("%s: %s, %s, pkgVer: %s: pkgName - %s state - %s.", | ||
171 | + typeInfo, this.wUpdate, typeOper, this.currentVersion, this.currentTitle, this.stateUpdate); | ||
172 | + if (LOG_LW2M_ERROR.equals(typeInfo)) { | ||
173 | + msg = String.format("%s Error: %s", msg, msgError); | ||
174 | + } | ||
175 | + handler.sendLogsToThingsboard(msg, lwM2MClient.getRegistration().getId()); | ||
176 | + } | ||
177 | + | ||
178 | + | ||
179 | + /** | ||
180 | + * After inspection Update Result | ||
181 | + * fw_state/sw_state = UPDATING | ||
182 | + * send execute | ||
183 | + */ | ||
184 | + public void executeFwSwWare(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) { | ||
185 | + this.setStateUpdate(UPDATING.name()); | ||
186 | + this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_INFO, null); | ||
187 | + request.sendAllRequest(this.lwM2MClient.getRegistration(), this.pathInstallId, EXECUTE, ContentFormat.TLV.getName(), | ||
188 | + null, 0, null); | ||
189 | + } | ||
190 | + | ||
191 | + | ||
192 | + /** | ||
193 | + * Firmware start: | ||
194 | + * -- Если Update Result -errors (более 1) - Это означает что пред. апдейт не прошел. | ||
195 | + * - Запускаем апдейт в независимости от состяния прошивки и ее версии. | ||
196 | + * -- Если Update Result - не errors (менее или равно 1) и ver не пустой - Это означает что пред. апдейт прошел. | ||
197 | + * -- Если Update Result - не errors и ver пустой - Это означает что апдейта еще не было. | ||
198 | + * - Проверяем поменялась ли версия и запускаем новый апдейт. | ||
199 | + */ | ||
200 | + private boolean conditionalFwUpdateStart() { | ||
201 | + Long updateResultFw = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); | ||
202 | + // #1/#2 | ||
203 | + return updateResultFw > LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code || | ||
204 | + ( | ||
205 | + (updateResultFw <= LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code | ||
206 | + ) && | ||
207 | + ( | ||
208 | + (this.currentVersion != null && !this.currentVersion.equals(this.lwM2MClient.getResourceValue(null, this.pathVerId))) || | ||
209 | + (this.currentTitle != null && !this.currentTitle.equals(this.lwM2MClient.getResourceValue(null, this.pathNameId))) | ||
210 | + ) | ||
211 | + ); | ||
212 | + } | ||
213 | + | ||
214 | + | ||
215 | + /** | ||
216 | + * Before operation Execute inspection Update Result : | ||
217 | + * 0 - Initial value | ||
218 | + */ | ||
219 | + public boolean conditionalFwExecuteStart() { | ||
220 | + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); | ||
221 | + return LwM2mTransportUtil.UpdateResultFw.INITIAL.code == updateResult; | ||
222 | + } | ||
223 | + | ||
224 | + /** | ||
225 | + * After operation Execute success inspection Update Result : | ||
226 | + * 1 - "Firmware updated successfully" | ||
227 | + */ | ||
228 | + public boolean conditionalFwExecuteAfterSuccess() { | ||
229 | + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); | ||
230 | + return LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code == updateResult; | ||
231 | + } | ||
232 | + | ||
233 | + /** | ||
234 | + * After operation Execute success inspection Update Result : | ||
235 | + * > 1 error: "Firmware updated successfully" | ||
236 | + */ | ||
237 | + public boolean conditionalFwExecuteAfterError() { | ||
238 | + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); | ||
239 | + return LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code < updateResult; | ||
240 | + } | ||
241 | + | ||
242 | + /** | ||
243 | + * Software start | ||
244 | + * -- Если Update Result -errors (равно и более 50) - Это означает что пред. апдейт не прошел. | ||
245 | + * * - Запускаем апдейт в независимости от состяния прошивки и ее версии. | ||
246 | + * -- Если Update Result - не errors (менее 50) и ver не пустой - Это означает что пред. апдейт прошел. | ||
247 | + * -- Если Update Result - не errors и ver пустой - Это означает что апдейта еще не было или пред. апдейт UnInstall | ||
248 | + * -- Если Update Result - не errors и ver не пустой - Это означает что пред. апдейт UnInstall | ||
249 | + * - Проверяем поменялась ли версия и запускаем новый апдейт. | ||
250 | + */ | ||
251 | + private boolean conditionalSwUpdateStart() { | ||
252 | + Long updateResultSw = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); | ||
253 | + // #1/#2 | ||
254 | + return updateResultSw >= LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.code || | ||
255 | + ( | ||
256 | + (updateResultSw <= LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.code | ||
257 | + ) && | ||
258 | + ( | ||
259 | + (this.currentVersion != null && !this.currentVersion.equals(this.lwM2MClient.getResourceValue(null, this.pathVerId))) || | ||
260 | + (this.currentTitle != null && !this.currentTitle.equals(this.lwM2MClient.getResourceValue(null, this.pathNameId))) | ||
261 | + ) | ||
262 | + ); | ||
263 | + } | ||
264 | + | ||
265 | + /** | ||
266 | + * Before operation Execute inspection Update Result : | ||
267 | + * 3 - Successfully Downloaded and package integrity verified | ||
268 | + */ | ||
269 | + public boolean conditionalSwUpdateExecute() { | ||
270 | + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); | ||
271 | + return LwM2mTransportUtil.UpdateResultSw.SUCCESSFULLY_DOWNLOADED_VERIFIED.code == updateResult; | ||
272 | + } | ||
273 | + | ||
274 | + /** | ||
275 | + * After finish operation Execute (success): | ||
276 | + * -- inspection Update Result: | ||
277 | + * ---- FW если Update Result == 1 ("Firmware updated successfully") или SW если Update Result == 2 ("Software successfully installed.") | ||
278 | + * -- fw_state/sw_state = UPDATED | ||
279 | + * | ||
280 | + * After finish operation Execute (error): | ||
281 | + * -- inspection updateResult and send to thingsboard info about error | ||
282 | + * --- send to telemetry ( key - this is name Update Result in model) ( | ||
283 | + * -- fw_state/sw_state = FAILED | ||
284 | + */ | ||
285 | + public void finishFwSwUpdate(DefaultLwM2MTransportMsgHandler handler, boolean success) { | ||
286 | + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); | ||
287 | + String value = FIRMWARE.equals(this.type) ? LwM2mTransportUtil.UpdateResultFw.fromUpdateResultFwByCode(updateResult.intValue()).type : | ||
288 | + LwM2mTransportUtil.UpdateResultSw.fromUpdateResultSwByCode(updateResult.intValue()).type; | ||
289 | + String key = splitCamelCaseString((String) this.lwM2MClient.getResourceName(null, this.pathResultId)); | ||
290 | + if (success) { | ||
291 | + this.stateUpdate = FirmwareUpdateStatus.UPDATED.name(); | ||
292 | + this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_INFO, null); | ||
293 | + } else { | ||
294 | + this.stateUpdate = FirmwareUpdateStatus.FAILED.name(); | ||
295 | + this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_ERROR, value); | ||
296 | + } | ||
297 | + handler.helper.sendParametersOnThingsboardTelemetry( | ||
298 | + handler.helper.getKvStringtoThingsboard(key, value), this.lwM2MClient.getSession()); | ||
299 | + } | ||
300 | + | ||
301 | + /** | ||
302 | + * After operation Execute success inspection Update Result : | ||
303 | + * 2 - "Software successfully installed." | ||
304 | + */ | ||
305 | + public boolean conditionalSwExecuteAfterSuccess() { | ||
306 | + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); | ||
307 | + return LwM2mTransportUtil.UpdateResultSw.SUCCESSFULLY_INSTALLED.code == updateResult; | ||
308 | + } | ||
309 | + | ||
310 | + /** | ||
311 | + * After operation Execute success inspection Update Result : | ||
312 | + * >= 50 - error "NOT_ENOUGH_STORAGE" | ||
313 | + */ | ||
314 | + public boolean conditionalSwExecuteAfterError() { | ||
315 | + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); | ||
316 | + return LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.code <= updateResult; | ||
317 | + } | ||
318 | + | ||
319 | + private void observeStateUpdate(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) { | ||
320 | + request.sendAllRequest(lwM2MClient.getRegistration(), | ||
321 | + convertPathFromObjectIdToIdVer(this.pathStateId, this.lwM2MClient.getRegistration()), OBSERVE, | ||
322 | + null, null, 0, null); | ||
323 | + request.sendAllRequest(lwM2MClient.getRegistration(), | ||
324 | + convertPathFromObjectIdToIdVer(this.pathResultId, this.lwM2MClient.getRegistration()), OBSERVE, | ||
325 | + null, null, 0, null); | ||
326 | + } | ||
327 | + | ||
328 | + public void sendSateOnThingsBoard(DefaultLwM2MTransportMsgHandler handler) { | ||
329 | + if (StringUtils.trimToNull(this.stateUpdate) != null) { | ||
330 | + List<TransportProtos.KeyValueProto> result = new ArrayList<>(); | ||
331 | + TransportProtos.KeyValueProto.Builder kvProto = TransportProtos.KeyValueProto.newBuilder().setKey(getAttributeKey(this.type, STATE)); | ||
332 | + kvProto.setType(TransportProtos.KeyValueType.STRING_V).setStringV(stateUpdate); | ||
333 | + result.add(kvProto.build()); | ||
334 | + handler.helper.sendParametersOnThingsboardTelemetry(result, | ||
335 | + handler.getSessionInfoOrCloseSession(this.lwM2MClient.getRegistration())); | ||
336 | + } | ||
337 | + } | ||
338 | + | ||
339 | + public void sendReadObserveInfo(LwM2mTransportRequest request) { | ||
340 | + this.infoFwSwUpdate = true; | ||
341 | + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( | ||
342 | + this.pathVerId, this.lwM2MClient.getRegistration())); | ||
343 | + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( | ||
344 | + this.pathNameId, this.lwM2MClient.getRegistration())); | ||
345 | + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( | ||
346 | + this.pathStateId, this.lwM2MClient.getRegistration())); | ||
347 | + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( | ||
348 | + this.pathResultId, this.lwM2MClient.getRegistration())); | ||
349 | + this.pendingInfoRequestsStart.forEach(pathIdVer -> { | ||
350 | + request.sendAllRequest(this.lwM2MClient.getRegistration(), pathIdVer, OBSERVE, ContentFormat.TLV.getName(), | ||
351 | + null, 0, null); | ||
352 | + }); | ||
353 | + | ||
354 | + } | ||
355 | +} |
@@ -17,6 +17,7 @@ package org.thingsboard.server.transport.lwm2m.server.client; | @@ -17,6 +17,7 @@ package org.thingsboard.server.transport.lwm2m.server.client; | ||
17 | 17 | ||
18 | import com.google.gson.JsonObject; | 18 | import com.google.gson.JsonObject; |
19 | import lombok.Data; | 19 | import lombok.Data; |
20 | +import lombok.extern.slf4j.Slf4j; | ||
20 | import org.eclipse.leshan.core.request.ContentFormat; | 21 | import org.eclipse.leshan.core.request.ContentFormat; |
21 | import org.eclipse.leshan.server.registration.Registration; | 22 | import org.eclipse.leshan.server.registration.Registration; |
22 | import org.thingsboard.server.gen.transport.TransportProtos; | 23 | import org.thingsboard.server.gen.transport.TransportProtos; |
@@ -27,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap; | @@ -27,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap; | ||
27 | 28 | ||
28 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.validPathIdVer; | 29 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.validPathIdVer; |
29 | 30 | ||
31 | +@Slf4j | ||
30 | @Data | 32 | @Data |
31 | public class Lwm2mClientRpcRequest { | 33 | public class Lwm2mClientRpcRequest { |
32 | public final String targetIdVerKey = "targetIdVer"; | 34 | public final String targetIdVerKey = "targetIdVer"; |
@@ -107,4 +109,14 @@ public class Lwm2mClientRpcRequest { | @@ -107,4 +109,14 @@ public class Lwm2mClientRpcRequest { | ||
107 | .setRequestId(this.requestId) | 109 | .setRequestId(this.requestId) |
108 | .build(); | 110 | .build(); |
109 | } | 111 | } |
112 | + | ||
113 | + @Override | ||
114 | + public Object clone() { | ||
115 | + try { | ||
116 | + return super.clone(); | ||
117 | + } catch (CloneNotSupportedException e) { | ||
118 | + log.error("", e); | ||
119 | + } | ||
120 | + return null; | ||
121 | + } | ||
110 | } | 122 | } |
@@ -26,9 +26,7 @@ import org.eclipse.leshan.core.util.NamedThreadFactory; | @@ -26,9 +26,7 @@ import org.eclipse.leshan.core.util.NamedThreadFactory; | ||
26 | import org.eclipse.leshan.core.util.Validate; | 26 | import org.eclipse.leshan.core.util.Validate; |
27 | import org.eclipse.leshan.server.californium.observation.ObserveUtil; | 27 | import org.eclipse.leshan.server.californium.observation.ObserveUtil; |
28 | import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; | 28 | import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; |
29 | -import org.eclipse.leshan.server.redis.JedisLock; | ||
30 | import org.eclipse.leshan.server.redis.RedisRegistrationStore; | 29 | import org.eclipse.leshan.server.redis.RedisRegistrationStore; |
31 | -import org.eclipse.leshan.server.redis.SingleInstanceJedisLock; | ||
32 | import org.eclipse.leshan.server.redis.serialization.ObservationSerDes; | 30 | import org.eclipse.leshan.server.redis.serialization.ObservationSerDes; |
33 | import org.eclipse.leshan.server.redis.serialization.RegistrationSerDes; | 31 | import org.eclipse.leshan.server.redis.serialization.RegistrationSerDes; |
34 | import org.eclipse.leshan.server.registration.Deregistration; | 32 | import org.eclipse.leshan.server.registration.Deregistration; |
@@ -38,11 +36,12 @@ import org.eclipse.leshan.server.registration.RegistrationUpdate; | @@ -38,11 +36,12 @@ import org.eclipse.leshan.server.registration.RegistrationUpdate; | ||
38 | import org.eclipse.leshan.server.registration.UpdatedRegistration; | 36 | import org.eclipse.leshan.server.registration.UpdatedRegistration; |
39 | import org.slf4j.Logger; | 37 | import org.slf4j.Logger; |
40 | import org.slf4j.LoggerFactory; | 38 | import org.slf4j.LoggerFactory; |
39 | +import org.springframework.data.redis.connection.RedisClusterConnection; | ||
40 | +import org.springframework.data.redis.connection.RedisConnection; | ||
41 | import org.springframework.data.redis.connection.RedisConnectionFactory; | 41 | import org.springframework.data.redis.connection.RedisConnectionFactory; |
42 | -import redis.clients.jedis.Jedis; | ||
43 | -import redis.clients.jedis.ScanParams; | ||
44 | -import redis.clients.jedis.ScanResult; | ||
45 | -import redis.clients.jedis.Transaction; | 42 | +import org.springframework.data.redis.core.Cursor; |
43 | +import org.springframework.data.redis.core.ScanOptions; | ||
44 | +import org.springframework.integration.redis.util.RedisLockRegistry; | ||
46 | 45 | ||
47 | import java.net.InetSocketAddress; | 46 | import java.net.InetSocketAddress; |
48 | import java.util.ArrayList; | 47 | import java.util.ArrayList; |
@@ -50,13 +49,14 @@ import java.util.Arrays; | @@ -50,13 +49,14 @@ import java.util.Arrays; | ||
50 | import java.util.Collection; | 49 | import java.util.Collection; |
51 | import java.util.Collections; | 50 | import java.util.Collections; |
52 | import java.util.Iterator; | 51 | import java.util.Iterator; |
52 | +import java.util.LinkedList; | ||
53 | import java.util.List; | 53 | import java.util.List; |
54 | -import java.util.NoSuchElementException; | ||
55 | import java.util.Set; | 54 | import java.util.Set; |
56 | import java.util.concurrent.Executors; | 55 | import java.util.concurrent.Executors; |
57 | import java.util.concurrent.ScheduledExecutorService; | 56 | import java.util.concurrent.ScheduledExecutorService; |
58 | import java.util.concurrent.ScheduledFuture; | 57 | import java.util.concurrent.ScheduledFuture; |
59 | import java.util.concurrent.TimeUnit; | 58 | import java.util.concurrent.TimeUnit; |
59 | +import java.util.concurrent.locks.Lock; | ||
60 | 60 | ||
61 | import static java.nio.charset.StandardCharsets.UTF_8; | 61 | import static java.nio.charset.StandardCharsets.UTF_8; |
62 | 62 | ||
@@ -92,7 +92,7 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -92,7 +92,7 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
92 | private final int cleanLimit; // maximum number to clean in a clean period | 92 | private final int cleanLimit; // maximum number to clean in a clean period |
93 | private final long gracePeriod; // in seconds | 93 | private final long gracePeriod; // in seconds |
94 | 94 | ||
95 | - private final JedisLock lock; | 95 | + private final RedisLockRegistry redisLock; |
96 | 96 | ||
97 | public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory) { | 97 | public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory) { |
98 | this(connectionFactory, DEFAULT_CLEAN_PERIOD, DEFAULT_GRACE_PERIOD, DEFAULT_CLEAN_LIMIT); // default clean period 60s | 98 | this(connectionFactory, DEFAULT_CLEAN_PERIOD, DEFAULT_GRACE_PERIOD, DEFAULT_CLEAN_LIMIT); // default clean period 60s |
@@ -106,20 +106,12 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -106,20 +106,12 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
106 | 106 | ||
107 | public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory, ScheduledExecutorService schedExecutor, long cleanPeriodInSec, | 107 | public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory, ScheduledExecutorService schedExecutor, long cleanPeriodInSec, |
108 | long lifetimeGracePeriodInSec, int cleanLimit) { | 108 | long lifetimeGracePeriodInSec, int cleanLimit) { |
109 | - this(connectionFactory, schedExecutor, cleanPeriodInSec, lifetimeGracePeriodInSec, cleanLimit, new SingleInstanceJedisLock()); | ||
110 | - } | ||
111 | - | ||
112 | - /** | ||
113 | - * @since 1.1 | ||
114 | - */ | ||
115 | - public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory, ScheduledExecutorService schedExecutor, long cleanPeriodInSec, | ||
116 | - long lifetimeGracePeriodInSec, int cleanLimit, JedisLock redisLock) { | ||
117 | this.connectionFactory = connectionFactory; | 109 | this.connectionFactory = connectionFactory; |
118 | this.schedExecutor = schedExecutor; | 110 | this.schedExecutor = schedExecutor; |
119 | this.cleanPeriod = cleanPeriodInSec; | 111 | this.cleanPeriod = cleanPeriodInSec; |
120 | this.cleanLimit = cleanLimit; | 112 | this.cleanLimit = cleanLimit; |
121 | this.gracePeriod = lifetimeGracePeriodInSec; | 113 | this.gracePeriod = lifetimeGracePeriodInSec; |
122 | - this.lock = redisLock; | 114 | + this.redisLock = new RedisLockRegistry(connectionFactory, "Registration"); |
123 | } | 115 | } |
124 | 116 | ||
125 | /* *************** Redis Key utility function **************** */ | 117 | /* *************** Redis Key utility function **************** */ |
@@ -135,76 +127,79 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -135,76 +127,79 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
135 | return (prefix + registrationID).getBytes(); | 127 | return (prefix + registrationID).getBytes(); |
136 | } | 128 | } |
137 | 129 | ||
138 | - private byte[] toLockKey(String endpoint) { | ||
139 | - return toKey(LOCK_EP, endpoint); | 130 | + private String toLockKey(String endpoint) { |
131 | + return new String(toKey(LOCK_EP, endpoint)); | ||
140 | } | 132 | } |
141 | 133 | ||
142 | - private byte[] toLockKey(byte[] endpoint) { | ||
143 | - return toKey(LOCK_EP.getBytes(UTF_8), endpoint); | 134 | + private String toLockKey(byte[] endpoint) { |
135 | + return new String(toKey(LOCK_EP.getBytes(UTF_8), endpoint)); | ||
144 | } | 136 | } |
145 | 137 | ||
146 | /* *************** Leshan Registration API **************** */ | 138 | /* *************** Leshan Registration API **************** */ |
147 | 139 | ||
148 | @Override | 140 | @Override |
149 | public Deregistration addRegistration(Registration registration) { | 141 | public Deregistration addRegistration(Registration registration) { |
150 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
151 | - byte[] lockValue = null; | ||
152 | - byte[] lockKey = toLockKey(registration.getEndpoint()); | 142 | + Lock lock = null; |
143 | + try (var connection = connectionFactory.getConnection()) { | ||
144 | + String lockKey = toLockKey(registration.getEndpoint()); | ||
153 | 145 | ||
154 | try { | 146 | try { |
155 | - lockValue = lock.acquire(j, lockKey); | ||
156 | - | 147 | + lock = redisLock.obtain(lockKey); |
148 | + lock.lock(); | ||
157 | // add registration | 149 | // add registration |
158 | byte[] k = toEndpointKey(registration.getEndpoint()); | 150 | byte[] k = toEndpointKey(registration.getEndpoint()); |
159 | - byte[] old = j.getSet(k, serializeReg(registration)); | 151 | + byte[] old = connection.getSet(k, serializeReg(registration)); |
160 | 152 | ||
161 | // add registration: secondary indexes | 153 | // add registration: secondary indexes |
162 | byte[] regid_idx = toRegIdKey(registration.getId()); | 154 | byte[] regid_idx = toRegIdKey(registration.getId()); |
163 | - j.set(regid_idx, registration.getEndpoint().getBytes(UTF_8)); | 155 | + connection.set(regid_idx, registration.getEndpoint().getBytes(UTF_8)); |
164 | byte[] addr_idx = toRegAddrKey(registration.getSocketAddress()); | 156 | byte[] addr_idx = toRegAddrKey(registration.getSocketAddress()); |
165 | - j.set(addr_idx, registration.getEndpoint().getBytes(UTF_8)); | 157 | + connection.set(addr_idx, registration.getEndpoint().getBytes(UTF_8)); |
166 | 158 | ||
167 | // Add or update expiration | 159 | // Add or update expiration |
168 | - addOrUpdateExpiration(j, registration); | 160 | + addOrUpdateExpiration(connection, registration); |
169 | 161 | ||
170 | if (old != null) { | 162 | if (old != null) { |
171 | Registration oldRegistration = deserializeReg(old); | 163 | Registration oldRegistration = deserializeReg(old); |
172 | // remove old secondary index | 164 | // remove old secondary index |
173 | if (!registration.getId().equals(oldRegistration.getId())) | 165 | if (!registration.getId().equals(oldRegistration.getId())) |
174 | - j.del(toRegIdKey(oldRegistration.getId())); | 166 | + connection.del(toRegIdKey(oldRegistration.getId())); |
175 | if (!oldRegistration.getSocketAddress().equals(registration.getSocketAddress())) { | 167 | if (!oldRegistration.getSocketAddress().equals(registration.getSocketAddress())) { |
176 | - removeAddrIndex(j, oldRegistration); | 168 | + removeAddrIndex(connection, oldRegistration); |
177 | } | 169 | } |
178 | // remove old observation | 170 | // remove old observation |
179 | - Collection<Observation> obsRemoved = unsafeRemoveAllObservations(j, oldRegistration.getId()); | 171 | + Collection<Observation> obsRemoved = unsafeRemoveAllObservations(connection, oldRegistration.getId()); |
180 | 172 | ||
181 | return new Deregistration(oldRegistration, obsRemoved); | 173 | return new Deregistration(oldRegistration, obsRemoved); |
182 | } | 174 | } |
183 | 175 | ||
184 | return null; | 176 | return null; |
185 | } finally { | 177 | } finally { |
186 | - lock.release(j, lockKey, lockValue); | 178 | + if (lock != null) { |
179 | + lock.unlock(); | ||
180 | + } | ||
187 | } | 181 | } |
188 | } | 182 | } |
189 | } | 183 | } |
190 | 184 | ||
191 | @Override | 185 | @Override |
192 | public UpdatedRegistration updateRegistration(RegistrationUpdate update) { | 186 | public UpdatedRegistration updateRegistration(RegistrationUpdate update) { |
193 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | 187 | + Lock lock = null; |
188 | + try (var connection = connectionFactory.getConnection()) { | ||
194 | 189 | ||
195 | // Fetch the registration ep by registration ID index | 190 | // Fetch the registration ep by registration ID index |
196 | - byte[] ep = j.get(toRegIdKey(update.getRegistrationId())); | 191 | + byte[] ep = connection.get(toRegIdKey(update.getRegistrationId())); |
197 | if (ep == null) { | 192 | if (ep == null) { |
198 | return null; | 193 | return null; |
199 | } | 194 | } |
200 | 195 | ||
201 | - byte[] lockValue = null; | ||
202 | - byte[] lockKey = toLockKey(ep); | 196 | + String lockKey = toLockKey(ep); |
203 | try { | 197 | try { |
204 | - lockValue = lock.acquire(j, lockKey); | 198 | + lock = redisLock.obtain(lockKey); |
199 | + lock.lock(); | ||
205 | 200 | ||
206 | // Fetch the registration | 201 | // Fetch the registration |
207 | - byte[] data = j.get(toEndpointKey(ep)); | 202 | + byte[] data = connection.get(toEndpointKey(ep)); |
208 | if (data == null) { | 203 | if (data == null) { |
209 | return null; | 204 | return null; |
210 | } | 205 | } |
@@ -214,40 +209,42 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -214,40 +209,42 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
214 | Registration updatedRegistration = update.update(r); | 209 | Registration updatedRegistration = update.update(r); |
215 | 210 | ||
216 | // Store the new registration | 211 | // Store the new registration |
217 | - j.set(toEndpointKey(updatedRegistration.getEndpoint()), serializeReg(updatedRegistration)); | 212 | + connection.set(toEndpointKey(updatedRegistration.getEndpoint()), serializeReg(updatedRegistration)); |
218 | 213 | ||
219 | // Add or update expiration | 214 | // Add or update expiration |
220 | - addOrUpdateExpiration(j, updatedRegistration); | 215 | + addOrUpdateExpiration(connection, updatedRegistration); |
221 | 216 | ||
222 | // Update secondary index : | 217 | // Update secondary index : |
223 | // If registration is already associated to this address we don't care as we only want to keep the most | 218 | // If registration is already associated to this address we don't care as we only want to keep the most |
224 | // recent binding. | 219 | // recent binding. |
225 | byte[] addr_idx = toRegAddrKey(updatedRegistration.getSocketAddress()); | 220 | byte[] addr_idx = toRegAddrKey(updatedRegistration.getSocketAddress()); |
226 | - j.set(addr_idx, updatedRegistration.getEndpoint().getBytes(UTF_8)); | 221 | + connection.set(addr_idx, updatedRegistration.getEndpoint().getBytes(UTF_8)); |
227 | if (!r.getSocketAddress().equals(updatedRegistration.getSocketAddress())) { | 222 | if (!r.getSocketAddress().equals(updatedRegistration.getSocketAddress())) { |
228 | - removeAddrIndex(j, r); | 223 | + removeAddrIndex(connection, r); |
229 | } | 224 | } |
230 | 225 | ||
231 | return new UpdatedRegistration(r, updatedRegistration); | 226 | return new UpdatedRegistration(r, updatedRegistration); |
232 | 227 | ||
233 | } finally { | 228 | } finally { |
234 | - lock.release(j, lockKey, lockValue); | 229 | + if (lock != null) { |
230 | + lock.unlock(); | ||
231 | + } | ||
235 | } | 232 | } |
236 | } | 233 | } |
237 | } | 234 | } |
238 | 235 | ||
239 | @Override | 236 | @Override |
240 | public Registration getRegistration(String registrationId) { | 237 | public Registration getRegistration(String registrationId) { |
241 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
242 | - return getRegistration(j, registrationId); | 238 | + try (var connection = connectionFactory.getConnection()) { |
239 | + return getRegistration(connection, registrationId); | ||
243 | } | 240 | } |
244 | } | 241 | } |
245 | 242 | ||
246 | @Override | 243 | @Override |
247 | public Registration getRegistrationByEndpoint(String endpoint) { | 244 | public Registration getRegistrationByEndpoint(String endpoint) { |
248 | Validate.notNull(endpoint); | 245 | Validate.notNull(endpoint); |
249 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
250 | - byte[] data = j.get(toEndpointKey(endpoint)); | 246 | + try (var connection = connectionFactory.getConnection()) { |
247 | + byte[] data = connection.get(toEndpointKey(endpoint)); | ||
251 | if (data == null) { | 248 | if (data == null) { |
252 | return null; | 249 | return null; |
253 | } | 250 | } |
@@ -258,12 +255,12 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -258,12 +255,12 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
258 | @Override | 255 | @Override |
259 | public Registration getRegistrationByAdress(InetSocketAddress address) { | 256 | public Registration getRegistrationByAdress(InetSocketAddress address) { |
260 | Validate.notNull(address); | 257 | Validate.notNull(address); |
261 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
262 | - byte[] ep = j.get(toRegAddrKey(address)); | 258 | + try (var connection = connectionFactory.getConnection()) { |
259 | + byte[] ep = connection.get(toRegAddrKey(address)); | ||
263 | if (ep == null) { | 260 | if (ep == null) { |
264 | return null; | 261 | return null; |
265 | } | 262 | } |
266 | - byte[] data = j.get(toEndpointKey(ep)); | 263 | + byte[] data = connection.get(toEndpointKey(ep)); |
267 | if (data == null) { | 264 | if (data == null) { |
268 | return null; | 265 | return null; |
269 | } | 266 | } |
@@ -273,140 +270,99 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -273,140 +270,99 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
273 | 270 | ||
274 | @Override | 271 | @Override |
275 | public Iterator<Registration> getAllRegistrations() { | 272 | public Iterator<Registration> getAllRegistrations() { |
276 | - return new TbLwM2mRedisRegistrationStore.RedisIterator(connectionFactory, new ScanParams().match(REG_EP + "*").count(100)); | ||
277 | - } | ||
278 | - | ||
279 | - protected class RedisIterator implements Iterator<Registration> { | ||
280 | - | ||
281 | - private final RedisConnectionFactory connectionFactory; | ||
282 | - private final ScanParams scanParams; | ||
283 | - | ||
284 | - private String cursor; | ||
285 | - private List<Registration> scanResult; | ||
286 | - | ||
287 | - public RedisIterator(RedisConnectionFactory connectionFactory, ScanParams scanParams) { | ||
288 | - this.connectionFactory = connectionFactory; | ||
289 | - this.scanParams = scanParams; | ||
290 | - // init scan result | ||
291 | - scanNext("0"); | ||
292 | - } | ||
293 | - | ||
294 | - private void scanNext(String cursor) { | ||
295 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
296 | - do { | ||
297 | - ScanResult<byte[]> sr = j.scan(cursor.getBytes(), scanParams); | ||
298 | - | ||
299 | - this.scanResult = new ArrayList<>(); | ||
300 | - if (sr.getResult() != null && !sr.getResult().isEmpty()) { | ||
301 | - for (byte[] value : j.mget(sr.getResult().toArray(new byte[][]{}))) { | ||
302 | - this.scanResult.add(deserializeReg(value)); | ||
303 | - } | ||
304 | - } | ||
305 | - | ||
306 | - cursor = sr.getCursor(); | ||
307 | - } while (!"0".equals(cursor) && scanResult.isEmpty()); | ||
308 | - | ||
309 | - this.cursor = cursor; | ||
310 | - } | ||
311 | - } | ||
312 | - | ||
313 | - @Override | ||
314 | - public boolean hasNext() { | ||
315 | - if (!scanResult.isEmpty()) { | ||
316 | - return true; | ||
317 | - } | ||
318 | - if ("0".equals(cursor)) { | ||
319 | - // no more elements to scan | ||
320 | - return false; | ||
321 | - } | ||
322 | - | ||
323 | - // read more elements | ||
324 | - scanNext(cursor); | ||
325 | - return !scanResult.isEmpty(); | ||
326 | - } | ||
327 | - | ||
328 | - @Override | ||
329 | - public Registration next() { | ||
330 | - if (!hasNext()) { | ||
331 | - throw new NoSuchElementException(); | 273 | + try (var connection = connectionFactory.getConnection()) { |
274 | + Collection<Registration> list = new LinkedList<>(); | ||
275 | + ScanOptions scanOptions = ScanOptions.scanOptions().count(100).match(REG_EP + "*").build(); | ||
276 | + List<Cursor<byte[]>> scans = new ArrayList<>(); | ||
277 | + if (connection instanceof RedisClusterConnection) { | ||
278 | + ((RedisClusterConnection) connection).clusterGetNodes().forEach(node -> { | ||
279 | + scans.add(((RedisClusterConnection) connection).scan(node, scanOptions)); | ||
280 | + }); | ||
281 | + } else { | ||
282 | + scans.add(connection.scan(scanOptions)); | ||
332 | } | 283 | } |
333 | - return scanResult.remove(0); | ||
334 | - } | ||
335 | 284 | ||
336 | - @Override | ||
337 | - public void remove() { | ||
338 | - throw new UnsupportedOperationException(); | 285 | + scans.forEach(scan -> { |
286 | + scan.forEachRemaining(key -> { | ||
287 | + byte[] element = connection.get(key); | ||
288 | + list.add(deserializeReg(element)); | ||
289 | + }); | ||
290 | + }); | ||
291 | + return list.iterator(); | ||
339 | } | 292 | } |
340 | } | 293 | } |
341 | 294 | ||
342 | @Override | 295 | @Override |
343 | public Deregistration removeRegistration(String registrationId) { | 296 | public Deregistration removeRegistration(String registrationId) { |
344 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
345 | - return removeRegistration(j, registrationId, false); | 297 | + try (var connection = connectionFactory.getConnection()) { |
298 | + return removeRegistration(connection, registrationId, false); | ||
346 | } | 299 | } |
347 | } | 300 | } |
348 | 301 | ||
349 | - private Deregistration removeRegistration(Jedis j, String registrationId, boolean removeOnlyIfNotAlive) { | 302 | + private Deregistration removeRegistration(RedisConnection connection, String registrationId, boolean removeOnlyIfNotAlive) { |
350 | // fetch the client ep by registration ID index | 303 | // fetch the client ep by registration ID index |
351 | - byte[] ep = j.get(toRegIdKey(registrationId)); | 304 | + byte[] ep = connection.get(toRegIdKey(registrationId)); |
352 | if (ep == null) { | 305 | if (ep == null) { |
353 | return null; | 306 | return null; |
354 | } | 307 | } |
355 | 308 | ||
356 | - byte[] lockValue = null; | ||
357 | - byte[] lockKey = toLockKey(ep); | 309 | + Lock lock = null; |
310 | + String lockKey = toLockKey(ep); | ||
358 | try { | 311 | try { |
359 | - lockValue = lock.acquire(j, lockKey); | 312 | + lock = redisLock.obtain(lockKey); |
313 | + lock.lock(); | ||
360 | 314 | ||
361 | // fetch the client | 315 | // fetch the client |
362 | - byte[] data = j.get(toEndpointKey(ep)); | 316 | + byte[] data = connection.get(toEndpointKey(ep)); |
363 | if (data == null) { | 317 | if (data == null) { |
364 | return null; | 318 | return null; |
365 | } | 319 | } |
366 | Registration r = deserializeReg(data); | 320 | Registration r = deserializeReg(data); |
367 | 321 | ||
368 | if (!removeOnlyIfNotAlive || !r.isAlive(gracePeriod)) { | 322 | if (!removeOnlyIfNotAlive || !r.isAlive(gracePeriod)) { |
369 | - long nbRemoved = j.del(toRegIdKey(r.getId())); | 323 | + long nbRemoved = connection.del(toRegIdKey(r.getId())); |
370 | if (nbRemoved > 0) { | 324 | if (nbRemoved > 0) { |
371 | - j.del(toEndpointKey(r.getEndpoint())); | ||
372 | - Collection<Observation> obsRemoved = unsafeRemoveAllObservations(j, r.getId()); | ||
373 | - removeAddrIndex(j, r); | ||
374 | - removeExpiration(j, r); | 325 | + connection.del(toEndpointKey(r.getEndpoint())); |
326 | + Collection<Observation> obsRemoved = unsafeRemoveAllObservations(connection, r.getId()); | ||
327 | + removeAddrIndex(connection, r); | ||
328 | + removeExpiration(connection, r); | ||
375 | return new Deregistration(r, obsRemoved); | 329 | return new Deregistration(r, obsRemoved); |
376 | } | 330 | } |
377 | } | 331 | } |
378 | return null; | 332 | return null; |
379 | } finally { | 333 | } finally { |
380 | - lock.release(j, lockKey, lockValue); | 334 | + if (lock != null) { |
335 | + lock.unlock(); | ||
336 | + } | ||
381 | } | 337 | } |
382 | } | 338 | } |
383 | 339 | ||
384 | - private void removeAddrIndex(Jedis j, Registration registration) { | 340 | + private void removeAddrIndex(RedisConnection connection, Registration registration) { |
385 | // Watch the key to remove. | 341 | // Watch the key to remove. |
386 | byte[] regAddrKey = toRegAddrKey(registration.getSocketAddress()); | 342 | byte[] regAddrKey = toRegAddrKey(registration.getSocketAddress()); |
387 | - j.watch(regAddrKey); | 343 | + connection.watch(regAddrKey); |
388 | 344 | ||
389 | - byte[] epFromAddr = j.get(regAddrKey); | 345 | + byte[] epFromAddr = connection.get(regAddrKey); |
390 | // Delete the key if needed. | 346 | // Delete the key if needed. |
391 | if (Arrays.equals(epFromAddr, registration.getEndpoint().getBytes(UTF_8))) { | 347 | if (Arrays.equals(epFromAddr, registration.getEndpoint().getBytes(UTF_8))) { |
392 | // Try to delete the key | 348 | // Try to delete the key |
393 | - Transaction transaction = j.multi(); | ||
394 | - transaction.del(regAddrKey); | ||
395 | - transaction.exec(); | 349 | + connection.multi(); |
350 | + connection.del(regAddrKey); | ||
351 | + connection.exec(); | ||
396 | // if transaction failed this is not an issue as the socket address is probably reused and we don't neeed to | 352 | // if transaction failed this is not an issue as the socket address is probably reused and we don't neeed to |
397 | // delete it anymore. | 353 | // delete it anymore. |
398 | } else { | 354 | } else { |
399 | // the key must not be deleted. | 355 | // the key must not be deleted. |
400 | - j.unwatch(); | 356 | + connection.unwatch(); |
401 | } | 357 | } |
402 | } | 358 | } |
403 | 359 | ||
404 | - private void addOrUpdateExpiration(Jedis j, Registration registration) { | ||
405 | - j.zadd(EXP_EP, registration.getExpirationTimeStamp(gracePeriod), registration.getEndpoint().getBytes(UTF_8)); | 360 | + private void addOrUpdateExpiration(RedisConnection connection, Registration registration) { |
361 | + connection.zAdd(EXP_EP, registration.getExpirationTimeStamp(gracePeriod), registration.getEndpoint().getBytes(UTF_8)); | ||
406 | } | 362 | } |
407 | 363 | ||
408 | - private void removeExpiration(Jedis j, Registration registration) { | ||
409 | - j.zrem(EXP_EP, registration.getEndpoint().getBytes(UTF_8)); | 364 | + private void removeExpiration(RedisConnection connection, Registration registration) { |
365 | + connection.zRem(EXP_EP, registration.getEndpoint().getBytes(UTF_8)); | ||
410 | } | 366 | } |
411 | 367 | ||
412 | private byte[] toRegIdKey(String registrationId) { | 368 | private byte[] toRegIdKey(String registrationId) { |
@@ -441,33 +397,35 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -441,33 +397,35 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
441 | */ | 397 | */ |
442 | @Override | 398 | @Override |
443 | public Collection<Observation> addObservation(String registrationId, Observation observation) { | 399 | public Collection<Observation> addObservation(String registrationId, Observation observation) { |
444 | - | ||
445 | List<Observation> removed = new ArrayList<>(); | 400 | List<Observation> removed = new ArrayList<>(); |
446 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | 401 | + try (var connection = connectionFactory.getConnection()) { |
447 | 402 | ||
448 | // fetch the client ep by registration ID index | 403 | // fetch the client ep by registration ID index |
449 | - byte[] ep = j.get(toRegIdKey(registrationId)); | 404 | + byte[] ep = connection.get(toRegIdKey(registrationId)); |
450 | if (ep == null) { | 405 | if (ep == null) { |
451 | return null; | 406 | return null; |
452 | } | 407 | } |
453 | 408 | ||
454 | - byte[] lockValue = null; | ||
455 | - byte[] lockKey = toLockKey(ep); | 409 | + Lock lock = null; |
410 | + String lockKey = toLockKey(ep); | ||
456 | 411 | ||
457 | try { | 412 | try { |
458 | - lockValue = lock.acquire(j, lockKey); | 413 | + lock = redisLock.obtain(lockKey); |
414 | + lock.lock(); | ||
459 | 415 | ||
460 | // cancel existing observations for the same path and registration id. | 416 | // cancel existing observations for the same path and registration id. |
461 | - for (Observation obs : getObservations(j, registrationId)) { | 417 | + for (Observation obs : getObservations(connection, registrationId)) { |
462 | if (observation.getPath().equals(obs.getPath()) | 418 | if (observation.getPath().equals(obs.getPath()) |
463 | && !Arrays.equals(observation.getId(), obs.getId())) { | 419 | && !Arrays.equals(observation.getId(), obs.getId())) { |
464 | removed.add(obs); | 420 | removed.add(obs); |
465 | - unsafeRemoveObservation(j, registrationId, obs.getId()); | 421 | + unsafeRemoveObservation(connection, registrationId, obs.getId()); |
466 | } | 422 | } |
467 | } | 423 | } |
468 | 424 | ||
469 | } finally { | 425 | } finally { |
470 | - lock.release(j, lockKey, lockValue); | 426 | + if (lock != null) { |
427 | + lock.unlock(); | ||
428 | + } | ||
471 | } | 429 | } |
472 | } | 430 | } |
473 | return removed; | 431 | return removed; |
@@ -475,29 +433,32 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -475,29 +433,32 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
475 | 433 | ||
476 | @Override | 434 | @Override |
477 | public Observation removeObservation(String registrationId, byte[] observationId) { | 435 | public Observation removeObservation(String registrationId, byte[] observationId) { |
478 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | 436 | + try (var connection = connectionFactory.getConnection()) { |
479 | 437 | ||
480 | // fetch the client ep by registration ID index | 438 | // fetch the client ep by registration ID index |
481 | - byte[] ep = j.get(toRegIdKey(registrationId)); | 439 | + byte[] ep = connection.get(toRegIdKey(registrationId)); |
482 | if (ep == null) { | 440 | if (ep == null) { |
483 | return null; | 441 | return null; |
484 | } | 442 | } |
485 | 443 | ||
486 | // remove observation | 444 | // remove observation |
487 | - byte[] lockValue = null; | ||
488 | - byte[] lockKey = toLockKey(ep); | 445 | + Lock lock = null; |
446 | + String lockKey = toLockKey(ep); | ||
489 | try { | 447 | try { |
490 | - lockValue = lock.acquire(j, lockKey); | 448 | + lock = redisLock.obtain(lockKey); |
449 | + lock.lock(); | ||
491 | 450 | ||
492 | Observation observation = build(get(new Token(observationId))); | 451 | Observation observation = build(get(new Token(observationId))); |
493 | if (observation != null && registrationId.equals(observation.getRegistrationId())) { | 452 | if (observation != null && registrationId.equals(observation.getRegistrationId())) { |
494 | - unsafeRemoveObservation(j, registrationId, observationId); | 453 | + unsafeRemoveObservation(connection, registrationId, observationId); |
495 | return observation; | 454 | return observation; |
496 | } | 455 | } |
497 | return null; | 456 | return null; |
498 | 457 | ||
499 | } finally { | 458 | } finally { |
500 | - lock.release(j, lockKey, lockValue); | 459 | + if (lock != null) { |
460 | + lock.unlock(); | ||
461 | + } | ||
501 | } | 462 | } |
502 | } | 463 | } |
503 | } | 464 | } |
@@ -509,15 +470,15 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -509,15 +470,15 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
509 | 470 | ||
510 | @Override | 471 | @Override |
511 | public Collection<Observation> getObservations(String registrationId) { | 472 | public Collection<Observation> getObservations(String registrationId) { |
512 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
513 | - return getObservations(j, registrationId); | 473 | + try (var connection = connectionFactory.getConnection()) { |
474 | + return getObservations(connection, registrationId); | ||
514 | } | 475 | } |
515 | } | 476 | } |
516 | 477 | ||
517 | - private Collection<Observation> getObservations(Jedis j, String registrationId) { | 478 | + private Collection<Observation> getObservations(RedisConnection connection, String registrationId) { |
518 | Collection<Observation> result = new ArrayList<>(); | 479 | Collection<Observation> result = new ArrayList<>(); |
519 | - for (byte[] token : j.lrange(toKey(OBS_TKNS_REGID_IDX, registrationId), 0, -1)) { | ||
520 | - byte[] obs = j.get(toKey(OBS_TKN, token)); | 480 | + for (byte[] token : connection.lRange(toKey(OBS_TKNS_REGID_IDX, registrationId), 0, -1)) { |
481 | + byte[] obs = connection.get(toKey(OBS_TKN, token)); | ||
521 | if (obs != null) { | 482 | if (obs != null) { |
522 | result.add(build(deserializeObs(obs))); | 483 | result.add(build(deserializeObs(obs))); |
523 | } | 484 | } |
@@ -527,22 +488,24 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -527,22 +488,24 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
527 | 488 | ||
528 | @Override | 489 | @Override |
529 | public Collection<Observation> removeObservations(String registrationId) { | 490 | public Collection<Observation> removeObservations(String registrationId) { |
530 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | 491 | + try (var connection = connectionFactory.getConnection()) { |
531 | // check registration exists | 492 | // check registration exists |
532 | - Registration registration = getRegistration(j, registrationId); | 493 | + Registration registration = getRegistration(connection, registrationId); |
533 | if (registration == null) | 494 | if (registration == null) |
534 | return Collections.emptyList(); | 495 | return Collections.emptyList(); |
535 | 496 | ||
536 | // get endpoint and create lock | 497 | // get endpoint and create lock |
537 | String endpoint = registration.getEndpoint(); | 498 | String endpoint = registration.getEndpoint(); |
538 | - byte[] lockValue = null; | ||
539 | - byte[] lockKey = toKey(LOCK_EP, endpoint); | 499 | + Lock lock = null; |
500 | + String lockKey = toLockKey(endpoint); | ||
540 | try { | 501 | try { |
541 | - lockValue = lock.acquire(j, lockKey); | ||
542 | - | ||
543 | - return unsafeRemoveAllObservations(j, registrationId); | 502 | + lock = redisLock.obtain(lockKey); |
503 | + lock.lock(); | ||
504 | + return unsafeRemoveAllObservations(connection, registrationId); | ||
544 | } finally { | 505 | } finally { |
545 | - lock.release(j, lockKey, lockValue); | 506 | + if (lock != null) { |
507 | + lock.unlock(); | ||
508 | + } | ||
546 | } | 509 | } |
547 | } | 510 | } |
548 | } | 511 | } |
@@ -565,31 +528,32 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -565,31 +528,32 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
565 | String endpoint = ObserveUtil.validateCoapObservation(obs); | 528 | String endpoint = ObserveUtil.validateCoapObservation(obs); |
566 | org.eclipse.californium.core.observe.Observation previousObservation = null; | 529 | org.eclipse.californium.core.observe.Observation previousObservation = null; |
567 | 530 | ||
568 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
569 | - byte[] lockValue = null; | ||
570 | - byte[] lockKey = toKey(LOCK_EP, endpoint); | 531 | + try (var connection = connectionFactory.getConnection()) { |
532 | + Lock lock = null; | ||
533 | + String lockKey = toLockKey(endpoint); | ||
571 | try { | 534 | try { |
572 | - lockValue = lock.acquire(j, lockKey); | 535 | + lock = redisLock.obtain(lockKey); |
536 | + lock.lock(); | ||
573 | 537 | ||
574 | String registrationId = ObserveUtil.extractRegistrationId(obs); | 538 | String registrationId = ObserveUtil.extractRegistrationId(obs); |
575 | - if (!j.exists(toRegIdKey(registrationId))) | 539 | + if (!connection.exists(toRegIdKey(registrationId))) |
576 | throw new ObservationStoreException("no registration for this Id"); | 540 | throw new ObservationStoreException("no registration for this Id"); |
577 | byte[] key = toKey(OBS_TKN, obs.getRequest().getToken().getBytes()); | 541 | byte[] key = toKey(OBS_TKN, obs.getRequest().getToken().getBytes()); |
578 | byte[] serializeObs = serializeObs(obs); | 542 | byte[] serializeObs = serializeObs(obs); |
579 | byte[] previousValue; | 543 | byte[] previousValue; |
580 | if (ifAbsent) { | 544 | if (ifAbsent) { |
581 | - previousValue = j.get(key); | 545 | + previousValue = connection.get(key); |
582 | if (previousValue == null || previousValue.length == 0) { | 546 | if (previousValue == null || previousValue.length == 0) { |
583 | - j.set(key, serializeObs); | 547 | + connection.set(key, serializeObs); |
584 | } else { | 548 | } else { |
585 | return deserializeObs(previousValue); | 549 | return deserializeObs(previousValue); |
586 | } | 550 | } |
587 | } else { | 551 | } else { |
588 | - previousValue = j.getSet(key, serializeObs); | 552 | + previousValue = connection.getSet(key, serializeObs); |
589 | } | 553 | } |
590 | 554 | ||
591 | // secondary index to get the list by registrationId | 555 | // secondary index to get the list by registrationId |
592 | - j.lpush(toKey(OBS_TKNS_REGID_IDX, registrationId), obs.getRequest().getToken().getBytes()); | 556 | + connection.lPush(toKey(OBS_TKNS_REGID_IDX, registrationId), obs.getRequest().getToken().getBytes()); |
593 | 557 | ||
594 | // log any collisions | 558 | // log any collisions |
595 | if (previousValue != null && previousValue.length != 0) { | 559 | if (previousValue != null && previousValue.length != 0) { |
@@ -599,7 +563,9 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -599,7 +563,9 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
599 | previousObservation.getRequest(), obs.getRequest()); | 563 | previousObservation.getRequest(), obs.getRequest()); |
600 | } | 564 | } |
601 | } finally { | 565 | } finally { |
602 | - lock.release(j, lockKey, lockValue); | 566 | + if (lock != null) { |
567 | + lock.unlock(); | ||
568 | + } | ||
603 | } | 569 | } |
604 | } | 570 | } |
605 | return previousObservation; | 571 | return previousObservation; |
@@ -607,17 +573,17 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -607,17 +573,17 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
607 | 573 | ||
608 | @Override | 574 | @Override |
609 | public void remove(Token token) { | 575 | public void remove(Token token) { |
610 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | 576 | + try (var connection = connectionFactory.getConnection()) { |
611 | byte[] tokenKey = toKey(OBS_TKN, token.getBytes()); | 577 | byte[] tokenKey = toKey(OBS_TKN, token.getBytes()); |
612 | 578 | ||
613 | // fetch the observation by token | 579 | // fetch the observation by token |
614 | - byte[] serializedObs = j.get(tokenKey); | 580 | + byte[] serializedObs = connection.get(tokenKey); |
615 | if (serializedObs == null) | 581 | if (serializedObs == null) |
616 | return; | 582 | return; |
617 | 583 | ||
618 | org.eclipse.californium.core.observe.Observation obs = deserializeObs(serializedObs); | 584 | org.eclipse.californium.core.observe.Observation obs = deserializeObs(serializedObs); |
619 | String registrationId = ObserveUtil.extractRegistrationId(obs); | 585 | String registrationId = ObserveUtil.extractRegistrationId(obs); |
620 | - Registration registration = getRegistration(j, registrationId); | 586 | + Registration registration = getRegistration(connection, registrationId); |
621 | if (registration == null) { | 587 | if (registration == null) { |
622 | LOG.warn("Unable to remove observation {}, registration {} does not exist anymore", obs.getRequest(), | 588 | LOG.warn("Unable to remove observation {}, registration {} does not exist anymore", obs.getRequest(), |
623 | registrationId); | 589 | registrationId); |
@@ -625,14 +591,17 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -625,14 +591,17 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
625 | } | 591 | } |
626 | 592 | ||
627 | String endpoint = registration.getEndpoint(); | 593 | String endpoint = registration.getEndpoint(); |
628 | - byte[] lockValue = null; | ||
629 | - byte[] lockKey = toKey(LOCK_EP, endpoint); | 594 | + Lock lock = null; |
595 | + String lockKey = toLockKey(endpoint); | ||
630 | try { | 596 | try { |
631 | - lockValue = lock.acquire(j, lockKey); | 597 | + lock = redisLock.obtain(lockKey); |
598 | + lock.lock(); | ||
632 | 599 | ||
633 | - unsafeRemoveObservation(j, registrationId, token.getBytes()); | 600 | + unsafeRemoveObservation(connection, registrationId, token.getBytes()); |
634 | } finally { | 601 | } finally { |
635 | - lock.release(j, lockKey, lockValue); | 602 | + if (lock != null) { |
603 | + lock.unlock(); | ||
604 | + } | ||
636 | } | 605 | } |
637 | } | 606 | } |
638 | 607 | ||
@@ -640,8 +609,8 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -640,8 +609,8 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
640 | 609 | ||
641 | @Override | 610 | @Override |
642 | public org.eclipse.californium.core.observe.Observation get(Token token) { | 611 | public org.eclipse.californium.core.observe.Observation get(Token token) { |
643 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
644 | - byte[] obs = j.get(toKey(OBS_TKN, token.getBytes())); | 612 | + try (var connection = connectionFactory.getConnection()) { |
613 | + byte[] obs = connection.get(toKey(OBS_TKN, token.getBytes())); | ||
645 | if (obs == null) { | 614 | if (obs == null) { |
646 | return null; | 615 | return null; |
647 | } else { | 616 | } else { |
@@ -652,12 +621,12 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -652,12 +621,12 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
652 | 621 | ||
653 | /* *************** Observation utility functions **************** */ | 622 | /* *************** Observation utility functions **************** */ |
654 | 623 | ||
655 | - private Registration getRegistration(Jedis j, String registrationId) { | ||
656 | - byte[] ep = j.get(toRegIdKey(registrationId)); | 624 | + private Registration getRegistration(RedisConnection connection, String registrationId) { |
625 | + byte[] ep = connection.get(toRegIdKey(registrationId)); | ||
657 | if (ep == null) { | 626 | if (ep == null) { |
658 | return null; | 627 | return null; |
659 | } | 628 | } |
660 | - byte[] data = j.get(toEndpointKey(ep)); | 629 | + byte[] data = connection.get(toEndpointKey(ep)); |
661 | if (data == null) { | 630 | if (data == null) { |
662 | return null; | 631 | return null; |
663 | } | 632 | } |
@@ -665,25 +634,25 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -665,25 +634,25 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
665 | return deserializeReg(data); | 634 | return deserializeReg(data); |
666 | } | 635 | } |
667 | 636 | ||
668 | - private void unsafeRemoveObservation(Jedis j, String registrationId, byte[] observationId) { | ||
669 | - if (j.del(toKey(OBS_TKN, observationId)) > 0L) { | ||
670 | - j.lrem(toKey(OBS_TKNS_REGID_IDX, registrationId), 0, observationId); | 637 | + private void unsafeRemoveObservation(RedisConnection connection, String registrationId, byte[] observationId) { |
638 | + if (connection.del(toKey(OBS_TKN, observationId)) > 0L) { | ||
639 | + connection.lRem(toKey(OBS_TKNS_REGID_IDX, registrationId), 0, observationId); | ||
671 | } | 640 | } |
672 | } | 641 | } |
673 | 642 | ||
674 | - private Collection<Observation> unsafeRemoveAllObservations(Jedis j, String registrationId) { | 643 | + private Collection<Observation> unsafeRemoveAllObservations(RedisConnection connection, String registrationId) { |
675 | Collection<Observation> removed = new ArrayList<>(); | 644 | Collection<Observation> removed = new ArrayList<>(); |
676 | byte[] regIdKey = toKey(OBS_TKNS_REGID_IDX, registrationId); | 645 | byte[] regIdKey = toKey(OBS_TKNS_REGID_IDX, registrationId); |
677 | 646 | ||
678 | // fetch all observations by token | 647 | // fetch all observations by token |
679 | - for (byte[] token : j.lrange(regIdKey, 0, -1)) { | ||
680 | - byte[] obs = j.get(toKey(OBS_TKN, token)); | 648 | + for (byte[] token : connection.lRange(regIdKey, 0, -1)) { |
649 | + byte[] obs = connection.get(toKey(OBS_TKN, token)); | ||
681 | if (obs != null) { | 650 | if (obs != null) { |
682 | removed.add(build(deserializeObs(obs))); | 651 | removed.add(build(deserializeObs(obs))); |
683 | } | 652 | } |
684 | - j.del(toKey(OBS_TKN, token)); | 653 | + connection.del(toKey(OBS_TKN, token)); |
685 | } | 654 | } |
686 | - j.del(regIdKey); | 655 | + connection.del(regIdKey); |
687 | 656 | ||
688 | return removed; | 657 | return removed; |
689 | } | 658 | } |
@@ -754,14 +723,14 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | @@ -754,14 +723,14 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto | ||
754 | @Override | 723 | @Override |
755 | public void run() { | 724 | public void run() { |
756 | 725 | ||
757 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
758 | - Set<byte[]> endpointsExpired = j.zrangeByScore(EXP_EP, Double.NEGATIVE_INFINITY, | 726 | + try (var connection = connectionFactory.getConnection()) { |
727 | + Set<byte[]> endpointsExpired = connection.zRangeByScore(EXP_EP, Double.NEGATIVE_INFINITY, | ||
759 | System.currentTimeMillis(), 0, cleanLimit); | 728 | System.currentTimeMillis(), 0, cleanLimit); |
760 | 729 | ||
761 | for (byte[] endpoint : endpointsExpired) { | 730 | for (byte[] endpoint : endpointsExpired) { |
762 | - Registration r = deserializeReg(j.get(toEndpointKey(endpoint))); | 731 | + Registration r = deserializeReg(connection.get(toEndpointKey(endpoint))); |
763 | if (!r.isAlive(gracePeriod)) { | 732 | if (!r.isAlive(gracePeriod)) { |
764 | - Deregistration dereg = removeRegistration(j, r.getId(), true); | 733 | + Deregistration dereg = removeRegistration(connection, r.getId(), true); |
765 | if (dereg != null) | 734 | if (dereg != null) |
766 | expirationListener.registrationExpired(dereg.getRegistration(), dereg.getObservations()); | 735 | expirationListener.registrationExpired(dereg.getRegistration(), dereg.getObservations()); |
767 | } | 736 | } |
@@ -20,13 +20,15 @@ import org.eclipse.leshan.server.security.EditableSecurityStore; | @@ -20,13 +20,15 @@ import org.eclipse.leshan.server.security.EditableSecurityStore; | ||
20 | import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException; | 20 | import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException; |
21 | import org.eclipse.leshan.server.security.SecurityInfo; | 21 | import org.eclipse.leshan.server.security.SecurityInfo; |
22 | import org.eclipse.leshan.server.security.SecurityStoreListener; | 22 | import org.eclipse.leshan.server.security.SecurityStoreListener; |
23 | +import org.springframework.data.redis.connection.RedisClusterConnection; | ||
23 | import org.springframework.data.redis.connection.RedisConnectionFactory; | 24 | import org.springframework.data.redis.connection.RedisConnectionFactory; |
24 | -import redis.clients.jedis.Jedis; | ||
25 | -import redis.clients.jedis.ScanParams; | ||
26 | -import redis.clients.jedis.ScanResult; | 25 | +import org.springframework.data.redis.core.Cursor; |
26 | +import org.springframework.data.redis.core.ScanOptions; | ||
27 | 27 | ||
28 | +import java.util.ArrayList; | ||
28 | import java.util.Collection; | 29 | import java.util.Collection; |
29 | import java.util.LinkedList; | 30 | import java.util.LinkedList; |
31 | +import java.util.List; | ||
30 | 32 | ||
31 | public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { | 33 | public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { |
32 | private static final String SEC_EP = "SEC#EP#"; | 34 | private static final String SEC_EP = "SEC#EP#"; |
@@ -42,8 +44,8 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { | @@ -42,8 +44,8 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { | ||
42 | 44 | ||
43 | @Override | 45 | @Override |
44 | public SecurityInfo getByEndpoint(String endpoint) { | 46 | public SecurityInfo getByEndpoint(String endpoint) { |
45 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
46 | - byte[] data = j.get((SEC_EP + endpoint).getBytes()); | 47 | + try (var connection = connectionFactory.getConnection()) { |
48 | + byte[] data = connection.get((SEC_EP + endpoint).getBytes()); | ||
47 | if (data == null) { | 49 | if (data == null) { |
48 | return null; | 50 | return null; |
49 | } else { | 51 | } else { |
@@ -54,12 +56,12 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { | @@ -54,12 +56,12 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { | ||
54 | 56 | ||
55 | @Override | 57 | @Override |
56 | public SecurityInfo getByIdentity(String identity) { | 58 | public SecurityInfo getByIdentity(String identity) { |
57 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
58 | - String ep = j.hget(PSKID_SEC, identity); | 59 | + try (var connection = connectionFactory.getConnection()) { |
60 | + byte[] ep = connection.hGet(PSKID_SEC.getBytes(), identity.getBytes()); | ||
59 | if (ep == null) { | 61 | if (ep == null) { |
60 | return null; | 62 | return null; |
61 | } else { | 63 | } else { |
62 | - byte[] data = j.get((SEC_EP + ep).getBytes()); | 64 | + byte[] data = connection.get((SEC_EP + new String(ep)).getBytes()); |
63 | if (data == null) { | 65 | if (data == null) { |
64 | return null; | 66 | return null; |
65 | } else { | 67 | } else { |
@@ -71,18 +73,24 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { | @@ -71,18 +73,24 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { | ||
71 | 73 | ||
72 | @Override | 74 | @Override |
73 | public Collection<SecurityInfo> getAll() { | 75 | public Collection<SecurityInfo> getAll() { |
74 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
75 | - ScanParams params = new ScanParams().match(SEC_EP + "*").count(100); | 76 | + try (var connection = connectionFactory.getConnection()) { |
76 | Collection<SecurityInfo> list = new LinkedList<>(); | 77 | Collection<SecurityInfo> list = new LinkedList<>(); |
77 | - String cursor = "0"; | ||
78 | - do { | ||
79 | - ScanResult<byte[]> res = j.scan(cursor.getBytes(), params); | ||
80 | - for (byte[] key : res.getResult()) { | ||
81 | - byte[] element = j.get(key); | 78 | + ScanOptions scanOptions = ScanOptions.scanOptions().count(100).match(SEC_EP + "*").build(); |
79 | + List<Cursor<byte[]>> scans = new ArrayList<>(); | ||
80 | + if (connection instanceof RedisClusterConnection) { | ||
81 | + ((RedisClusterConnection) connection).clusterGetNodes().forEach(node -> { | ||
82 | + scans.add(((RedisClusterConnection) connection).scan(node, scanOptions)); | ||
83 | + }); | ||
84 | + } else { | ||
85 | + scans.add(connection.scan(scanOptions)); | ||
86 | + } | ||
87 | + | ||
88 | + scans.forEach(scan -> { | ||
89 | + scan.forEachRemaining(key -> { | ||
90 | + byte[] element = connection.get(key); | ||
82 | list.add(deserialize(element)); | 91 | list.add(deserialize(element)); |
83 | - } | ||
84 | - cursor = res.getCursor(); | ||
85 | - } while (!"0".equals(cursor)); | 92 | + }); |
93 | + }); | ||
86 | return list; | 94 | return list; |
87 | } | 95 | } |
88 | } | 96 | } |
@@ -90,21 +98,21 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { | @@ -90,21 +98,21 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { | ||
90 | @Override | 98 | @Override |
91 | public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException { | 99 | public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException { |
92 | byte[] data = serialize(info); | 100 | byte[] data = serialize(info); |
93 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | 101 | + try (var connection = connectionFactory.getConnection()) { |
94 | if (info.getIdentity() != null) { | 102 | if (info.getIdentity() != null) { |
95 | // populate the secondary index (security info by PSK id) | 103 | // populate the secondary index (security info by PSK id) |
96 | - String oldEndpoint = j.hget(PSKID_SEC, info.getIdentity()); | ||
97 | - if (oldEndpoint != null && !oldEndpoint.equals(info.getEndpoint())) { | 104 | + String oldEndpoint = new String(connection.hGet(PSKID_SEC.getBytes(), info.getIdentity().getBytes())); |
105 | + if (!oldEndpoint.equals(info.getEndpoint())) { | ||
98 | throw new NonUniqueSecurityInfoException("PSK Identity " + info.getIdentity() + " is already used"); | 106 | throw new NonUniqueSecurityInfoException("PSK Identity " + info.getIdentity() + " is already used"); |
99 | } | 107 | } |
100 | - j.hset(PSKID_SEC.getBytes(), info.getIdentity().getBytes(), info.getEndpoint().getBytes()); | 108 | + connection.hSet(PSKID_SEC.getBytes(), info.getIdentity().getBytes(), info.getEndpoint().getBytes()); |
101 | } | 109 | } |
102 | 110 | ||
103 | - byte[] previousData = j.getSet((SEC_EP + info.getEndpoint()).getBytes(), data); | 111 | + byte[] previousData = connection.getSet((SEC_EP + info.getEndpoint()).getBytes(), data); |
104 | SecurityInfo previous = previousData == null ? null : deserialize(previousData); | 112 | SecurityInfo previous = previousData == null ? null : deserialize(previousData); |
105 | String previousIdentity = previous == null ? null : previous.getIdentity(); | 113 | String previousIdentity = previous == null ? null : previous.getIdentity(); |
106 | if (previousIdentity != null && !previousIdentity.equals(info.getIdentity())) { | 114 | if (previousIdentity != null && !previousIdentity.equals(info.getIdentity())) { |
107 | - j.hdel(PSKID_SEC, previousIdentity); | 115 | + connection.hDel(PSKID_SEC.getBytes(), previousIdentity.getBytes()); |
108 | } | 116 | } |
109 | 117 | ||
110 | return previous; | 118 | return previous; |
@@ -113,15 +121,15 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { | @@ -113,15 +121,15 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { | ||
113 | 121 | ||
114 | @Override | 122 | @Override |
115 | public SecurityInfo remove(String endpoint, boolean infosAreCompromised) { | 123 | public SecurityInfo remove(String endpoint, boolean infosAreCompromised) { |
116 | - try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) { | ||
117 | - byte[] data = j.get((SEC_EP + endpoint).getBytes()); | 124 | + try (var connection = connectionFactory.getConnection()) { |
125 | + byte[] data = connection.get((SEC_EP + endpoint).getBytes()); | ||
118 | 126 | ||
119 | if (data != null) { | 127 | if (data != null) { |
120 | SecurityInfo info = deserialize(data); | 128 | SecurityInfo info = deserialize(data); |
121 | if (info.getIdentity() != null) { | 129 | if (info.getIdentity() != null) { |
122 | - j.hdel(PSKID_SEC.getBytes(), info.getIdentity().getBytes()); | 130 | + connection.hDel(PSKID_SEC.getBytes(), info.getIdentity().getBytes()); |
123 | } | 131 | } |
124 | - j.del((SEC_EP + endpoint).getBytes()); | 132 | + connection.del((SEC_EP + endpoint).getBytes()); |
125 | if (listener != null) { | 133 | if (listener != null) { |
126 | listener.securityInfoRemoved(infosAreCompromised, info); | 134 | listener.securityInfoRemoved(infosAreCompromised, info); |
127 | } | 135 | } |
@@ -74,7 +74,7 @@ public class TbLwM2mSecurityStore implements EditableSecurityStore { | @@ -74,7 +74,7 @@ public class TbLwM2mSecurityStore implements EditableSecurityStore { | ||
74 | add(securityInfo); | 74 | add(securityInfo); |
75 | } | 75 | } |
76 | } catch (NonUniqueSecurityInfoException e) { | 76 | } catch (NonUniqueSecurityInfoException e) { |
77 | - log.warn("Failed to add security info: {}", securityInfo, e); | 77 | + log.trace("Failed to add security info: {}", securityInfo, e); |
78 | } | 78 | } |
79 | } | 79 | } |
80 | return securityInfo; | 80 | return securityInfo; |
@@ -90,7 +90,7 @@ public class TbLwM2mSecurityStore implements EditableSecurityStore { | @@ -90,7 +90,7 @@ public class TbLwM2mSecurityStore implements EditableSecurityStore { | ||
90 | add(securityInfo); | 90 | add(securityInfo); |
91 | } | 91 | } |
92 | } catch (NonUniqueSecurityInfoException e) { | 92 | } catch (NonUniqueSecurityInfoException e) { |
93 | - log.warn("Failed to add security info: {}", securityInfo, e); | 93 | + log.trace("Failed to add security info: {}", securityInfo, e); |
94 | } | 94 | } |
95 | } | 95 | } |
96 | return securityInfo; | 96 | return securityInfo; |
@@ -26,6 +26,7 @@ import org.springframework.context.annotation.Lazy; | @@ -26,6 +26,7 @@ import org.springframework.context.annotation.Lazy; | ||
26 | import org.springframework.stereotype.Component; | 26 | import org.springframework.stereotype.Component; |
27 | import org.thingsboard.server.cache.TBRedisCacheConfiguration; | 27 | import org.thingsboard.server.cache.TBRedisCacheConfiguration; |
28 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | 28 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
29 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; | ||
29 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; | 30 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; |
30 | 31 | ||
31 | import java.util.Optional; | 32 | import java.util.Optional; |
@@ -38,6 +39,9 @@ public class TbLwM2mStoreFactory { | @@ -38,6 +39,9 @@ public class TbLwM2mStoreFactory { | ||
38 | private Optional<TBRedisCacheConfiguration> redisConfiguration; | 39 | private Optional<TBRedisCacheConfiguration> redisConfiguration; |
39 | 40 | ||
40 | @Autowired | 41 | @Autowired |
42 | + private LwM2MTransportServerConfig config; | ||
43 | + | ||
44 | + @Autowired | ||
41 | @Lazy | 45 | @Lazy |
42 | private LwM2mClientContext clientContext; | 46 | private LwM2mClientContext clientContext; |
43 | 47 | ||
@@ -47,7 +51,7 @@ public class TbLwM2mStoreFactory { | @@ -47,7 +51,7 @@ public class TbLwM2mStoreFactory { | ||
47 | @Bean | 51 | @Bean |
48 | private CaliforniumRegistrationStore registrationStore() { | 52 | private CaliforniumRegistrationStore registrationStore() { |
49 | return redisConfiguration.isPresent() && useRedis ? | 53 | return redisConfiguration.isPresent() && useRedis ? |
50 | - new TbLwM2mRedisRegistrationStore(redisConfiguration.get().redisConnectionFactory()) : new InMemoryRegistrationStore(); | 54 | + new TbLwM2mRedisRegistrationStore(redisConfiguration.get().redisConnectionFactory()) : new InMemoryRegistrationStore(config.getCleanPeriodInSec()); |
51 | } | 55 | } |
52 | 56 | ||
53 | @Bean | 57 | @Bean |
@@ -121,9 +121,11 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter { | @@ -121,9 +121,11 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter { | ||
121 | /** let's assume we received an ISO 8601 format date */ | 121 | /** let's assume we received an ISO 8601 format date */ |
122 | try { | 122 | try { |
123 | return new Date(Long.decode(value.toString())); | 123 | return new Date(Long.decode(value.toString())); |
124 | -// DatatypeFactory datatypeFactory = DatatypeFactory.newInstance(); | ||
125 | -// XMLGregorianCalendar cal = datatypeFactory.newXMLGregorianCalendar((String) value); | ||
126 | -// return cal.toGregorianCalendar().getTime(); | 124 | + /** |
125 | + DatatypeFactory datatypeFactory = DatatypeFactory.newInstance(); | ||
126 | + XMLGregorianCalendar cal = datatypeFactory.newXMLGregorianCalendar((String) value); | ||
127 | + return cal.toGregorianCalendar().getTime(); | ||
128 | + **/ | ||
127 | } catch (IllegalArgumentException e) { | 129 | } catch (IllegalArgumentException e) { |
128 | log.debug("Unable to convert string to date", e); | 130 | log.debug("Unable to convert string to date", e); |
129 | throw new CodecException("Unable to convert string (%s) to date for resource %s", value, | 131 | throw new CodecException("Unable to convert string (%s) to date for resource %s", value, |
@@ -48,6 +48,8 @@ public interface AlarmDao extends Dao<Alarm> { | @@ -48,6 +48,8 @@ public interface AlarmDao extends Dao<Alarm> { | ||
48 | 48 | ||
49 | PageData<AlarmInfo> findAlarms(TenantId tenantId, AlarmQuery query); | 49 | PageData<AlarmInfo> findAlarms(TenantId tenantId, AlarmQuery query); |
50 | 50 | ||
51 | + PageData<AlarmInfo> findCustomerAlarms(TenantId tenantId, CustomerId customerId, AlarmQuery query); | ||
52 | + | ||
51 | PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId, CustomerId customerId, | 53 | PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId, CustomerId customerId, |
52 | AlarmDataQuery query, Collection<EntityId> orderedEntityIds); | 54 | AlarmDataQuery query, Collection<EntityId> orderedEntityIds); |
53 | 55 |
@@ -41,7 +41,6 @@ import org.thingsboard.server.common.data.id.TenantId; | @@ -41,7 +41,6 @@ import org.thingsboard.server.common.data.id.TenantId; | ||
41 | import org.thingsboard.server.common.data.page.PageData; | 41 | import org.thingsboard.server.common.data.page.PageData; |
42 | import org.thingsboard.server.common.data.query.AlarmData; | 42 | import org.thingsboard.server.common.data.query.AlarmData; |
43 | import org.thingsboard.server.common.data.query.AlarmDataQuery; | 43 | import org.thingsboard.server.common.data.query.AlarmDataQuery; |
44 | -import org.thingsboard.server.common.data.query.DeviceTypeFilter; | ||
45 | import org.thingsboard.server.common.data.relation.EntityRelation; | 44 | import org.thingsboard.server.common.data.relation.EntityRelation; |
46 | import org.thingsboard.server.common.data.relation.EntityRelationsQuery; | 45 | import org.thingsboard.server.common.data.relation.EntityRelationsQuery; |
47 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; | 46 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; |
@@ -102,6 +101,11 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | @@ -102,6 +101,11 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | ||
102 | 101 | ||
103 | @Override | 102 | @Override |
104 | public AlarmOperationResult createOrUpdateAlarm(Alarm alarm) { | 103 | public AlarmOperationResult createOrUpdateAlarm(Alarm alarm) { |
104 | + return createOrUpdateAlarm(alarm, true); | ||
105 | + } | ||
106 | + | ||
107 | + @Override | ||
108 | + public AlarmOperationResult createOrUpdateAlarm(Alarm alarm, boolean alarmCreationEnabled) { | ||
105 | alarmDataValidator.validate(alarm, Alarm::getTenantId); | 109 | alarmDataValidator.validate(alarm, Alarm::getTenantId); |
106 | try { | 110 | try { |
107 | if (alarm.getStartTs() == 0L) { | 111 | if (alarm.getStartTs() == 0L) { |
@@ -110,9 +114,13 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | @@ -110,9 +114,13 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | ||
110 | if (alarm.getEndTs() == 0L) { | 114 | if (alarm.getEndTs() == 0L) { |
111 | alarm.setEndTs(alarm.getStartTs()); | 115 | alarm.setEndTs(alarm.getStartTs()); |
112 | } | 116 | } |
117 | + alarm.setCustomerId(entityService.fetchEntityCustomerId(alarm.getTenantId(), alarm.getOriginator())); | ||
113 | if (alarm.getId() == null) { | 118 | if (alarm.getId() == null) { |
114 | Alarm existing = alarmDao.findLatestByOriginatorAndType(alarm.getTenantId(), alarm.getOriginator(), alarm.getType()).get(); | 119 | Alarm existing = alarmDao.findLatestByOriginatorAndType(alarm.getTenantId(), alarm.getOriginator(), alarm.getType()).get(); |
115 | if (existing == null || existing.getStatus().isCleared()) { | 120 | if (existing == null || existing.getStatus().isCleared()) { |
121 | + if (!alarmCreationEnabled) { | ||
122 | + throw new IllegalStateException("Alarm creation is disabled"); | ||
123 | + } | ||
116 | return createAlarm(alarm); | 124 | return createAlarm(alarm); |
117 | } else { | 125 | } else { |
118 | return updateAlarm(existing, alarm); | 126 | return updateAlarm(existing, alarm); |
@@ -158,7 +166,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | @@ -158,7 +166,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | ||
158 | log.debug("New Alarm : {}", alarm); | 166 | log.debug("New Alarm : {}", alarm); |
159 | Alarm saved = alarmDao.save(alarm.getTenantId(), alarm); | 167 | Alarm saved = alarmDao.save(alarm.getTenantId(), alarm); |
160 | List<EntityId> propagatedEntitiesList = createAlarmRelations(saved); | 168 | List<EntityId> propagatedEntitiesList = createAlarmRelations(saved); |
161 | - return new AlarmOperationResult(saved, true, propagatedEntitiesList); | 169 | + return new AlarmOperationResult(saved, true, true, propagatedEntitiesList); |
162 | } | 170 | } |
163 | 171 | ||
164 | private List<EntityId> createAlarmRelations(Alarm alarm) throws InterruptedException, ExecutionException { | 172 | private List<EntityId> createAlarmRelations(Alarm alarm) throws InterruptedException, ExecutionException { |
@@ -292,26 +300,39 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | @@ -292,26 +300,39 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | ||
292 | public ListenableFuture<PageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query) { | 300 | public ListenableFuture<PageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query) { |
293 | PageData<AlarmInfo> alarms = alarmDao.findAlarms(tenantId, query); | 301 | PageData<AlarmInfo> alarms = alarmDao.findAlarms(tenantId, query); |
294 | if (query.getFetchOriginator() != null && query.getFetchOriginator().booleanValue()) { | 302 | if (query.getFetchOriginator() != null && query.getFetchOriginator().booleanValue()) { |
295 | - List<ListenableFuture<AlarmInfo>> alarmFutures = new ArrayList<>(alarms.getData().size()); | ||
296 | - for (AlarmInfo alarmInfo : alarms.getData()) { | ||
297 | - alarmFutures.add(Futures.transform( | ||
298 | - entityService.fetchEntityNameAsync(tenantId, alarmInfo.getOriginator()), originatorName -> { | ||
299 | - if (originatorName == null) { | ||
300 | - originatorName = "Deleted"; | ||
301 | - } | ||
302 | - alarmInfo.setOriginatorName(originatorName); | ||
303 | - return alarmInfo; | ||
304 | - }, MoreExecutors.directExecutor() | ||
305 | - )); | ||
306 | - } | ||
307 | - return Futures.transform(Futures.successfulAsList(alarmFutures), | ||
308 | - alarmInfos -> new PageData<>(alarmInfos, alarms.getTotalPages(), alarms.getTotalElements(), | ||
309 | - alarms.hasNext()), MoreExecutors.directExecutor()); | 303 | + return fetchAlarmsOriginators(tenantId, alarms); |
310 | } | 304 | } |
311 | return Futures.immediateFuture(alarms); | 305 | return Futures.immediateFuture(alarms); |
312 | } | 306 | } |
313 | 307 | ||
314 | @Override | 308 | @Override |
309 | + public ListenableFuture<PageData<AlarmInfo>> findCustomerAlarms(TenantId tenantId, CustomerId customerId, AlarmQuery query) { | ||
310 | + PageData<AlarmInfo> alarms = alarmDao.findCustomerAlarms(tenantId, customerId, query); | ||
311 | + if (query.getFetchOriginator() != null && query.getFetchOriginator().booleanValue()) { | ||
312 | + return fetchAlarmsOriginators(tenantId, alarms); | ||
313 | + } | ||
314 | + return Futures.immediateFuture(alarms); | ||
315 | + } | ||
316 | + | ||
317 | + private ListenableFuture<PageData<AlarmInfo>> fetchAlarmsOriginators(TenantId tenantId, PageData<AlarmInfo> alarms) { | ||
318 | + List<ListenableFuture<AlarmInfo>> alarmFutures = new ArrayList<>(alarms.getData().size()); | ||
319 | + for (AlarmInfo alarmInfo : alarms.getData()) { | ||
320 | + alarmFutures.add(Futures.transform( | ||
321 | + entityService.fetchEntityNameAsync(tenantId, alarmInfo.getOriginator()), originatorName -> { | ||
322 | + if (originatorName == null) { | ||
323 | + originatorName = "Deleted"; | ||
324 | + } | ||
325 | + alarmInfo.setOriginatorName(originatorName); | ||
326 | + return alarmInfo; | ||
327 | + }, MoreExecutors.directExecutor() | ||
328 | + )); | ||
329 | + } | ||
330 | + return Futures.transform(Futures.successfulAsList(alarmFutures), | ||
331 | + alarmInfos -> new PageData<>(alarmInfos, alarms.getTotalPages(), alarms.getTotalElements(), | ||
332 | + alarms.hasNext()), MoreExecutors.directExecutor()); | ||
333 | + } | ||
334 | + | ||
335 | + @Override | ||
315 | public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, | 336 | public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, |
316 | AlarmStatus alarmStatus) { | 337 | AlarmStatus alarmStatus) { |
317 | Set<AlarmStatus> statusList = null; | 338 | Set<AlarmStatus> statusList = null; |
@@ -342,6 +363,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | @@ -342,6 +363,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | ||
342 | existing.setStatus(alarm.getStatus()); | 363 | existing.setStatus(alarm.getStatus()); |
343 | existing.setSeverity(alarm.getSeverity()); | 364 | existing.setSeverity(alarm.getSeverity()); |
344 | existing.setDetails(alarm.getDetails()); | 365 | existing.setDetails(alarm.getDetails()); |
366 | + existing.setCustomerId(alarm.getCustomerId()); | ||
345 | existing.setPropagate(existing.isPropagate() || alarm.isPropagate()); | 367 | existing.setPropagate(existing.isPropagate() || alarm.isPropagate()); |
346 | List<String> existingPropagateRelationTypes = existing.getPropagateRelationTypes(); | 368 | List<String> existingPropagateRelationTypes = existing.getPropagateRelationTypes(); |
347 | List<String> newRelationTypes = alarm.getPropagateRelationTypes(); | 369 | List<String> newRelationTypes = alarm.getPropagateRelationTypes(); |
@@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
16 | package org.thingsboard.server.dao.asset; | 16 | package org.thingsboard.server.dao.asset; |
17 | 17 | ||
18 | 18 | ||
19 | -import com.google.common.base.Function; | ||
20 | import com.google.common.util.concurrent.Futures; | 19 | import com.google.common.util.concurrent.Futures; |
21 | import com.google.common.util.concurrent.ListenableFuture; | 20 | import com.google.common.util.concurrent.ListenableFuture; |
22 | import com.google.common.util.concurrent.MoreExecutors; | 21 | import com.google.common.util.concurrent.MoreExecutors; |
@@ -46,11 +45,10 @@ import org.thingsboard.server.common.data.id.EntityId; | @@ -46,11 +45,10 @@ import org.thingsboard.server.common.data.id.EntityId; | ||
46 | import org.thingsboard.server.common.data.id.TenantId; | 45 | import org.thingsboard.server.common.data.id.TenantId; |
47 | import org.thingsboard.server.common.data.page.PageData; | 46 | import org.thingsboard.server.common.data.page.PageData; |
48 | import org.thingsboard.server.common.data.page.PageLink; | 47 | import org.thingsboard.server.common.data.page.PageLink; |
49 | -import org.thingsboard.server.common.data.page.TimePageLink; | ||
50 | import org.thingsboard.server.common.data.relation.EntityRelation; | 48 | import org.thingsboard.server.common.data.relation.EntityRelation; |
51 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; | 49 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; |
52 | -import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; | ||
53 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; | 50 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
51 | +import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; | ||
54 | import org.thingsboard.server.dao.customer.CustomerDao; | 52 | import org.thingsboard.server.dao.customer.CustomerDao; |
55 | import org.thingsboard.server.dao.entity.AbstractEntityService; | 53 | import org.thingsboard.server.dao.entity.AbstractEntityService; |
56 | import org.thingsboard.server.dao.exception.DataValidationException; | 54 | import org.thingsboard.server.dao.exception.DataValidationException; |
@@ -59,8 +57,8 @@ import org.thingsboard.server.dao.service.PaginatedRemover; | @@ -59,8 +57,8 @@ import org.thingsboard.server.dao.service.PaginatedRemover; | ||
59 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; | 57 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
60 | import org.thingsboard.server.dao.tenant.TenantDao; | 58 | import org.thingsboard.server.dao.tenant.TenantDao; |
61 | 59 | ||
62 | -import javax.annotation.Nullable; | ||
63 | import java.util.ArrayList; | 60 | import java.util.ArrayList; |
61 | +import java.util.Arrays; | ||
64 | import java.util.Collections; | 62 | import java.util.Collections; |
65 | import java.util.Comparator; | 63 | import java.util.Comparator; |
66 | import java.util.List; | 64 | import java.util.List; |
@@ -180,15 +178,16 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ | @@ -180,15 +178,16 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ | ||
180 | throw new RuntimeException("Exception while finding entity views for assetId [" + assetId + "]", e); | 178 | throw new RuntimeException("Exception while finding entity views for assetId [" + assetId + "]", e); |
181 | } | 179 | } |
182 | 180 | ||
183 | - List<Object> list = new ArrayList<>(); | ||
184 | - list.add(asset.getTenantId()); | ||
185 | - list.add(asset.getName()); | ||
186 | - Cache cache = cacheManager.getCache(ASSET_CACHE); | ||
187 | - cache.evict(list); | 181 | + removeAssetFromCacheByName(asset.getTenantId(), asset.getName()); |
188 | 182 | ||
189 | assetDao.removeById(tenantId, assetId.getId()); | 183 | assetDao.removeById(tenantId, assetId.getId()); |
190 | } | 184 | } |
191 | 185 | ||
186 | + private void removeAssetFromCacheByName(TenantId tenantId, String name) { | ||
187 | + Cache cache = cacheManager.getCache(ASSET_CACHE); | ||
188 | + cache.evict(Arrays.asList(tenantId, name)); | ||
189 | + } | ||
190 | + | ||
192 | @Override | 191 | @Override |
193 | public PageData<Asset> findAssetsByTenantId(TenantId tenantId, PageLink pageLink) { | 192 | public PageData<Asset> findAssetsByTenantId(TenantId tenantId, PageLink pageLink) { |
194 | log.trace("Executing findAssetsByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink); | 193 | log.trace("Executing findAssetsByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink); |
@@ -397,6 +396,13 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ | @@ -397,6 +396,13 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ | ||
397 | 396 | ||
398 | @Override | 397 | @Override |
399 | protected void validateUpdate(TenantId tenantId, Asset asset) { | 398 | protected void validateUpdate(TenantId tenantId, Asset asset) { |
399 | + Asset old = assetDao.findById(asset.getTenantId(), asset.getId().getId()); | ||
400 | + if (old == null) { | ||
401 | + throw new DataValidationException("Can't update non existing asset!"); | ||
402 | + } | ||
403 | + if (!old.getName().equals(asset.getName())) { | ||
404 | + removeAssetFromCacheByName(tenantId, old.getName()); | ||
405 | + } | ||
400 | } | 406 | } |
401 | 407 | ||
402 | @Override | 408 | @Override |
@@ -18,6 +18,7 @@ package org.thingsboard.server.dao.dashboard; | @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.dashboard; | ||
18 | import com.google.common.util.concurrent.ListenableFuture; | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
20 | import org.apache.commons.lang3.StringUtils; | 20 | import org.apache.commons.lang3.StringUtils; |
21 | +import org.hibernate.exception.ConstraintViolationException; | ||
21 | import org.springframework.beans.factory.annotation.Autowired; | 22 | import org.springframework.beans.factory.annotation.Autowired; |
22 | import org.springframework.context.annotation.Lazy; | 23 | import org.springframework.context.annotation.Lazy; |
23 | import org.springframework.stereotype.Service; | 24 | import org.springframework.stereotype.Service; |
@@ -166,7 +167,16 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb | @@ -166,7 +167,16 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb | ||
166 | log.trace("Executing deleteDashboard [{}]", dashboardId); | 167 | log.trace("Executing deleteDashboard [{}]", dashboardId); |
167 | Validator.validateId(dashboardId, INCORRECT_DASHBOARD_ID + dashboardId); | 168 | Validator.validateId(dashboardId, INCORRECT_DASHBOARD_ID + dashboardId); |
168 | deleteEntityRelations(tenantId, dashboardId); | 169 | deleteEntityRelations(tenantId, dashboardId); |
169 | - dashboardDao.removeById(tenantId, dashboardId.getId()); | 170 | + try { |
171 | + dashboardDao.removeById(tenantId, dashboardId.getId()); | ||
172 | + } catch (Exception t) { | ||
173 | + ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); | ||
174 | + if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_default_dashboard_device_profile")) { | ||
175 | + throw new DataValidationException("The dashboard referenced by the device profiles cannot be deleted!"); | ||
176 | + } else { | ||
177 | + throw t; | ||
178 | + } | ||
179 | + } | ||
170 | } | 180 | } |
171 | 181 | ||
172 | @Override | 182 | @Override |
@@ -36,6 +36,7 @@ import org.springframework.cache.CacheManager; | @@ -36,6 +36,7 @@ import org.springframework.cache.CacheManager; | ||
36 | import org.springframework.cache.annotation.Cacheable; | 36 | import org.springframework.cache.annotation.Cacheable; |
37 | import org.springframework.stereotype.Service; | 37 | import org.springframework.stereotype.Service; |
38 | import org.springframework.util.CollectionUtils; | 38 | import org.springframework.util.CollectionUtils; |
39 | +import org.thingsboard.server.common.data.DashboardInfo; | ||
39 | import org.thingsboard.server.common.data.Device; | 40 | import org.thingsboard.server.common.data.Device; |
40 | import org.thingsboard.server.common.data.DeviceProfile; | 41 | import org.thingsboard.server.common.data.DeviceProfile; |
41 | import org.thingsboard.server.common.data.DeviceProfileInfo; | 42 | import org.thingsboard.server.common.data.DeviceProfileInfo; |
@@ -61,9 +62,12 @@ import org.thingsboard.server.common.data.id.DeviceProfileId; | @@ -61,9 +62,12 @@ import org.thingsboard.server.common.data.id.DeviceProfileId; | ||
61 | import org.thingsboard.server.common.data.id.TenantId; | 62 | import org.thingsboard.server.common.data.id.TenantId; |
62 | import org.thingsboard.server.common.data.page.PageData; | 63 | import org.thingsboard.server.common.data.page.PageData; |
63 | import org.thingsboard.server.common.data.page.PageLink; | 64 | import org.thingsboard.server.common.data.page.PageLink; |
65 | +import org.thingsboard.server.common.data.rule.RuleChain; | ||
66 | +import org.thingsboard.server.dao.dashboard.DashboardService; | ||
64 | import org.thingsboard.server.dao.entity.AbstractEntityService; | 67 | import org.thingsboard.server.dao.entity.AbstractEntityService; |
65 | import org.thingsboard.server.dao.exception.DataValidationException; | 68 | import org.thingsboard.server.dao.exception.DataValidationException; |
66 | import org.thingsboard.server.dao.firmware.FirmwareService; | 69 | import org.thingsboard.server.dao.firmware.FirmwareService; |
70 | +import org.thingsboard.server.dao.rule.RuleChainService; | ||
67 | import org.thingsboard.server.dao.service.DataValidator; | 71 | import org.thingsboard.server.dao.service.DataValidator; |
68 | import org.thingsboard.server.dao.service.PaginatedRemover; | 72 | import org.thingsboard.server.dao.service.PaginatedRemover; |
69 | import org.thingsboard.server.dao.service.Validator; | 73 | import org.thingsboard.server.dao.service.Validator; |
@@ -117,6 +121,12 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -117,6 +121,12 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
117 | @Autowired | 121 | @Autowired |
118 | private FirmwareService firmwareService; | 122 | private FirmwareService firmwareService; |
119 | 123 | ||
124 | + @Autowired | ||
125 | + private RuleChainService ruleChainService; | ||
126 | + | ||
127 | + @Autowired | ||
128 | + private DashboardService dashboardService; | ||
129 | + | ||
120 | private final Lock findOrCreateLock = new ReentrantLock(); | 130 | private final Lock findOrCreateLock = new ReentrantLock(); |
121 | 131 | ||
122 | @Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{#deviceProfileId.id}") | 132 | @Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{#deviceProfileId.id}") |
@@ -336,7 +346,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -336,7 +346,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
336 | } | 346 | } |
337 | 347 | ||
338 | private DataValidator<DeviceProfile> deviceProfileValidator = | 348 | private DataValidator<DeviceProfile> deviceProfileValidator = |
339 | - new DataValidator<DeviceProfile>() { | 349 | + new DataValidator<>() { |
340 | @Override | 350 | @Override |
341 | protected void validateDataImpl(TenantId tenantId, DeviceProfile deviceProfile) { | 351 | protected void validateDataImpl(TenantId tenantId, DeviceProfile deviceProfile) { |
342 | if (StringUtils.isEmpty(deviceProfile.getName())) { | 352 | if (StringUtils.isEmpty(deviceProfile.getName())) { |
@@ -402,6 +412,20 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -402,6 +412,20 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
402 | } | 412 | } |
403 | } | 413 | } |
404 | 414 | ||
415 | + if (deviceProfile.getDefaultRuleChainId() != null) { | ||
416 | + RuleChain ruleChain = ruleChainService.findRuleChainById(tenantId, deviceProfile.getDefaultRuleChainId()); | ||
417 | + if (ruleChain == null) { | ||
418 | + throw new DataValidationException("Can't assign non-existent rule chain!"); | ||
419 | + } | ||
420 | + } | ||
421 | + | ||
422 | + if (deviceProfile.getDefaultDashboardId() != null) { | ||
423 | + DashboardInfo dashboard = dashboardService.findDashboardInfoById(tenantId, deviceProfile.getDefaultDashboardId()); | ||
424 | + if (dashboard == null) { | ||
425 | + throw new DataValidationException("Can't assign non-existent dashboard!"); | ||
426 | + } | ||
427 | + } | ||
428 | + | ||
405 | if (deviceProfile.getFirmwareId() != null) { | 429 | if (deviceProfile.getFirmwareId() != null) { |
406 | Firmware firmware = firmwareService.findFirmwareById(tenantId, deviceProfile.getFirmwareId()); | 430 | Firmware firmware = firmwareService.findFirmwareById(tenantId, deviceProfile.getFirmwareId()); |
407 | if (firmware == null) { | 431 | if (firmware == null) { |
@@ -84,6 +84,7 @@ import org.thingsboard.common.util.JacksonUtil; | @@ -84,6 +84,7 @@ import org.thingsboard.common.util.JacksonUtil; | ||
84 | 84 | ||
85 | import javax.annotation.Nullable; | 85 | import javax.annotation.Nullable; |
86 | import java.util.ArrayList; | 86 | import java.util.ArrayList; |
87 | +import java.util.Arrays; | ||
87 | import java.util.Collections; | 88 | import java.util.Collections; |
88 | import java.util.Comparator; | 89 | import java.util.Comparator; |
89 | import java.util.List; | 90 | import java.util.List; |
@@ -245,7 +246,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -245,7 +246,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
245 | ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); | 246 | ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); |
246 | if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("device_name_unq_key")) { | 247 | if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("device_name_unq_key")) { |
247 | // remove device from cache in case null value cached in the distributed redis. | 248 | // remove device from cache in case null value cached in the distributed redis. |
248 | - removeDeviceFromCache(device.getTenantId(), device.getName()); | 249 | + removeDeviceFromCacheByName(device.getTenantId(), device.getName()); |
249 | throw new DataValidationException("Device with such name already exists!"); | 250 | throw new DataValidationException("Device with such name already exists!"); |
250 | } else { | 251 | } else { |
251 | throw t; | 252 | throw t; |
@@ -322,17 +323,14 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -322,17 +323,14 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
322 | } | 323 | } |
323 | deleteEntityRelations(tenantId, deviceId); | 324 | deleteEntityRelations(tenantId, deviceId); |
324 | 325 | ||
325 | - removeDeviceFromCache(tenantId, device.getName()); | 326 | + removeDeviceFromCacheByName(tenantId, device.getName()); |
326 | 327 | ||
327 | deviceDao.removeById(tenantId, deviceId.getId()); | 328 | deviceDao.removeById(tenantId, deviceId.getId()); |
328 | } | 329 | } |
329 | 330 | ||
330 | - private void removeDeviceFromCache(TenantId tenantId, String name) { | ||
331 | - List<Object> list = new ArrayList<>(); | ||
332 | - list.add(tenantId); | ||
333 | - list.add(name); | 331 | + private void removeDeviceFromCacheByName(TenantId tenantId, String name) { |
334 | Cache cache = cacheManager.getCache(DEVICE_CACHE); | 332 | Cache cache = cacheManager.getCache(DEVICE_CACHE); |
335 | - cache.evict(list); | 333 | + cache.evict(Arrays.asList(tenantId, name)); |
336 | } | 334 | } |
337 | 335 | ||
338 | @Override | 336 | @Override |
@@ -671,6 +669,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -671,6 +669,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
671 | if (old == null) { | 669 | if (old == null) { |
672 | throw new DataValidationException("Can't update non existing device!"); | 670 | throw new DataValidationException("Can't update non existing device!"); |
673 | } | 671 | } |
672 | + if (!old.getName().equals(device.getName())) { | ||
673 | + removeDeviceFromCacheByName(tenantId, old.getName()); | ||
674 | + } | ||
674 | } | 675 | } |
675 | 676 | ||
676 | @Override | 677 | @Override |
@@ -58,7 +58,6 @@ import org.thingsboard.server.common.data.id.TenantId; | @@ -58,7 +58,6 @@ import org.thingsboard.server.common.data.id.TenantId; | ||
58 | import org.thingsboard.server.common.data.id.UserId; | 58 | import org.thingsboard.server.common.data.id.UserId; |
59 | import org.thingsboard.server.common.data.page.PageData; | 59 | import org.thingsboard.server.common.data.page.PageData; |
60 | import org.thingsboard.server.common.data.page.PageLink; | 60 | import org.thingsboard.server.common.data.page.PageLink; |
61 | -import org.thingsboard.server.common.data.page.TimePageLink; | ||
62 | import org.thingsboard.server.common.data.relation.EntityRelation; | 61 | import org.thingsboard.server.common.data.relation.EntityRelation; |
63 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; | 62 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; |
64 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; | 63 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
@@ -80,6 +79,7 @@ import javax.annotation.PostConstruct; | @@ -80,6 +79,7 @@ import javax.annotation.PostConstruct; | ||
80 | import java.net.InetSocketAddress; | 79 | import java.net.InetSocketAddress; |
81 | import java.net.Proxy; | 80 | import java.net.Proxy; |
82 | import java.util.ArrayList; | 81 | import java.util.ArrayList; |
82 | +import java.util.Arrays; | ||
83 | import java.util.Collections; | 83 | import java.util.Collections; |
84 | import java.util.Comparator; | 84 | import java.util.Comparator; |
85 | import java.util.HashMap; | 85 | import java.util.HashMap; |
@@ -222,17 +222,18 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic | @@ -222,17 +222,18 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic | ||
222 | 222 | ||
223 | Edge edge = edgeDao.findById(tenantId, edgeId.getId()); | 223 | Edge edge = edgeDao.findById(tenantId, edgeId.getId()); |
224 | 224 | ||
225 | - List<Object> list = new ArrayList<>(); | ||
226 | - list.add(edge.getTenantId()); | ||
227 | - list.add(edge.getName()); | ||
228 | - Cache cache = cacheManager.getCache(EDGE_CACHE); | ||
229 | - cache.evict(list); | ||
230 | - | ||
231 | deleteEntityRelations(tenantId, edgeId); | 225 | deleteEntityRelations(tenantId, edgeId); |
232 | 226 | ||
227 | + removeEdgeFromCacheByName(edge.getTenantId(), edge.getName()); | ||
228 | + | ||
233 | edgeDao.removeById(tenantId, edgeId.getId()); | 229 | edgeDao.removeById(tenantId, edgeId.getId()); |
234 | } | 230 | } |
235 | 231 | ||
232 | + private void removeEdgeFromCacheByName(TenantId tenantId, String name) { | ||
233 | + Cache cache = cacheManager.getCache(EDGE_CACHE); | ||
234 | + cache.evict(Arrays.asList(tenantId, name)); | ||
235 | + } | ||
236 | + | ||
236 | @Override | 237 | @Override |
237 | public PageData<Edge> findEdgesByTenantId(TenantId tenantId, PageLink pageLink) { | 238 | public PageData<Edge> findEdgesByTenantId(TenantId tenantId, PageLink pageLink) { |
238 | log.trace("Executing findEdgesByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink); | 239 | log.trace("Executing findEdgesByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink); |
@@ -423,6 +424,10 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic | @@ -423,6 +424,10 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic | ||
423 | 424 | ||
424 | @Override | 425 | @Override |
425 | protected void validateUpdate(TenantId tenantId, Edge edge) { | 426 | protected void validateUpdate(TenantId tenantId, Edge edge) { |
427 | + Edge old = edgeDao.findById(edge.getTenantId(), edge.getId().getId()); | ||
428 | + if (!old.getName().equals(edge.getName())) { | ||
429 | + removeEdgeFromCacheByName(tenantId, old.getName()); | ||
430 | + } | ||
426 | } | 431 | } |
427 | 432 | ||
428 | @Override | 433 | @Override |