Commit cf405be4f3a350e9fada398d5c775fea41354398
Merge branch 'master' of github.com:thingsboard/thingsboard
Showing
66 changed files
with
1599 additions
and
938 deletions
Too many changes to show.
To preserve performance only 66 of 140 files are displayed.
@@ -63,6 +63,8 @@ CREATE TABLE IF NOT EXISTS firmware ( | @@ -63,6 +63,8 @@ CREATE TABLE IF NOT EXISTS firmware ( | ||
63 | id uuid NOT NULL CONSTRAINT firmware_pkey PRIMARY KEY, | 63 | id uuid NOT NULL CONSTRAINT firmware_pkey PRIMARY KEY, |
64 | created_time bigint NOT NULL, | 64 | created_time bigint NOT NULL, |
65 | tenant_id uuid NOT NULL, | 65 | tenant_id uuid NOT NULL, |
66 | + device_profile_id uuid, | ||
67 | + type varchar(32) NOT NULL, | ||
66 | title varchar(255) NOT NULL, | 68 | title varchar(255) NOT NULL, |
67 | version varchar(255) NOT NULL, | 69 | version varchar(255) NOT NULL, |
68 | file_name varchar(255), | 70 | file_name varchar(255), |
@@ -77,10 +79,12 @@ CREATE TABLE IF NOT EXISTS firmware ( | @@ -77,10 +79,12 @@ CREATE TABLE IF NOT EXISTS firmware ( | ||
77 | ); | 79 | ); |
78 | 80 | ||
79 | ALTER TABLE device_profile | 81 | ALTER TABLE device_profile |
80 | - ADD COLUMN IF NOT EXISTS firmware_id uuid; | 82 | + ADD COLUMN IF NOT EXISTS firmware_id uuid, |
83 | + ADD COLUMN IF NOT EXISTS software_id uuid; | ||
81 | 84 | ||
82 | ALTER TABLE device | 85 | ALTER TABLE device |
83 | - ADD COLUMN IF NOT EXISTS firmware_id uuid; | 86 | + ADD COLUMN IF NOT EXISTS firmware_id uuid, |
87 | + ADD COLUMN IF NOT EXISTS software_id uuid; | ||
84 | 88 | ||
85 | DO $$ | 89 | DO $$ |
86 | BEGIN | 90 | BEGIN |
@@ -90,11 +94,23 @@ DO $$ | @@ -90,11 +94,23 @@ DO $$ | ||
90 | FOREIGN KEY (firmware_id) REFERENCES firmware(id); | 94 | FOREIGN KEY (firmware_id) REFERENCES firmware(id); |
91 | END IF; | 95 | END IF; |
92 | 96 | ||
97 | + IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_software_device_profile') THEN | ||
98 | + ALTER TABLE device_profile | ||
99 | + ADD CONSTRAINT fk_software_device_profile | ||
100 | + FOREIGN KEY (firmware_id) REFERENCES firmware(id); | ||
101 | + END IF; | ||
102 | + | ||
93 | IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device') THEN | 103 | IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device') THEN |
94 | ALTER TABLE device | 104 | ALTER TABLE device |
95 | ADD CONSTRAINT fk_firmware_device | 105 | ADD CONSTRAINT fk_firmware_device |
96 | FOREIGN KEY (firmware_id) REFERENCES firmware(id); | 106 | FOREIGN KEY (firmware_id) REFERENCES firmware(id); |
97 | END IF; | 107 | END IF; |
108 | + | ||
109 | + IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_software_device') THEN | ||
110 | + ALTER TABLE device | ||
111 | + ADD CONSTRAINT fk_software_device | ||
112 | + FOREIGN KEY (firmware_id) REFERENCES firmware(id); | ||
113 | + END IF; | ||
98 | END; | 114 | END; |
99 | $$; | 115 | $$; |
100 | 116 |
@@ -132,7 +132,7 @@ import org.thingsboard.server.service.firmware.FirmwareStateService; | @@ -132,7 +132,7 @@ import org.thingsboard.server.service.firmware.FirmwareStateService; | ||
132 | import org.thingsboard.server.service.edge.EdgeNotificationService; | 132 | import org.thingsboard.server.service.edge.EdgeNotificationService; |
133 | import org.thingsboard.server.service.edge.rpc.EdgeGrpcService; | 133 | import org.thingsboard.server.service.edge.rpc.EdgeGrpcService; |
134 | import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService; | 134 | import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService; |
135 | -import org.thingsboard.server.service.lwm2m.LwM2MModelsRepository; | 135 | +import org.thingsboard.server.service.lwm2m.LwM2MServerSecurityInfoRepository; |
136 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; | 136 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
137 | import org.thingsboard.server.service.queue.TbClusterService; | 137 | import org.thingsboard.server.service.queue.TbClusterService; |
138 | import org.thingsboard.server.service.resource.TbResourceService; | 138 | import org.thingsboard.server.service.resource.TbResourceService; |
@@ -267,7 +267,7 @@ public abstract class BaseController { | @@ -267,7 +267,7 @@ public abstract class BaseController { | ||
267 | protected TbDeviceProfileCache deviceProfileCache; | 267 | protected TbDeviceProfileCache deviceProfileCache; |
268 | 268 | ||
269 | @Autowired | 269 | @Autowired |
270 | - protected LwM2MModelsRepository lwM2MModelsRepository; | 270 | + protected LwM2MServerSecurityInfoRepository lwM2MServerSecurityInfoRepository; |
271 | 271 | ||
272 | @Autowired(required = false) | 272 | @Autowired(required = false) |
273 | protected EdgeService edgeService; | 273 | protected EdgeService edgeService; |
@@ -146,12 +146,16 @@ public class DeviceProfileController extends BaseController { | @@ -146,12 +146,16 @@ public class DeviceProfileController extends BaseController { | ||
146 | checkEntity(deviceProfile.getId(), deviceProfile, Resource.DEVICE_PROFILE); | 146 | checkEntity(deviceProfile.getId(), deviceProfile, Resource.DEVICE_PROFILE); |
147 | 147 | ||
148 | boolean isFirmwareChanged = false; | 148 | boolean isFirmwareChanged = false; |
149 | + boolean isSoftwareChanged = false; | ||
149 | 150 | ||
150 | if (!created) { | 151 | if (!created) { |
151 | DeviceProfile oldDeviceProfile = deviceProfileService.findDeviceProfileById(getTenantId(), deviceProfile.getId()); | 152 | DeviceProfile oldDeviceProfile = deviceProfileService.findDeviceProfileById(getTenantId(), deviceProfile.getId()); |
152 | if (!Objects.equals(deviceProfile.getFirmwareId(), oldDeviceProfile.getFirmwareId())) { | 153 | if (!Objects.equals(deviceProfile.getFirmwareId(), oldDeviceProfile.getFirmwareId())) { |
153 | isFirmwareChanged = true; | 154 | isFirmwareChanged = true; |
154 | } | 155 | } |
156 | + if (!Objects.equals(deviceProfile.getSoftwareId(), oldDeviceProfile.getSoftwareId())) { | ||
157 | + isSoftwareChanged = true; | ||
158 | + } | ||
155 | } | 159 | } |
156 | 160 | ||
157 | DeviceProfile savedDeviceProfile = checkNotNull(deviceProfileService.saveDeviceProfile(deviceProfile)); | 161 | DeviceProfile savedDeviceProfile = checkNotNull(deviceProfileService.saveDeviceProfile(deviceProfile)); |
@@ -164,9 +168,8 @@ public class DeviceProfileController extends BaseController { | @@ -164,9 +168,8 @@ public class DeviceProfileController extends BaseController { | ||
164 | null, | 168 | null, |
165 | created ? ActionType.ADDED : ActionType.UPDATED, null); | 169 | created ? ActionType.ADDED : ActionType.UPDATED, null); |
166 | 170 | ||
167 | - if (isFirmwareChanged) { | ||
168 | - firmwareStateService.update(savedDeviceProfile); | ||
169 | - } | 171 | + firmwareStateService.update(savedDeviceProfile, isFirmwareChanged, isSoftwareChanged); |
172 | + | ||
170 | sendEntityNotificationMsg(getTenantId(), savedDeviceProfile.getId(), | 173 | sendEntityNotificationMsg(getTenantId(), savedDeviceProfile.getId(), |
171 | deviceProfile.getId() == null ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED); | 174 | deviceProfile.getId() == null ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED); |
172 | return savedDeviceProfile; | 175 | return savedDeviceProfile; |
@@ -35,6 +35,8 @@ import org.thingsboard.server.common.data.Firmware; | @@ -35,6 +35,8 @@ import org.thingsboard.server.common.data.Firmware; | ||
35 | import org.thingsboard.server.common.data.FirmwareInfo; | 35 | import org.thingsboard.server.common.data.FirmwareInfo; |
36 | import org.thingsboard.server.common.data.audit.ActionType; | 36 | import org.thingsboard.server.common.data.audit.ActionType; |
37 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 37 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
38 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
39 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | ||
38 | import org.thingsboard.server.common.data.id.FirmwareId; | 40 | import org.thingsboard.server.common.data.id.FirmwareId; |
39 | import org.thingsboard.server.common.data.page.PageData; | 41 | import org.thingsboard.server.common.data.page.PageData; |
40 | import org.thingsboard.server.common.data.page.PageLink; | 42 | import org.thingsboard.server.common.data.page.PageLink; |
@@ -133,6 +135,8 @@ public class FirmwareController extends BaseController { | @@ -133,6 +135,8 @@ public class FirmwareController extends BaseController { | ||
133 | Firmware firmware = new Firmware(firmwareId); | 135 | Firmware firmware = new Firmware(firmwareId); |
134 | firmware.setCreatedTime(info.getCreatedTime()); | 136 | firmware.setCreatedTime(info.getCreatedTime()); |
135 | firmware.setTenantId(getTenantId()); | 137 | firmware.setTenantId(getTenantId()); |
138 | + firmware.setDeviceProfileId(info.getDeviceProfileId()); | ||
139 | + firmware.setType(info.getType()); | ||
136 | firmware.setTitle(info.getTitle()); | 140 | firmware.setTitle(info.getTitle()); |
137 | firmware.setVersion(info.getVersion()); | 141 | firmware.setVersion(info.getVersion()); |
138 | firmware.setAdditionalInfo(info.getAdditionalInfo()); | 142 | firmware.setAdditionalInfo(info.getAdditionalInfo()); |
@@ -175,17 +179,22 @@ public class FirmwareController extends BaseController { | @@ -175,17 +179,22 @@ public class FirmwareController extends BaseController { | ||
175 | } | 179 | } |
176 | 180 | ||
177 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 181 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
178 | - @RequestMapping(value = "/firmwares/{hasData}", method = RequestMethod.GET) | 182 | + @RequestMapping(value = "/firmwares/{deviceProfileId}/{type}/{hasData}", method = RequestMethod.GET) |
179 | @ResponseBody | 183 | @ResponseBody |
180 | - public PageData<FirmwareInfo> getFirmwares(@PathVariable("hasData") boolean hasData, | 184 | + public PageData<FirmwareInfo> getFirmwares(@PathVariable("deviceProfileId") String strDeviceProfileId, |
185 | + @PathVariable("type") String strType, | ||
186 | + @PathVariable("hasData") boolean hasData, | ||
181 | @RequestParam int pageSize, | 187 | @RequestParam int pageSize, |
182 | @RequestParam int page, | 188 | @RequestParam int page, |
183 | @RequestParam(required = false) String textSearch, | 189 | @RequestParam(required = false) String textSearch, |
184 | @RequestParam(required = false) String sortProperty, | 190 | @RequestParam(required = false) String sortProperty, |
185 | @RequestParam(required = false) String sortOrder) throws ThingsboardException { | 191 | @RequestParam(required = false) String sortOrder) throws ThingsboardException { |
192 | + checkParameter("deviceProfileId", strDeviceProfileId); | ||
193 | + checkParameter("type", strType); | ||
186 | try { | 194 | try { |
187 | PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | 195 | PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
188 | - return checkNotNull(firmwareService.findTenantFirmwaresByTenantIdAndHasData(getTenantId(), hasData, pageLink)); | 196 | + return checkNotNull(firmwareService.findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(getTenantId(), |
197 | + new DeviceProfileId(toUUID(strDeviceProfileId)), FirmwareType.valueOf(strType), hasData, pageLink)); | ||
189 | } catch (Exception e) { | 198 | } catch (Exception e) { |
190 | throw handleException(e); | 199 | throw handleException(e); |
191 | } | 200 | } |
@@ -47,9 +47,9 @@ public class Lwm2mController extends BaseController { | @@ -47,9 +47,9 @@ public class Lwm2mController extends BaseController { | ||
47 | @RequestMapping(value = "/lwm2m/deviceProfile/bootstrap/{securityMode}/{bootstrapServerIs}", method = RequestMethod.GET) | 47 | @RequestMapping(value = "/lwm2m/deviceProfile/bootstrap/{securityMode}/{bootstrapServerIs}", method = RequestMethod.GET) |
48 | @ResponseBody | 48 | @ResponseBody |
49 | public ServerSecurityConfig getLwm2mBootstrapSecurityInfo(@PathVariable("securityMode") String securityMode, | 49 | public ServerSecurityConfig getLwm2mBootstrapSecurityInfo(@PathVariable("securityMode") String securityMode, |
50 | - @PathVariable("bootstrapServerIs") boolean bootstrapServerIs) throws ThingsboardException { | 50 | + @PathVariable("bootstrapServerIs") boolean bootstrapServer) throws ThingsboardException { |
51 | try { | 51 | try { |
52 | - return lwM2MModelsRepository.getBootstrapSecurityInfo(securityMode, bootstrapServerIs); | 52 | + return lwM2MServerSecurityInfoRepository.getServerSecurityInfo(securityMode, bootstrapServer); |
53 | } catch (Exception e) { | 53 | } catch (Exception e) { |
54 | throw handleException(e); | 54 | throw handleException(e); |
55 | } | 55 | } |
@@ -32,6 +32,7 @@ import org.springframework.web.bind.annotation.RequestParam; | @@ -32,6 +32,7 @@ import org.springframework.web.bind.annotation.RequestParam; | ||
32 | import org.springframework.web.bind.annotation.ResponseBody; | 32 | import org.springframework.web.bind.annotation.ResponseBody; |
33 | import org.springframework.web.bind.annotation.ResponseStatus; | 33 | import org.springframework.web.bind.annotation.ResponseStatus; |
34 | import org.springframework.web.bind.annotation.RestController; | 34 | import org.springframework.web.bind.annotation.RestController; |
35 | +import org.thingsboard.common.util.JacksonUtil; | ||
35 | import org.thingsboard.rule.engine.api.MailService; | 36 | import org.thingsboard.rule.engine.api.MailService; |
36 | import org.thingsboard.server.common.data.EntityType; | 37 | import org.thingsboard.server.common.data.EntityType; |
37 | import org.thingsboard.server.common.data.User; | 38 | import org.thingsboard.server.common.data.User; |
@@ -89,13 +90,14 @@ public class UserController extends BaseController { | @@ -89,13 +90,14 @@ public class UserController extends BaseController { | ||
89 | try { | 90 | try { |
90 | UserId userId = new UserId(toUUID(strUserId)); | 91 | UserId userId = new UserId(toUUID(strUserId)); |
91 | User user = checkUserId(userId, Operation.READ); | 92 | User user = checkUserId(userId, Operation.READ); |
92 | - if(!user.getAdditionalInfo().isNull()) { | ||
93 | - processDashboardIdFromAdditionalInfo((ObjectNode) user.getAdditionalInfo(), DEFAULT_DASHBOARD); | ||
94 | - processDashboardIdFromAdditionalInfo((ObjectNode) user.getAdditionalInfo(), HOME_DASHBOARD); | ||
95 | - } | ||
96 | - UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId()); | ||
97 | - if(userCredentials.isEnabled()) { | ||
98 | - addUserCredentialsEnabled((ObjectNode) user.getAdditionalInfo()); | 93 | + if(user.getAdditionalInfo().isObject()) { |
94 | + ObjectNode additionalInfo = (ObjectNode) user.getAdditionalInfo(); | ||
95 | + processDashboardIdFromAdditionalInfo(additionalInfo, DEFAULT_DASHBOARD); | ||
96 | + processDashboardIdFromAdditionalInfo(additionalInfo, HOME_DASHBOARD); | ||
97 | + UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId()); | ||
98 | + if(userCredentials.isEnabled() && !additionalInfo.has("userCredentialsEnabled")) { | ||
99 | + additionalInfo.put("userCredentialsEnabled", true); | ||
100 | + } | ||
99 | } | 101 | } |
100 | return user; | 102 | return user; |
101 | } catch (Exception e) { | 103 | } catch (Exception e) { |
@@ -103,14 +105,6 @@ public class UserController extends BaseController { | @@ -103,14 +105,6 @@ public class UserController extends BaseController { | ||
103 | } | 105 | } |
104 | } | 106 | } |
105 | 107 | ||
106 | - private void addUserCredentialsEnabled(ObjectNode additionalInfo) { | ||
107 | - if(!additionalInfo.isNull()) { | ||
108 | - if(!additionalInfo.has("userCredentialsEnabled")) { | ||
109 | - additionalInfo.put("userCredentialsEnabled", true); | ||
110 | - } | ||
111 | - } | ||
112 | - } | ||
113 | - | ||
114 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") | 108 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
115 | @RequestMapping(value = "/user/tokenAccessEnabled", method = RequestMethod.GET) | 109 | @RequestMapping(value = "/user/tokenAccessEnabled", method = RequestMethod.GET) |
116 | @ResponseBody | 110 | @ResponseBody |
@@ -19,13 +19,17 @@ import com.google.common.util.concurrent.FutureCallback; | @@ -19,13 +19,17 @@ import com.google.common.util.concurrent.FutureCallback; | ||
19 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
20 | import org.springframework.stereotype.Service; | 20 | import org.springframework.stereotype.Service; |
21 | import org.thingsboard.rule.engine.api.RuleEngineTelemetryService; | 21 | import org.thingsboard.rule.engine.api.RuleEngineTelemetryService; |
22 | +import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; | ||
22 | import org.thingsboard.server.common.data.DataConstants; | 23 | import org.thingsboard.server.common.data.DataConstants; |
23 | import org.thingsboard.server.common.data.Device; | 24 | import org.thingsboard.server.common.data.Device; |
24 | import org.thingsboard.server.common.data.DeviceProfile; | 25 | import org.thingsboard.server.common.data.DeviceProfile; |
25 | 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; | ||
26 | import org.thingsboard.server.common.data.id.DeviceId; | 29 | import org.thingsboard.server.common.data.id.DeviceId; |
27 | import org.thingsboard.server.common.data.id.FirmwareId; | 30 | import org.thingsboard.server.common.data.id.FirmwareId; |
28 | import org.thingsboard.server.common.data.id.TenantId; | 31 | import org.thingsboard.server.common.data.id.TenantId; |
32 | +import org.thingsboard.server.common.data.kv.AttributeKey; | ||
29 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 33 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
30 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; | 34 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
31 | import org.thingsboard.server.common.data.kv.BasicTsKvEntry; | 35 | import org.thingsboard.server.common.data.kv.BasicTsKvEntry; |
@@ -43,37 +47,49 @@ import org.thingsboard.server.queue.TbQueueProducer; | @@ -43,37 +47,49 @@ import org.thingsboard.server.queue.TbQueueProducer; | ||
43 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; | 47 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
44 | import org.thingsboard.server.queue.provider.TbCoreQueueFactory; | 48 | import org.thingsboard.server.queue.provider.TbCoreQueueFactory; |
45 | import org.thingsboard.server.queue.util.TbCoreComponent; | 49 | import org.thingsboard.server.queue.util.TbCoreComponent; |
50 | +import org.thingsboard.server.service.queue.TbClusterService; | ||
46 | 51 | ||
47 | import javax.annotation.Nullable; | 52 | import javax.annotation.Nullable; |
48 | import java.util.ArrayList; | 53 | import java.util.ArrayList; |
49 | -import java.util.Arrays; | ||
50 | import java.util.Collections; | 54 | import java.util.Collections; |
55 | +import java.util.HashSet; | ||
51 | import java.util.List; | 56 | import java.util.List; |
57 | +import java.util.Set; | ||
52 | import java.util.UUID; | 58 | import java.util.UUID; |
53 | import java.util.function.Consumer; | 59 | import java.util.function.Consumer; |
54 | - | ||
55 | -import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_CHECKSUM; | ||
56 | -import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_CHECKSUM_ALGORITHM; | ||
57 | -import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_SIZE; | ||
58 | -import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_TITLE; | ||
59 | -import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_VERSION; | 60 | +import java.util.function.Function; |
61 | + | ||
62 | +import static org.thingsboard.server.common.data.firmware.FirmwareKey.CHECKSUM; | ||
63 | +import static org.thingsboard.server.common.data.firmware.FirmwareKey.CHECKSUM_ALGORITHM; | ||
64 | +import static org.thingsboard.server.common.data.firmware.FirmwareKey.SIZE; | ||
65 | +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.TS; | ||
68 | +import static org.thingsboard.server.common.data.firmware.FirmwareKey.VERSION; | ||
69 | +import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getAttributeKey; | ||
70 | +import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getTargetTelemetryKey; | ||
71 | +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; | ||
60 | 74 | ||
61 | @Slf4j | 75 | @Slf4j |
62 | @Service | 76 | @Service |
63 | @TbCoreComponent | 77 | @TbCoreComponent |
64 | public class DefaultFirmwareStateService implements FirmwareStateService { | 78 | public class DefaultFirmwareStateService implements FirmwareStateService { |
65 | 79 | ||
80 | + private final TbClusterService tbClusterService; | ||
66 | private final FirmwareService firmwareService; | 81 | private final FirmwareService firmwareService; |
67 | private final DeviceService deviceService; | 82 | private final DeviceService deviceService; |
68 | private final DeviceProfileService deviceProfileService; | 83 | private final DeviceProfileService deviceProfileService; |
69 | private final RuleEngineTelemetryService telemetryService; | 84 | private final RuleEngineTelemetryService telemetryService; |
70 | private final TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> fwStateMsgProducer; | 85 | private final TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> fwStateMsgProducer; |
71 | 86 | ||
72 | - public DefaultFirmwareStateService(FirmwareService firmwareService, | 87 | + public DefaultFirmwareStateService(TbClusterService tbClusterService, FirmwareService firmwareService, |
73 | DeviceService deviceService, | 88 | DeviceService deviceService, |
74 | DeviceProfileService deviceProfileService, | 89 | DeviceProfileService deviceProfileService, |
75 | RuleEngineTelemetryService telemetryService, | 90 | RuleEngineTelemetryService telemetryService, |
76 | TbCoreQueueFactory coreQueueFactory) { | 91 | TbCoreQueueFactory coreQueueFactory) { |
92 | + this.tbClusterService = tbClusterService; | ||
77 | this.firmwareService = firmwareService; | 93 | this.firmwareService = firmwareService; |
78 | this.deviceService = deviceService; | 94 | this.deviceService = deviceService; |
79 | this.deviceProfileService = deviceProfileService; | 95 | this.deviceProfileService = deviceProfileService; |
@@ -83,6 +99,11 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | @@ -83,6 +99,11 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | ||
83 | 99 | ||
84 | @Override | 100 | @Override |
85 | public void update(Device device, Device oldDevice) { | 101 | public void update(Device device, Device oldDevice) { |
102 | + updateFirmware(device, oldDevice); | ||
103 | + updateSoftware(device, oldDevice); | ||
104 | + } | ||
105 | + | ||
106 | + private void updateFirmware(Device device, Device oldDevice) { | ||
86 | FirmwareId newFirmwareId = device.getFirmwareId(); | 107 | FirmwareId newFirmwareId = device.getFirmwareId(); |
87 | if (newFirmwareId == null) { | 108 | if (newFirmwareId == null) { |
88 | DeviceProfile newDeviceProfile = deviceProfileService.findDeviceProfileById(device.getTenantId(), device.getDeviceProfileId()); | 109 | DeviceProfile newDeviceProfile = deviceProfileService.findDeviceProfileById(device.getTenantId(), device.getDeviceProfileId()); |
@@ -97,35 +118,84 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | @@ -97,35 +118,84 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | ||
97 | } | 118 | } |
98 | if (!newFirmwareId.equals(oldFirmwareId)) { | 119 | if (!newFirmwareId.equals(oldFirmwareId)) { |
99 | // Device was updated and new firmware is different from previous firmware. | 120 | // Device was updated and new firmware is different from previous firmware. |
100 | - send(device.getTenantId(), device.getId(), newFirmwareId, System.currentTimeMillis()); | 121 | + send(device.getTenantId(), device.getId(), newFirmwareId, System.currentTimeMillis(), FIRMWARE); |
101 | } | 122 | } |
102 | } else { | 123 | } else { |
103 | // Device was updated and new firmware is not set. | 124 | // Device was updated and new firmware is not set. |
104 | - remove(device); | 125 | + remove(device, FIRMWARE); |
105 | } | 126 | } |
106 | } else if (newFirmwareId != null) { | 127 | } else if (newFirmwareId != null) { |
107 | // Device was created and firmware is defined. | 128 | // Device was created and firmware is defined. |
108 | - send(device.getTenantId(), device.getId(), newFirmwareId, System.currentTimeMillis()); | 129 | + send(device.getTenantId(), device.getId(), newFirmwareId, System.currentTimeMillis(), FIRMWARE); |
130 | + } | ||
131 | + } | ||
132 | + | ||
133 | + private void updateSoftware(Device device, Device oldDevice) { | ||
134 | + FirmwareId newSoftwareId = device.getSoftwareId(); | ||
135 | + if (newSoftwareId == null) { | ||
136 | + DeviceProfile newDeviceProfile = deviceProfileService.findDeviceProfileById(device.getTenantId(), device.getDeviceProfileId()); | ||
137 | + newSoftwareId = newDeviceProfile.getSoftwareId(); | ||
138 | + } | ||
139 | + if (oldDevice != null) { | ||
140 | + if (newSoftwareId != null) { | ||
141 | + FirmwareId oldSoftwareId = oldDevice.getSoftwareId(); | ||
142 | + if (oldSoftwareId == null) { | ||
143 | + DeviceProfile oldDeviceProfile = deviceProfileService.findDeviceProfileById(oldDevice.getTenantId(), oldDevice.getDeviceProfileId()); | ||
144 | + oldSoftwareId = oldDeviceProfile.getSoftwareId(); | ||
145 | + } | ||
146 | + if (!newSoftwareId.equals(oldSoftwareId)) { | ||
147 | + // Device was updated and new firmware is different from previous firmware. | ||
148 | + send(device.getTenantId(), device.getId(), newSoftwareId, System.currentTimeMillis(), SOFTWARE); | ||
149 | + } | ||
150 | + } else { | ||
151 | + // Device was updated and new firmware is not set. | ||
152 | + remove(device, SOFTWARE); | ||
153 | + } | ||
154 | + } else if (newSoftwareId != null) { | ||
155 | + // Device was created and firmware is defined. | ||
156 | + send(device.getTenantId(), device.getId(), newSoftwareId, System.currentTimeMillis(), SOFTWARE); | ||
109 | } | 157 | } |
110 | } | 158 | } |
111 | 159 | ||
112 | @Override | 160 | @Override |
113 | - public void update(DeviceProfile deviceProfile) { | 161 | + public void update(DeviceProfile deviceProfile, boolean isFirmwareChanged, boolean isSoftwareChanged) { |
114 | TenantId tenantId = deviceProfile.getTenantId(); | 162 | TenantId tenantId = deviceProfile.getTenantId(); |
115 | 163 | ||
164 | + if (isFirmwareChanged) { | ||
165 | + update(tenantId, deviceProfile, FIRMWARE); | ||
166 | + } | ||
167 | + if (isSoftwareChanged) { | ||
168 | + update(tenantId, deviceProfile, SOFTWARE); | ||
169 | + } | ||
170 | + } | ||
171 | + | ||
172 | + private void update(TenantId tenantId, DeviceProfile deviceProfile, FirmwareType firmwareType) { | ||
173 | + Function<PageLink, PageData<Device>> getDevicesFunction; | ||
116 | Consumer<Device> updateConsumer; | 174 | Consumer<Device> updateConsumer; |
175 | + | ||
176 | + switch (firmwareType) { | ||
177 | + case FIRMWARE: | ||
178 | + getDevicesFunction = pl -> deviceService.findDevicesByTenantIdAndTypeAndEmptyFirmware(tenantId, deviceProfile.getName(), pl); | ||
179 | + break; | ||
180 | + case SOFTWARE: | ||
181 | + getDevicesFunction = pl -> deviceService.findDevicesByTenantIdAndTypeAndEmptySoftware(tenantId, deviceProfile.getName(), pl); | ||
182 | + break; | ||
183 | + default: | ||
184 | + log.warn("Unsupported firmware type: [{}]", firmwareType); | ||
185 | + return; | ||
186 | + } | ||
187 | + | ||
117 | if (deviceProfile.getFirmwareId() != null) { | 188 | if (deviceProfile.getFirmwareId() != null) { |
118 | long ts = System.currentTimeMillis(); | 189 | long ts = System.currentTimeMillis(); |
119 | - updateConsumer = d -> send(d.getTenantId(), d.getId(), deviceProfile.getFirmwareId(), ts); | 190 | + updateConsumer = d -> send(d.getTenantId(), d.getId(), deviceProfile.getFirmwareId(), ts, firmwareType); |
120 | } else { | 191 | } else { |
121 | - updateConsumer = this::remove; | 192 | + updateConsumer = d -> remove(d, firmwareType); |
122 | } | 193 | } |
123 | 194 | ||
124 | PageLink pageLink = new PageLink(100); | 195 | PageLink pageLink = new PageLink(100); |
125 | PageData<Device> pageData; | 196 | PageData<Device> pageData; |
126 | do { | 197 | do { |
127 | - pageData = deviceService.findDevicesByTenantIdAndTypeAndEmptyFirmware(tenantId, deviceProfile.getName(), pageLink); | ||
128 | - | 198 | + pageData = getDevicesFunction.apply(pageLink); |
129 | pageData.getData().forEach(updateConsumer); | 199 | pageData.getData().forEach(updateConsumer); |
130 | 200 | ||
131 | if (pageData.hasNext()) { | 201 | if (pageData.hasNext()) { |
@@ -140,16 +210,17 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | @@ -140,16 +210,17 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | ||
140 | FirmwareId targetFirmwareId = new FirmwareId(new UUID(msg.getFirmwareIdMSB(), msg.getFirmwareIdLSB())); | 210 | FirmwareId targetFirmwareId = new FirmwareId(new UUID(msg.getFirmwareIdMSB(), msg.getFirmwareIdLSB())); |
141 | DeviceId deviceId = new DeviceId(new UUID(msg.getDeviceIdMSB(), msg.getDeviceIdLSB())); | 211 | DeviceId deviceId = new DeviceId(new UUID(msg.getDeviceIdMSB(), msg.getDeviceIdLSB())); |
142 | TenantId tenantId = new TenantId(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB())); | 212 | TenantId tenantId = new TenantId(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB())); |
213 | + FirmwareType firmwareType = FirmwareType.valueOf(msg.getType()); | ||
143 | long ts = msg.getTs(); | 214 | long ts = msg.getTs(); |
144 | 215 | ||
145 | Device device = deviceService.findDeviceById(tenantId, deviceId); | 216 | Device device = deviceService.findDeviceById(tenantId, deviceId); |
146 | if (device == null) { | 217 | if (device == null) { |
147 | log.warn("[{}] [{}] Device was removed during firmware update msg was queued!", tenantId, deviceId); | 218 | log.warn("[{}] [{}] Device was removed during firmware update msg was queued!", tenantId, deviceId); |
148 | } else { | 219 | } else { |
149 | - FirmwareId currentFirmwareId = device.getFirmwareId(); | ||
150 | - | 220 | + FirmwareId currentFirmwareId = FirmwareUtil.getFirmwareId(device, firmwareType); |
151 | if (currentFirmwareId == null) { | 221 | if (currentFirmwareId == null) { |
152 | - currentFirmwareId = deviceProfileService.findDeviceProfileById(tenantId, device.getDeviceProfileId()).getFirmwareId(); | 222 | + DeviceProfile deviceProfile = deviceProfileService.findDeviceProfileById(tenantId, device.getDeviceProfileId()); |
223 | + currentFirmwareId = FirmwareUtil.getFirmwareId(deviceProfile, firmwareType); | ||
153 | } | 224 | } |
154 | 225 | ||
155 | if (targetFirmwareId.equals(currentFirmwareId)) { | 226 | if (targetFirmwareId.equals(currentFirmwareId)) { |
@@ -162,7 +233,7 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | @@ -162,7 +233,7 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | ||
162 | return isSuccess; | 233 | return isSuccess; |
163 | } | 234 | } |
164 | 235 | ||
165 | - private void send(TenantId tenantId, DeviceId deviceId, FirmwareId firmwareId, long ts) { | 236 | + private void send(TenantId tenantId, DeviceId deviceId, FirmwareId firmwareId, long ts, FirmwareType firmwareType) { |
166 | ToFirmwareStateServiceMsg msg = ToFirmwareStateServiceMsg.newBuilder() | 237 | ToFirmwareStateServiceMsg msg = ToFirmwareStateServiceMsg.newBuilder() |
167 | .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) | 238 | .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) |
168 | .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) | 239 | .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) |
@@ -170,6 +241,7 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | @@ -170,6 +241,7 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | ||
170 | .setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()) | 241 | .setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()) |
171 | .setFirmwareIdMSB(firmwareId.getId().getMostSignificantBits()) | 242 | .setFirmwareIdMSB(firmwareId.getId().getMostSignificantBits()) |
172 | .setFirmwareIdLSB(firmwareId.getId().getLeastSignificantBits()) | 243 | .setFirmwareIdLSB(firmwareId.getId().getLeastSignificantBits()) |
244 | + .setType(firmwareType.name()) | ||
173 | .setTs(ts) | 245 | .setTs(ts) |
174 | .build(); | 246 | .build(); |
175 | 247 | ||
@@ -183,10 +255,10 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | @@ -183,10 +255,10 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | ||
183 | fwStateMsgProducer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), null); | 255 | fwStateMsgProducer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), null); |
184 | 256 | ||
185 | List<TsKvEntry> telemetry = new ArrayList<>(); | 257 | List<TsKvEntry> telemetry = new ArrayList<>(); |
186 | - telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.TARGET_FIRMWARE_TITLE, firmware.getTitle()))); | ||
187 | - telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.TARGET_FIRMWARE_VERSION, firmware.getVersion()))); | ||
188 | - telemetry.add(new BasicTsKvEntry(ts, new LongDataEntry(DataConstants.TARGET_FIRMWARE_TS, ts))); | ||
189 | - telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_STATE, FirmwareUpdateStatus.QUEUED.name()))); | 258 | + telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(getTargetTelemetryKey(firmware.getType(), TITLE), firmware.getTitle()))); |
259 | + telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(getTargetTelemetryKey(firmware.getType(), VERSION), firmware.getVersion()))); | ||
260 | + telemetry.add(new BasicTsKvEntry(ts, new LongDataEntry(getTargetTelemetryKey(firmware.getType(), TS), ts))); | ||
261 | + telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(getTelemetryKey(firmware.getType(), STATE), FirmwareUpdateStatus.QUEUED.name()))); | ||
190 | 262 | ||
191 | telemetryService.saveAndNotify(tenantId, deviceId, telemetry, new FutureCallback<>() { | 263 | telemetryService.saveAndNotify(tenantId, deviceId, telemetry, new FutureCallback<>() { |
192 | @Override | 264 | @Override |
@@ -206,7 +278,7 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | @@ -206,7 +278,7 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | ||
206 | TenantId tenantId = device.getTenantId(); | 278 | TenantId tenantId = device.getTenantId(); |
207 | DeviceId deviceId = device.getId(); | 279 | DeviceId deviceId = device.getId(); |
208 | 280 | ||
209 | - BasicTsKvEntry status = new BasicTsKvEntry(System.currentTimeMillis(), new StringDataEntry(DataConstants.FIRMWARE_STATE, FirmwareUpdateStatus.INITIATED.name())); | 281 | + BasicTsKvEntry status = new BasicTsKvEntry(System.currentTimeMillis(), new StringDataEntry(getTelemetryKey(firmware.getType(), STATE), FirmwareUpdateStatus.INITIATED.name())); |
210 | 282 | ||
211 | telemetryService.saveAndNotify(tenantId, deviceId, Collections.singletonList(status), new FutureCallback<>() { | 283 | telemetryService.saveAndNotify(tenantId, deviceId, Collections.singletonList(status), new FutureCallback<>() { |
212 | @Override | 284 | @Override |
@@ -221,13 +293,12 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | @@ -221,13 +293,12 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | ||
221 | }); | 293 | }); |
222 | 294 | ||
223 | List<AttributeKvEntry> attributes = new ArrayList<>(); | 295 | List<AttributeKvEntry> attributes = new ArrayList<>(); |
296 | + attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(getAttributeKey(firmware.getType(), TITLE), firmware.getTitle()))); | ||
297 | + attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(getAttributeKey(firmware.getType(), VERSION), firmware.getVersion()))); | ||
298 | + attributes.add(new BaseAttributeKvEntry(ts, new LongDataEntry(getAttributeKey(firmware.getType(), SIZE), firmware.getDataSize()))); | ||
299 | + attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(getAttributeKey(firmware.getType(), CHECKSUM_ALGORITHM), firmware.getChecksumAlgorithm()))); | ||
300 | + attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(getAttributeKey(firmware.getType(), CHECKSUM), firmware.getChecksum()))); | ||
224 | 301 | ||
225 | - attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_TITLE, firmware.getTitle()))); | ||
226 | - attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_VERSION, firmware.getVersion()))); | ||
227 | - | ||
228 | - attributes.add(new BaseAttributeKvEntry(ts, new LongDataEntry(FIRMWARE_SIZE, firmware.getDataSize()))); | ||
229 | - attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_CHECKSUM_ALGORITHM, firmware.getChecksumAlgorithm()))); | ||
230 | - attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_CHECKSUM, firmware.getChecksum()))); | ||
231 | telemetryService.saveAndNotify(tenantId, deviceId, DataConstants.SHARED_SCOPE, attributes, new FutureCallback<>() { | 302 | telemetryService.saveAndNotify(tenantId, deviceId, DataConstants.SHARED_SCOPE, attributes, new FutureCallback<>() { |
232 | @Override | 303 | @Override |
233 | public void onSuccess(@Nullable Void tmp) { | 304 | public void onSuccess(@Nullable Void tmp) { |
@@ -241,13 +312,15 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | @@ -241,13 +312,15 @@ public class DefaultFirmwareStateService implements FirmwareStateService { | ||
241 | }); | 312 | }); |
242 | } | 313 | } |
243 | 314 | ||
244 | - private void remove(Device device) { | ||
245 | - telemetryService.deleteAndNotify(device.getTenantId(), device.getId(), DataConstants.SHARED_SCOPE, | ||
246 | - Arrays.asList(FIRMWARE_TITLE, FIRMWARE_VERSION, FIRMWARE_SIZE, FIRMWARE_CHECKSUM_ALGORITHM, FIRMWARE_CHECKSUM), | 315 | + private void remove(Device device, FirmwareType firmwareType) { |
316 | + telemetryService.deleteAndNotify(device.getTenantId(), device.getId(), DataConstants.SHARED_SCOPE, FirmwareUtil.getAttributeKeys(firmwareType), | ||
247 | new FutureCallback<>() { | 317 | new FutureCallback<>() { |
248 | @Override | 318 | @Override |
249 | public void onSuccess(@Nullable Void tmp) { | 319 | public void onSuccess(@Nullable Void tmp) { |
250 | log.trace("[{}] Success remove target firmware attributes!", device.getId()); | 320 | log.trace("[{}] Success remove target firmware attributes!", device.getId()); |
321 | + Set<AttributeKey> keysToNotify = new HashSet<>(); | ||
322 | + FirmwareUtil.ALL_FW_ATTRIBUTE_KEYS.forEach(key -> keysToNotify.add(new AttributeKey(DataConstants.SHARED_SCOPE, key))); | ||
323 | + tbClusterService.pushMsgToCore(DeviceAttributesEventNotificationMsg.onDelete(device.getTenantId(), device.getId(), keysToNotify), null); | ||
251 | } | 324 | } |
252 | 325 | ||
253 | @Override | 326 | @Override |
@@ -23,7 +23,7 @@ public interface FirmwareStateService { | @@ -23,7 +23,7 @@ public interface FirmwareStateService { | ||
23 | 23 | ||
24 | void update(Device device, Device oldDevice); | 24 | void update(Device device, Device oldDevice); |
25 | 25 | ||
26 | - void update(DeviceProfile deviceProfile); | 26 | + void update(DeviceProfile deviceProfile, boolean isFirmwareChanged, boolean isSoftwareChanged); |
27 | 27 | ||
28 | boolean process(ToFirmwareStateServiceMsg msg); | 28 | boolean process(ToFirmwareStateServiceMsg msg); |
29 | 29 |
application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MServerSecurityInfoRepository.java
renamed from
application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java
@@ -16,14 +16,15 @@ | @@ -16,14 +16,15 @@ | ||
16 | package org.thingsboard.server.service.lwm2m; | 16 | package org.thingsboard.server.service.lwm2m; |
17 | 17 | ||
18 | 18 | ||
19 | +import lombok.RequiredArgsConstructor; | ||
19 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
20 | import org.eclipse.leshan.core.util.Hex; | 21 | import org.eclipse.leshan.core.util.Hex; |
21 | -import org.springframework.beans.factory.annotation.Autowired; | ||
22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | 22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
23 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
24 | import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig; | 24 | import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig; |
25 | -import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstrap; | ||
26 | -import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer; | 25 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MSecureServerConfig; |
26 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportBootstrapConfig; | ||
27 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; | ||
27 | import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; | 28 | import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; |
28 | 29 | ||
29 | import java.math.BigInteger; | 30 | import java.math.BigInteger; |
@@ -42,96 +43,59 @@ import java.security.spec.KeySpec; | @@ -42,96 +43,59 @@ import java.security.spec.KeySpec; | ||
42 | 43 | ||
43 | @Slf4j | 44 | @Slf4j |
44 | @Service | 45 | @Service |
46 | +@RequiredArgsConstructor | ||
45 | @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core'") | 47 | @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core'") |
46 | -public class LwM2MModelsRepository { | 48 | +public class LwM2MServerSecurityInfoRepository { |
47 | 49 | ||
48 | - private static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; | ||
49 | - | ||
50 | - @Autowired | ||
51 | - LwM2MTransportConfigServer contextServer; | ||
52 | - | ||
53 | - | ||
54 | - @Autowired | ||
55 | - LwM2MTransportConfigBootstrap contextBootStrap; | 50 | + private final LwM2MTransportServerConfig serverConfig; |
51 | + private final LwM2MTransportBootstrapConfig bootstrapConfig; | ||
56 | 52 | ||
57 | /** | 53 | /** |
58 | * @param securityMode | 54 | * @param securityMode |
59 | - * @param bootstrapServerIs | 55 | + * @param bootstrapServer |
60 | * @return ServerSecurityConfig more value is default: Important - port, host, publicKey | 56 | * @return ServerSecurityConfig more value is default: Important - port, host, publicKey |
61 | */ | 57 | */ |
62 | - public ServerSecurityConfig getBootstrapSecurityInfo(String securityMode, boolean bootstrapServerIs) { | 58 | + public ServerSecurityConfig getServerSecurityInfo(String securityMode, boolean bootstrapServer) { |
63 | LwM2MSecurityMode lwM2MSecurityMode = LwM2MSecurityMode.fromSecurityMode(securityMode.toLowerCase()); | 59 | LwM2MSecurityMode lwM2MSecurityMode = LwM2MSecurityMode.fromSecurityMode(securityMode.toLowerCase()); |
64 | - return getBootstrapServer(bootstrapServerIs, lwM2MSecurityMode); | 60 | + ServerSecurityConfig result = getServerSecurityConfig(bootstrapServer ? bootstrapConfig : serverConfig, lwM2MSecurityMode); |
61 | + result.setBootstrapServerIs(bootstrapServer); | ||
62 | + return result; | ||
65 | } | 63 | } |
66 | 64 | ||
67 | - /** | ||
68 | - * @param bootstrapServerIs | ||
69 | - * @param mode | ||
70 | - * @return ServerSecurityConfig more value is default: Important - port, host, publicKey | ||
71 | - */ | ||
72 | - private ServerSecurityConfig getBootstrapServer(boolean bootstrapServerIs, LwM2MSecurityMode mode) { | 65 | + private ServerSecurityConfig getServerSecurityConfig(LwM2MSecureServerConfig serverConfig, LwM2MSecurityMode mode) { |
73 | ServerSecurityConfig bsServ = new ServerSecurityConfig(); | 66 | ServerSecurityConfig bsServ = new ServerSecurityConfig(); |
74 | - bsServ.setBootstrapServerIs(bootstrapServerIs); | ||
75 | - if (bootstrapServerIs) { | ||
76 | - bsServ.setServerId(contextBootStrap.getBootstrapServerId()); | ||
77 | - switch (mode) { | ||
78 | - case NO_SEC: | ||
79 | - bsServ.setHost(contextBootStrap.getBootstrapHost()); | ||
80 | - bsServ.setPort(contextBootStrap.getBootstrapPortNoSec()); | ||
81 | - bsServ.setServerPublicKey(""); | ||
82 | - break; | ||
83 | - case PSK: | ||
84 | - bsServ.setHost(contextBootStrap.getBootstrapHostSecurity()); | ||
85 | - bsServ.setPort(contextBootStrap.getBootstrapPortSecurity()); | ||
86 | - bsServ.setServerPublicKey(""); | ||
87 | - break; | ||
88 | - case RPK: | ||
89 | - case X509: | ||
90 | - bsServ.setHost(contextBootStrap.getBootstrapHostSecurity()); | ||
91 | - bsServ.setPort(contextBootStrap.getBootstrapPortSecurity()); | ||
92 | - bsServ.setServerPublicKey(getPublicKey (contextBootStrap.getBootstrapAlias(), this.contextBootStrap.getBootstrapPublicX(), this.contextBootStrap.getBootstrapPublicY())); | ||
93 | - break; | ||
94 | - default: | ||
95 | - break; | ||
96 | - } | ||
97 | - } else { | ||
98 | - bsServ.setServerId(contextServer.getServerId()); | ||
99 | - switch (mode) { | ||
100 | - case NO_SEC: | ||
101 | - bsServ.setHost(contextServer.getServerHost()); | ||
102 | - bsServ.setPort(contextServer.getServerPortNoSec()); | ||
103 | - bsServ.setServerPublicKey(""); | ||
104 | - break; | ||
105 | - case PSK: | ||
106 | - bsServ.setHost(contextServer.getServerHostSecurity()); | ||
107 | - bsServ.setPort(contextServer.getServerPortSecurity()); | ||
108 | - bsServ.setServerPublicKey(""); | ||
109 | - break; | ||
110 | - case RPK: | ||
111 | - case X509: | ||
112 | - bsServ.setHost(contextServer.getServerHostSecurity()); | ||
113 | - bsServ.setPort(contextServer.getServerPortSecurity()); | ||
114 | - bsServ.setServerPublicKey(getPublicKey (contextServer.getServerAlias(), this.contextServer.getServerPublicX(), this.contextServer.getServerPublicY())); | ||
115 | - break; | ||
116 | - default: | ||
117 | - break; | ||
118 | - } | 67 | + bsServ.setServerId(serverConfig.getId()); |
68 | + switch (mode) { | ||
69 | + case NO_SEC: | ||
70 | + bsServ.setHost(serverConfig.getHost()); | ||
71 | + bsServ.setPort(serverConfig.getPort()); | ||
72 | + bsServ.setServerPublicKey(""); | ||
73 | + break; | ||
74 | + case PSK: | ||
75 | + bsServ.setHost(serverConfig.getSecureHost()); | ||
76 | + bsServ.setPort(serverConfig.getSecurePort()); | ||
77 | + bsServ.setServerPublicKey(""); | ||
78 | + break; | ||
79 | + case RPK: | ||
80 | + case X509: | ||
81 | + bsServ.setHost(serverConfig.getSecureHost()); | ||
82 | + bsServ.setPort(serverConfig.getSecurePort()); | ||
83 | + bsServ.setServerPublicKey(getPublicKey(serverConfig.getCertificateAlias(), this.serverConfig.getPublicX(), this.serverConfig.getPublicY())); | ||
84 | + break; | ||
85 | + default: | ||
86 | + break; | ||
119 | } | 87 | } |
120 | return bsServ; | 88 | return bsServ; |
121 | } | 89 | } |
122 | 90 | ||
123 | - private String getPublicKey (String alias, String publicServerX, String publicServerY) { | 91 | + private String getPublicKey(String alias, String publicServerX, String publicServerY) { |
124 | String publicKey = getServerPublicKeyX509(alias); | 92 | String publicKey = getServerPublicKeyX509(alias); |
125 | return publicKey != null ? publicKey : getRPKPublicKey(publicServerX, publicServerY); | 93 | return publicKey != null ? publicKey : getRPKPublicKey(publicServerX, publicServerY); |
126 | } | 94 | } |
127 | 95 | ||
128 | - /** | ||
129 | - * @param alias | ||
130 | - * @return PublicKey format HexString or null | ||
131 | - */ | ||
132 | private String getServerPublicKeyX509(String alias) { | 96 | private String getServerPublicKeyX509(String alias) { |
133 | try { | 97 | try { |
134 | - X509Certificate serverCertificate = (X509Certificate) contextServer.getKeyStoreValue().getCertificate(alias); | 98 | + X509Certificate serverCertificate = (X509Certificate) serverConfig.getKeyStoreValue().getCertificate(alias); |
135 | return Hex.encodeHexString(serverCertificate.getEncoded()); | 99 | return Hex.encodeHexString(serverCertificate.getEncoded()); |
136 | } catch (CertificateEncodingException | KeyStoreException e) { | 100 | } catch (CertificateEncodingException | KeyStoreException e) { |
137 | e.printStackTrace(); | 101 | e.printStackTrace(); |
@@ -139,11 +103,6 @@ public class LwM2MModelsRepository { | @@ -139,11 +103,6 @@ public class LwM2MModelsRepository { | ||
139 | return null; | 103 | return null; |
140 | } | 104 | } |
141 | 105 | ||
142 | - /** | ||
143 | - * @param publicServerX | ||
144 | - * @param publicServerY | ||
145 | - * @return PublicKey format HexString or null | ||
146 | - */ | ||
147 | private String getRPKPublicKey(String publicServerX, String publicServerY) { | 106 | private String getRPKPublicKey(String publicServerX, String publicServerY) { |
148 | try { | 107 | try { |
149 | /** Get Elliptic Curve Parameter spec for secp256r1 */ | 108 | /** Get Elliptic Curve Parameter spec for secp256r1 */ |
@@ -185,7 +185,7 @@ public class DefaultTbResourceService implements TbResourceService { | @@ -185,7 +185,7 @@ public class DefaultTbResourceService implements TbResourceService { | ||
185 | instance.setId(0); | 185 | instance.setId(0); |
186 | List<LwM2mResourceObserve> resources = new ArrayList<>(); | 186 | List<LwM2mResourceObserve> resources = new ArrayList<>(); |
187 | obj.resources.forEach((k, v) -> { | 187 | obj.resources.forEach((k, v) -> { |
188 | - if (!v.operations.isExecutable()) { | 188 | + if (v.operations.isReadable()) { |
189 | LwM2mResourceObserve lwM2MResourceObserve = new LwM2mResourceObserve(k, v.name, false, false, false); | 189 | LwM2mResourceObserve lwM2MResourceObserve = new LwM2mResourceObserve(k, v.name, false, false, false); |
190 | resources.add(lwM2MResourceObserve); | 190 | resources.add(lwM2MResourceObserve); |
191 | } | 191 | } |
@@ -41,6 +41,8 @@ import org.thingsboard.server.common.data.TenantProfile; | @@ -41,6 +41,8 @@ import org.thingsboard.server.common.data.TenantProfile; | ||
41 | import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials; | 41 | import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials; |
42 | import org.thingsboard.server.common.data.device.credentials.ProvisionDeviceCredentialsData; | 42 | import org.thingsboard.server.common.data.device.credentials.ProvisionDeviceCredentialsData; |
43 | import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials; | 43 | import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials; |
44 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
45 | +import org.thingsboard.server.common.data.firmware.FirmwareUtil; | ||
44 | import org.thingsboard.server.common.data.id.CustomerId; | 46 | import org.thingsboard.server.common.data.id.CustomerId; |
45 | import org.thingsboard.server.common.data.id.DeviceId; | 47 | import org.thingsboard.server.common.data.id.DeviceId; |
46 | import org.thingsboard.server.common.data.id.DeviceProfileId; | 48 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
@@ -512,16 +514,17 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -512,16 +514,17 @@ public class DefaultTransportApiService implements TransportApiService { | ||
512 | private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.GetFirmwareRequestMsg requestMsg) { | 514 | private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.GetFirmwareRequestMsg requestMsg) { |
513 | TenantId tenantId = new TenantId(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB())); | 515 | TenantId tenantId = new TenantId(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB())); |
514 | DeviceId deviceId = new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB())); | 516 | DeviceId deviceId = new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB())); |
517 | + FirmwareType firmwareType = FirmwareType.valueOf(requestMsg.getType()); | ||
515 | Device device = deviceService.findDeviceById(tenantId, deviceId); | 518 | Device device = deviceService.findDeviceById(tenantId, deviceId); |
516 | 519 | ||
517 | if (device == null) { | 520 | if (device == null) { |
518 | return getEmptyTransportApiResponseFuture(); | 521 | return getEmptyTransportApiResponseFuture(); |
519 | } | 522 | } |
520 | 523 | ||
521 | - FirmwareId firmwareId = device.getFirmwareId(); | ||
522 | - | 524 | + FirmwareId firmwareId = FirmwareUtil.getFirmwareId(device, firmwareType); |
523 | if (firmwareId == null) { | 525 | if (firmwareId == null) { |
524 | - firmwareId = deviceProfileCache.find(device.getDeviceProfileId()).getFirmwareId(); | 526 | + DeviceProfile deviceProfile = deviceProfileCache.find(device.getDeviceProfileId()); |
527 | + firmwareId = FirmwareUtil.getFirmwareId(deviceProfile, firmwareType); | ||
525 | } | 528 | } |
526 | 529 | ||
527 | TransportProtos.GetFirmwareResponseMsg.Builder builder = TransportProtos.GetFirmwareResponseMsg.newBuilder(); | 530 | TransportProtos.GetFirmwareResponseMsg.Builder builder = TransportProtos.GetFirmwareResponseMsg.newBuilder(); |
@@ -537,6 +540,7 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -537,6 +540,7 @@ public class DefaultTransportApiService implements TransportApiService { | ||
537 | builder.setResponseStatus(TransportProtos.ResponseStatus.SUCCESS); | 540 | builder.setResponseStatus(TransportProtos.ResponseStatus.SUCCESS); |
538 | builder.setFirmwareIdMSB(firmwareId.getId().getMostSignificantBits()); | 541 | builder.setFirmwareIdMSB(firmwareId.getId().getMostSignificantBits()); |
539 | builder.setFirmwareIdLSB(firmwareId.getId().getLeastSignificantBits()); | 542 | builder.setFirmwareIdLSB(firmwareId.getId().getLeastSignificantBits()); |
543 | + builder.setType(firmwareInfo.getType().name()); | ||
540 | builder.setTitle(firmwareInfo.getTitle()); | 544 | builder.setTitle(firmwareInfo.getTitle()); |
541 | builder.setVersion(firmwareInfo.getVersion()); | 545 | builder.setVersion(firmwareInfo.getVersion()); |
542 | builder.setFileName(firmwareInfo.getFileName()); | 546 | builder.setFileName(firmwareInfo.getFileName()); |
@@ -630,38 +630,14 @@ transport: | @@ -630,38 +630,14 @@ transport: | ||
630 | lwm2m: | 630 | lwm2m: |
631 | # Enable/disable lvm2m transport protocol. | 631 | # Enable/disable lvm2m transport protocol. |
632 | enabled: "${LWM2M_ENABLED:true}" | 632 | enabled: "${LWM2M_ENABLED:true}" |
633 | - # We choose a default timeout a bit higher to the MAX_TRANSMIT_WAIT(62-93s) which is the time from starting to | ||
634 | - # send a Confirmable message to the time when an acknowledgement is no longer expected. | ||
635 | - # DEFAULT_TIMEOUT = 2 * 60 * 1000l; 2 min in ms | ||
636 | - timeout: "${LWM2M_TIMEOUT:120000}" | ||
637 | - recommended_ciphers: "${LWM2M_RECOMMENDED_CIPHERS:false}" | ||
638 | - recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}" | ||
639 | - response_pool_size: "${LWM2M_RESPONSE_POOL_SIZE:100}" | ||
640 | - registered_pool_size: "${LWM2M_REGISTERED_POOL_SIZE:10}" | ||
641 | - update_registered_pool_size: "${LWM2M_UPDATE_REGISTERED_POOL_SIZE:10}" | ||
642 | - un_registered_pool_size: "${LWM2M_UN_REGISTERED_POOL_SIZE:10}" | ||
643 | - secure: | ||
644 | - # Certificate_x509: | ||
645 | - # To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format | ||
646 | - # Create new X509 Certificates: common/transport/lwm2m/src/main/resources/credentials/shell/lwM2M_credentials.sh | ||
647 | - key_store_type: "${LWM2M_KEYSTORE_TYPE:JKS}" | ||
648 | - # key_store_path_file: "${KEY_STORE_PATH_FILE:/common/transport/lwm2m/src/main/resources/credentials/serverKeyStore.jks" | ||
649 | - key_store_path_file: "${KEY_STORE_PATH_FILE:}" | ||
650 | - key_store_password: "${LWM2M_KEYSTORE_PASSWORD_SERVER:server_ks_password}" | ||
651 | - root_alias: "${LWM2M_SERVER_ROOT_CA:rootca}" | ||
652 | - enable_gen_new_key_psk_rpk: "${ENABLE_GEN_NEW_KEY_PSK_RPK:false}" | ||
653 | server: | 633 | server: |
654 | id: "${LWM2M_SERVER_ID:123}" | 634 | id: "${LWM2M_SERVER_ID:123}" |
655 | bind_address: "${LWM2M_BIND_ADDRESS:0.0.0.0}" | 635 | bind_address: "${LWM2M_BIND_ADDRESS:0.0.0.0}" |
656 | - bind_port_no_sec: "${LWM2M_BIND_PORT_NO_SEC:5685}" | ||
657 | - secure: | ||
658 | - bind_address_security: "${LWM2M_BIND_ADDRESS_SECURITY:0.0.0.0}" | ||
659 | - bind_port_security: "${LWM2M_BIND_PORT_SECURITY:5686}" | ||
660 | - # create_rpk: "${CREATE_RPK:}" | 636 | + bind_port: "${LWM2M_BIND_PORT:5685}" |
637 | + security: | ||
638 | + bind_address: "${LWM2M_BIND_ADDRESS_SECURITY:0.0.0.0}" | ||
639 | + bind_port: "${LWM2M_BIND_PORT_SECURITY:5686}" | ||
661 | # Only for RPK: Public & Private Key. If the keystore file is missing or not working | 640 | # Only for RPK: Public & Private Key. If the keystore file is missing or not working |
662 | - # - Public Key (Hex): [3059301306072a8648ce3d020106082a8648ce3d0301070342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b] | ||
663 | - # - Private Key (Hex): [308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b], | ||
664 | - # - Elliptic Curve parameters : [secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)] | ||
665 | public_x: "${LWM2M_SERVER_PUBLIC_X:05064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f358}" | 641 | public_x: "${LWM2M_SERVER_PUBLIC_X:05064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f358}" |
666 | public_y: "${LWM2M_SERVER_PUBLIC_Y:5eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}" | 642 | public_y: "${LWM2M_SERVER_PUBLIC_Y:5eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}" |
667 | private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}" | 643 | private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}" |
@@ -671,19 +647,34 @@ transport: | @@ -671,19 +647,34 @@ transport: | ||
671 | enable: "${LWM2M_ENABLED_BS:true}" | 647 | enable: "${LWM2M_ENABLED_BS:true}" |
672 | id: "${LWM2M_SERVER_ID_BS:111}" | 648 | id: "${LWM2M_SERVER_ID_BS:111}" |
673 | bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" | 649 | bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" |
674 | - bind_port_no_sec: "${LWM2M_BIND_PORT_NO_SEC_BS:5687}" | ||
675 | - secure: | ||
676 | - bind_address_security: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" | ||
677 | - bind_port_security: "${LWM2M_BIND_PORT_SECURITY_BS:5688}" | 650 | + bind_port: "${LWM2M_BIND_PORT_BS:5687}" |
651 | + security: | ||
652 | + bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" | ||
653 | + bind_port: "${LWM2M_BIND_PORT_SECURITY_BS:5688}" | ||
678 | # Only for RPK: Public & Private Key. If the keystore file is missing or not working | 654 | # Only for RPK: Public & Private Key. If the keystore file is missing or not working |
679 | - # - Elliptic Curve parameters : [secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)] | ||
680 | - # - Public Key (Hex): [3059301306072a8648ce3d020106082a8648ce3d030107034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34] | ||
681 | - # - Private Key (Hex): [308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34], | ||
682 | public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}" | 655 | public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}" |
683 | public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:3fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" | 656 | public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:3fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" |
684 | private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" | 657 | private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" |
685 | # Only Certificate_x509: | 658 | # Only Certificate_x509: |
686 | alias: "${LWM2M_KEYSTORE_ALIAS_BS:bootstrap}" | 659 | alias: "${LWM2M_KEYSTORE_ALIAS_BS:bootstrap}" |
660 | + security: | ||
661 | + # Certificate_x509: | ||
662 | + # To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format | ||
663 | + # Create new X509 Certificates: common/transport/lwm2m/src/main/resources/credentials/shell/lwM2M_credentials.sh | ||
664 | + key_store_type: "${LWM2M_KEYSTORE_TYPE:JKS}" | ||
665 | + # key_store_path_file: "${KEY_STORE_PATH_FILE:/common/transport/lwm2m/src/main/resources/credentials/serverKeyStore.jks" | ||
666 | + key_store: "${LWM2M_KEY_STORE:lwm2mserver.jks}" | ||
667 | + key_store_password: "${LWM2M_KEY_STORE_PASSWORD:server_ks_password}" | ||
668 | + root_alias: "${LWM2M_SERVER_ROOT_CA:rootca}" | ||
669 | + enable_gen_new_key_psk_rpk: "${ENABLE_GEN_NEW_KEY_PSK_RPK:false}" | ||
670 | + timeout: "${LWM2M_TIMEOUT:120000}" | ||
671 | + recommended_ciphers: "${LWM2M_RECOMMENDED_CIPHERS:false}" | ||
672 | + recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}" | ||
673 | + response_pool_size: "${LWM2M_RESPONSE_POOL_SIZE:100}" | ||
674 | + registered_pool_size: "${LWM2M_REGISTERED_POOL_SIZE:10}" | ||
675 | + update_registered_pool_size: "${LWM2M_UPDATE_REGISTERED_POOL_SIZE:10}" | ||
676 | + un_registered_pool_size: "${LWM2M_UN_REGISTERED_POOL_SIZE:10}" | ||
677 | + log_max_length: "${LWM2M_LOG_MAX_LENGTH:100}" | ||
687 | # Use redis for Security and Registration stores | 678 | # Use redis for Security and Registration stores |
688 | redis.enabled: "${LWM2M_REDIS_ENABLED:false}" | 679 | redis.enabled: "${LWM2M_REDIS_ENABLED:false}" |
689 | snmp: | 680 | snmp: |
@@ -24,10 +24,13 @@ import org.springframework.mock.web.MockMultipartFile; | @@ -24,10 +24,13 @@ import org.springframework.mock.web.MockMultipartFile; | ||
24 | import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; | 24 | import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; |
25 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; | 25 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; |
26 | import org.thingsboard.common.util.JacksonUtil; | 26 | import org.thingsboard.common.util.JacksonUtil; |
27 | +import org.thingsboard.server.common.data.DeviceProfile; | ||
27 | import org.thingsboard.server.common.data.Firmware; | 28 | import org.thingsboard.server.common.data.Firmware; |
28 | import org.thingsboard.server.common.data.FirmwareInfo; | 29 | import org.thingsboard.server.common.data.FirmwareInfo; |
29 | import org.thingsboard.server.common.data.Tenant; | 30 | import org.thingsboard.server.common.data.Tenant; |
30 | import org.thingsboard.server.common.data.User; | 31 | import org.thingsboard.server.common.data.User; |
32 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
33 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | ||
31 | import org.thingsboard.server.common.data.page.PageData; | 34 | import org.thingsboard.server.common.data.page.PageData; |
32 | import org.thingsboard.server.common.data.page.PageLink; | 35 | import org.thingsboard.server.common.data.page.PageLink; |
33 | import org.thingsboard.server.common.data.security.Authority; | 36 | import org.thingsboard.server.common.data.security.Authority; |
@@ -38,6 +41,7 @@ import java.util.Collections; | @@ -38,6 +41,7 @@ import java.util.Collections; | ||
38 | import java.util.List; | 41 | import java.util.List; |
39 | 42 | ||
40 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | 43 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
44 | +import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE; | ||
41 | 45 | ||
42 | public abstract class BaseFirmwareControllerTest extends AbstractControllerTest { | 46 | public abstract class BaseFirmwareControllerTest extends AbstractControllerTest { |
43 | 47 | ||
@@ -53,6 +57,7 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | @@ -53,6 +57,7 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | ||
53 | 57 | ||
54 | private Tenant savedTenant; | 58 | private Tenant savedTenant; |
55 | private User tenantAdmin; | 59 | private User tenantAdmin; |
60 | + private DeviceProfileId deviceProfileId; | ||
56 | 61 | ||
57 | @Before | 62 | @Before |
58 | public void beforeTest() throws Exception { | 63 | public void beforeTest() throws Exception { |
@@ -71,6 +76,11 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | @@ -71,6 +76,11 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | ||
71 | tenantAdmin.setLastName("Downs"); | 76 | tenantAdmin.setLastName("Downs"); |
72 | 77 | ||
73 | tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | 78 | tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); |
79 | + | ||
80 | + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile", null); | ||
81 | + DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); | ||
82 | + Assert.assertNotNull(savedDeviceProfile); | ||
83 | + deviceProfileId = savedDeviceProfile.getId(); | ||
74 | } | 84 | } |
75 | 85 | ||
76 | @After | 86 | @After |
@@ -84,6 +94,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | @@ -84,6 +94,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | ||
84 | @Test | 94 | @Test |
85 | public void testSaveFirmware() throws Exception { | 95 | public void testSaveFirmware() throws Exception { |
86 | FirmwareInfo firmwareInfo = new FirmwareInfo(); | 96 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
97 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | ||
98 | + firmwareInfo.setType(FIRMWARE); | ||
87 | firmwareInfo.setTitle(TITLE); | 99 | firmwareInfo.setTitle(TITLE); |
88 | firmwareInfo.setVersion(VERSION); | 100 | firmwareInfo.setVersion(VERSION); |
89 | 101 | ||
@@ -107,6 +119,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | @@ -107,6 +119,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | ||
107 | @Test | 119 | @Test |
108 | public void testSaveFirmwareData() throws Exception { | 120 | public void testSaveFirmwareData() throws Exception { |
109 | FirmwareInfo firmwareInfo = new FirmwareInfo(); | 121 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
122 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | ||
123 | + firmwareInfo.setType(FIRMWARE); | ||
110 | firmwareInfo.setTitle(TITLE); | 124 | firmwareInfo.setTitle(TITLE); |
111 | firmwareInfo.setVersion(VERSION); | 125 | firmwareInfo.setVersion(VERSION); |
112 | 126 | ||
@@ -137,6 +151,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | @@ -137,6 +151,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | ||
137 | @Test | 151 | @Test |
138 | public void testUpdateFirmwareFromDifferentTenant() throws Exception { | 152 | public void testUpdateFirmwareFromDifferentTenant() throws Exception { |
139 | FirmwareInfo firmwareInfo = new FirmwareInfo(); | 153 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
154 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | ||
155 | + firmwareInfo.setType(FIRMWARE); | ||
140 | firmwareInfo.setTitle(TITLE); | 156 | firmwareInfo.setTitle(TITLE); |
141 | firmwareInfo.setVersion(VERSION); | 157 | firmwareInfo.setVersion(VERSION); |
142 | 158 | ||
@@ -150,6 +166,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | @@ -150,6 +166,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | ||
150 | @Test | 166 | @Test |
151 | public void testFindFirmwareInfoById() throws Exception { | 167 | public void testFindFirmwareInfoById() throws Exception { |
152 | FirmwareInfo firmwareInfo = new FirmwareInfo(); | 168 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
169 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | ||
170 | + firmwareInfo.setType(FIRMWARE); | ||
153 | firmwareInfo.setTitle(TITLE); | 171 | firmwareInfo.setTitle(TITLE); |
154 | firmwareInfo.setVersion(VERSION); | 172 | firmwareInfo.setVersion(VERSION); |
155 | 173 | ||
@@ -163,6 +181,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | @@ -163,6 +181,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | ||
163 | @Test | 181 | @Test |
164 | public void testFindFirmwareById() throws Exception { | 182 | public void testFindFirmwareById() throws Exception { |
165 | FirmwareInfo firmwareInfo = new FirmwareInfo(); | 183 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
184 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | ||
185 | + firmwareInfo.setType(FIRMWARE); | ||
166 | firmwareInfo.setTitle(TITLE); | 186 | firmwareInfo.setTitle(TITLE); |
167 | firmwareInfo.setVersion(VERSION); | 187 | firmwareInfo.setVersion(VERSION); |
168 | 188 | ||
@@ -180,6 +200,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | @@ -180,6 +200,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | ||
180 | @Test | 200 | @Test |
181 | public void testDeleteFirmware() throws Exception { | 201 | public void testDeleteFirmware() throws Exception { |
182 | FirmwareInfo firmwareInfo = new FirmwareInfo(); | 202 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
203 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | ||
204 | + firmwareInfo.setType(FIRMWARE); | ||
183 | firmwareInfo.setTitle(TITLE); | 205 | firmwareInfo.setTitle(TITLE); |
184 | firmwareInfo.setVersion(VERSION); | 206 | firmwareInfo.setVersion(VERSION); |
185 | 207 | ||
@@ -197,6 +219,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | @@ -197,6 +219,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | ||
197 | List<FirmwareInfo> firmwares = new ArrayList<>(); | 219 | List<FirmwareInfo> firmwares = new ArrayList<>(); |
198 | for (int i = 0; i < 165; i++) { | 220 | for (int i = 0; i < 165; i++) { |
199 | FirmwareInfo firmwareInfo = new FirmwareInfo(); | 221 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
222 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | ||
223 | + firmwareInfo.setType(FIRMWARE); | ||
200 | firmwareInfo.setTitle(TITLE); | 224 | firmwareInfo.setTitle(TITLE); |
201 | firmwareInfo.setVersion(VERSION + i); | 225 | firmwareInfo.setVersion(VERSION + i); |
202 | 226 | ||
@@ -238,6 +262,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | @@ -238,6 +262,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | ||
238 | 262 | ||
239 | for (int i = 0; i < 165; i++) { | 263 | for (int i = 0; i < 165; i++) { |
240 | FirmwareInfo firmwareInfo = new FirmwareInfo(); | 264 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
265 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | ||
266 | + firmwareInfo.setType(FIRMWARE); | ||
241 | firmwareInfo.setTitle(TITLE); | 267 | firmwareInfo.setTitle(TITLE); |
242 | firmwareInfo.setVersion(VERSION + i); | 268 | firmwareInfo.setVersion(VERSION + i); |
243 | 269 | ||
@@ -257,7 +283,7 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | @@ -257,7 +283,7 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | ||
257 | PageLink pageLink = new PageLink(24); | 283 | PageLink pageLink = new PageLink(24); |
258 | PageData<FirmwareInfo> pageData; | 284 | PageData<FirmwareInfo> pageData; |
259 | do { | 285 | do { |
260 | - pageData = doGetTypedWithPageLink("/api/firmwares/true?", | 286 | + pageData = doGetTypedWithPageLink("/api/firmwares/" + deviceProfileId.toString() + "/FIRMWARE/true?", |
261 | new TypeReference<>() { | 287 | new TypeReference<>() { |
262 | }, pageLink); | 288 | }, pageLink); |
263 | loadedFirmwaresWithData.addAll(pageData.getData()); | 289 | loadedFirmwaresWithData.addAll(pageData.getData()); |
@@ -269,7 +295,7 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | @@ -269,7 +295,7 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest | ||
269 | List<FirmwareInfo> loadedFirmwaresWithoutData = new ArrayList<>(); | 295 | List<FirmwareInfo> loadedFirmwaresWithoutData = new ArrayList<>(); |
270 | pageLink = new PageLink(24); | 296 | pageLink = new PageLink(24); |
271 | do { | 297 | do { |
272 | - pageData = doGetTypedWithPageLink("/api/firmwares/false?", | 298 | + pageData = doGetTypedWithPageLink("/api/firmwares/" + deviceProfileId.toString() + "/FIRMWARE/false?", |
273 | new TypeReference<>() { | 299 | new TypeReference<>() { |
274 | }, pageLink); | 300 | }, pageLink); |
275 | loadedFirmwaresWithoutData.addAll(pageData.getData()); | 301 | loadedFirmwaresWithoutData.addAll(pageData.getData()); |
@@ -65,6 +65,8 @@ public interface DeviceService { | @@ -65,6 +65,8 @@ public interface DeviceService { | ||
65 | 65 | ||
66 | PageData<Device> findDevicesByTenantIdAndTypeAndEmptyFirmware(TenantId tenantId, String type, PageLink pageLink); | 66 | PageData<Device> findDevicesByTenantIdAndTypeAndEmptyFirmware(TenantId tenantId, String type, PageLink pageLink); |
67 | 67 | ||
68 | + PageData<Device> findDevicesByTenantIdAndTypeAndEmptySoftware(TenantId tenantId, String type, PageLink pageLink); | ||
69 | + | ||
68 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink); | 70 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink); |
69 | 71 | ||
70 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndDeviceProfileId(TenantId tenantId, DeviceProfileId deviceProfileId, PageLink pageLink); | 72 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndDeviceProfileId(TenantId tenantId, DeviceProfileId deviceProfileId, PageLink pageLink); |
@@ -18,6 +18,8 @@ package org.thingsboard.server.dao.firmware; | @@ -18,6 +18,8 @@ package org.thingsboard.server.dao.firmware; | ||
18 | import com.google.common.util.concurrent.ListenableFuture; | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | import org.thingsboard.server.common.data.Firmware; | 19 | import org.thingsboard.server.common.data.Firmware; |
20 | import org.thingsboard.server.common.data.FirmwareInfo; | 20 | import org.thingsboard.server.common.data.FirmwareInfo; |
21 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
22 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | ||
21 | import org.thingsboard.server.common.data.id.FirmwareId; | 23 | import org.thingsboard.server.common.data.id.FirmwareId; |
22 | import org.thingsboard.server.common.data.id.TenantId; | 24 | import org.thingsboard.server.common.data.id.TenantId; |
23 | import org.thingsboard.server.common.data.page.PageData; | 25 | import org.thingsboard.server.common.data.page.PageData; |
@@ -37,7 +39,7 @@ public interface FirmwareService { | @@ -37,7 +39,7 @@ public interface FirmwareService { | ||
37 | 39 | ||
38 | PageData<FirmwareInfo> findTenantFirmwaresByTenantId(TenantId tenantId, PageLink pageLink); | 40 | PageData<FirmwareInfo> findTenantFirmwaresByTenantId(TenantId tenantId, PageLink pageLink); |
39 | 41 | ||
40 | - PageData<FirmwareInfo> findTenantFirmwaresByTenantIdAndHasData(TenantId tenantId, boolean hasData, PageLink pageLink); | 42 | + PageData<FirmwareInfo> findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, FirmwareType firmwareType, boolean hasData, PageLink pageLink); |
41 | 43 | ||
42 | void deleteFirmware(TenantId tenantId, FirmwareId firmwareId); | 44 | void deleteFirmware(TenantId tenantId, FirmwareId firmwareId); |
43 | 45 |
@@ -93,22 +93,26 @@ public class DataConstants { | @@ -93,22 +93,26 @@ public class DataConstants { | ||
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 | 95 | ||
96 | - //firmware | ||
97 | - //telemetry | ||
98 | - public static final String CURRENT_FIRMWARE_TITLE = "cur_fw_title"; | ||
99 | - public static final String CURRENT_FIRMWARE_VERSION = "cur_fw_version"; | ||
100 | - public static final String TARGET_FIRMWARE_TITLE = "target_fw_title"; | ||
101 | - public static final String TARGET_FIRMWARE_VERSION = "target_fw_version"; | ||
102 | - public static final String TARGET_FIRMWARE_TS = "target_fw_ts"; | ||
103 | - public static final String FIRMWARE_STATE = "fw_state"; | ||
104 | - | ||
105 | - //attributes | ||
106 | - //telemetry | ||
107 | - public static final String FIRMWARE_TITLE = "fw_title"; | ||
108 | - public static final String FIRMWARE_VERSION = "fw_version"; | ||
109 | - public static final String FIRMWARE_SIZE = "fw_size"; | ||
110 | - public static final String FIRMWARE_CHECKSUM = "fw_checksum"; | ||
111 | - public static final String FIRMWARE_CHECKSUM_ALGORITHM = "fw_checksum_algorithm"; | 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 | ||
112 | public static final String EDGE_MSG_SOURCE = "edge"; | 115 | public static final String EDGE_MSG_SOURCE = "edge"; |
113 | public static final String MSG_SOURCE_KEY = "source"; | 116 | public static final String MSG_SOURCE_KEY = "source"; |
117 | + | ||
114 | } | 118 | } |
@@ -32,7 +32,7 @@ import java.io.IOException; | @@ -32,7 +32,7 @@ import java.io.IOException; | ||
32 | 32 | ||
33 | @EqualsAndHashCode(callSuper = true) | 33 | @EqualsAndHashCode(callSuper = true) |
34 | @Slf4j | 34 | @Slf4j |
35 | -public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implements HasName, HasTenantId, HasCustomerId { | 35 | +public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implements HasName, HasTenantId, HasCustomerId, HasFirmware { |
36 | 36 | ||
37 | private static final long serialVersionUID = 2807343040519543363L; | 37 | private static final long serialVersionUID = 2807343040519543363L; |
38 | 38 | ||
@@ -50,6 +50,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen | @@ -50,6 +50,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen | ||
50 | private byte[] deviceDataBytes; | 50 | private byte[] deviceDataBytes; |
51 | 51 | ||
52 | private FirmwareId firmwareId; | 52 | private FirmwareId firmwareId; |
53 | + private FirmwareId softwareId; | ||
53 | 54 | ||
54 | public Device() { | 55 | public Device() { |
55 | super(); | 56 | super(); |
@@ -69,6 +70,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen | @@ -69,6 +70,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen | ||
69 | this.deviceProfileId = device.getDeviceProfileId(); | 70 | this.deviceProfileId = device.getDeviceProfileId(); |
70 | this.setDeviceData(device.getDeviceData()); | 71 | this.setDeviceData(device.getDeviceData()); |
71 | this.firmwareId = device.getFirmwareId(); | 72 | this.firmwareId = device.getFirmwareId(); |
73 | + this.softwareId = device.getSoftwareId(); | ||
72 | } | 74 | } |
73 | 75 | ||
74 | public Device updateDevice(Device device) { | 76 | public Device updateDevice(Device device) { |
@@ -79,6 +81,8 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen | @@ -79,6 +81,8 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen | ||
79 | this.label = device.getLabel(); | 81 | this.label = device.getLabel(); |
80 | this.deviceProfileId = device.getDeviceProfileId(); | 82 | this.deviceProfileId = device.getDeviceProfileId(); |
81 | this.setDeviceData(device.getDeviceData()); | 83 | this.setDeviceData(device.getDeviceData()); |
84 | + this.setFirmwareId(device.getFirmwareId()); | ||
85 | + this.setSoftwareId(device.getSoftwareId()); | ||
82 | return this; | 86 | return this; |
83 | } | 87 | } |
84 | 88 | ||
@@ -171,6 +175,14 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen | @@ -171,6 +175,14 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen | ||
171 | this.firmwareId = firmwareId; | 175 | this.firmwareId = firmwareId; |
172 | } | 176 | } |
173 | 177 | ||
178 | + public FirmwareId getSoftwareId() { | ||
179 | + return softwareId; | ||
180 | + } | ||
181 | + | ||
182 | + public void setSoftwareId(FirmwareId softwareId) { | ||
183 | + this.softwareId = softwareId; | ||
184 | + } | ||
185 | + | ||
174 | @Override | 186 | @Override |
175 | public String toString() { | 187 | public String toString() { |
176 | StringBuilder builder = new StringBuilder(); | 188 | StringBuilder builder = new StringBuilder(); |
@@ -36,7 +36,7 @@ import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalIn | @@ -36,7 +36,7 @@ import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalIn | ||
36 | @Data | 36 | @Data |
37 | @EqualsAndHashCode(callSuper = true) | 37 | @EqualsAndHashCode(callSuper = true) |
38 | @Slf4j | 38 | @Slf4j |
39 | -public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements HasName, HasTenantId { | 39 | +public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements HasName, HasTenantId, HasFirmware { |
40 | 40 | ||
41 | private TenantId tenantId; | 41 | private TenantId tenantId; |
42 | @NoXss | 42 | @NoXss |
@@ -59,6 +59,8 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | @@ -59,6 +59,8 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | ||
59 | 59 | ||
60 | private FirmwareId firmwareId; | 60 | private FirmwareId firmwareId; |
61 | 61 | ||
62 | + private FirmwareId softwareId; | ||
63 | + | ||
62 | public DeviceProfile() { | 64 | public DeviceProfile() { |
63 | super(); | 65 | super(); |
64 | } | 66 | } |
@@ -77,6 +79,8 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | @@ -77,6 +79,8 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | ||
77 | this.defaultQueueName = deviceProfile.getDefaultQueueName(); | 79 | this.defaultQueueName = deviceProfile.getDefaultQueueName(); |
78 | this.setProfileData(deviceProfile.getProfileData()); | 80 | this.setProfileData(deviceProfile.getProfileData()); |
79 | this.provisionDeviceKey = deviceProfile.getProvisionDeviceKey(); | 81 | this.provisionDeviceKey = deviceProfile.getProvisionDeviceKey(); |
82 | + this.firmwareId = deviceProfile.getFirmwareId(); | ||
83 | + this.softwareId = deviceProfile.getSoftwareId(); | ||
80 | } | 84 | } |
81 | 85 | ||
82 | @Override | 86 | @Override |
@@ -19,6 +19,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore; | @@ -19,6 +19,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore; | ||
19 | import lombok.Data; | 19 | import lombok.Data; |
20 | import lombok.EqualsAndHashCode; | 20 | import lombok.EqualsAndHashCode; |
21 | import lombok.extern.slf4j.Slf4j; | 21 | import lombok.extern.slf4j.Slf4j; |
22 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
23 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | ||
22 | import org.thingsboard.server.common.data.id.FirmwareId; | 24 | import org.thingsboard.server.common.data.id.FirmwareId; |
23 | import org.thingsboard.server.common.data.id.TenantId; | 25 | import org.thingsboard.server.common.data.id.TenantId; |
24 | 26 | ||
@@ -30,6 +32,8 @@ public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId> | @@ -30,6 +32,8 @@ public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId> | ||
30 | private static final long serialVersionUID = 3168391583570815419L; | 32 | private static final long serialVersionUID = 3168391583570815419L; |
31 | 33 | ||
32 | private TenantId tenantId; | 34 | private TenantId tenantId; |
35 | + private DeviceProfileId deviceProfileId; | ||
36 | + private FirmwareType type; | ||
33 | private String title; | 37 | private String title; |
34 | private String version; | 38 | private String version; |
35 | private boolean hasData; | 39 | private boolean hasData; |
@@ -51,6 +55,8 @@ public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId> | @@ -51,6 +55,8 @@ public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId> | ||
51 | public FirmwareInfo(FirmwareInfo firmwareInfo) { | 55 | public FirmwareInfo(FirmwareInfo firmwareInfo) { |
52 | super(firmwareInfo); | 56 | super(firmwareInfo); |
53 | this.tenantId = firmwareInfo.getTenantId(); | 57 | this.tenantId = firmwareInfo.getTenantId(); |
58 | + this.deviceProfileId = firmwareInfo.getDeviceProfileId(); | ||
59 | + this.type = firmwareInfo.getType(); | ||
54 | this.title = firmwareInfo.getTitle(); | 60 | this.title = firmwareInfo.getTitle(); |
55 | this.version = firmwareInfo.getVersion(); | 61 | this.version = firmwareInfo.getVersion(); |
56 | this.hasData = firmwareInfo.isHasData(); | 62 | this.hasData = firmwareInfo.isHasData(); |
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.common.data; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.id.FirmwareId; | ||
19 | + | ||
20 | +public interface HasFirmware { | ||
21 | + | ||
22 | + FirmwareId getFirmwareId(); | ||
23 | + | ||
24 | + FirmwareId getSoftwareId(); | ||
25 | +} |
@@ -31,6 +31,7 @@ public class MqttTopics { | @@ -31,6 +31,7 @@ public class MqttTopics { | ||
31 | private static final String SUB_TOPIC = "+"; | 31 | private static final String SUB_TOPIC = "+"; |
32 | private static final String PROVISION = "/provision"; | 32 | private static final String PROVISION = "/provision"; |
33 | private static final String FIRMWARE = "/fw"; | 33 | private static final String FIRMWARE = "/fw"; |
34 | + private static final String SOFTWARE = "/sw"; | ||
34 | private static final String CHUNK = "/chunk/"; | 35 | private static final String CHUNK = "/chunk/"; |
35 | private static final String ERROR = "/error"; | 36 | private static final String ERROR = "/error"; |
36 | 37 | ||
@@ -75,9 +76,17 @@ public class MqttTopics { | @@ -75,9 +76,17 @@ public class MqttTopics { | ||
75 | // v2 topics | 76 | // v2 topics |
76 | public static final String BASE_DEVICE_API_TOPIC_V2 = "v2"; | 77 | public static final String BASE_DEVICE_API_TOPIC_V2 = "v2"; |
77 | 78 | ||
78 | - public static final String DEVICE_FIRMWARE_RESPONSE_TOPIC_PREFIX = BASE_DEVICE_API_TOPIC_V2 + FIRMWARE + RESPONSE + "/"; | ||
79 | - public static final String DEVICE_FIRMWARE_RESPONSES_TOPIC = DEVICE_FIRMWARE_RESPONSE_TOPIC_PREFIX + SUB_TOPIC + CHUNK + SUB_TOPIC; | 79 | + public static final String REQUEST_ID_PATTERN = "(?<requestId>\\d+)"; |
80 | + public static final String CHUNK_PATTERN = "(?<chunk>\\d+)"; | ||
81 | + | ||
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; | ||
80 | 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"; | ||
86 | + | ||
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; | ||
89 | + public static final String DEVICE_SOFTWARE_ERROR_TOPIC = BASE_DEVICE_API_TOPIC_V2 + SOFTWARE + ERROR; | ||
81 | 90 | ||
82 | private MqttTopics() { | 91 | private MqttTopics() { |
83 | } | 92 | } |
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.common.data.firmware; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | + | ||
20 | +public enum FirmwareKey { | ||
21 | + | ||
22 | + TITLE("title"), VERSION("version"), TS("ts"), STATE("state"), SIZE("size"), CHECKSUM("checksum"), CHECKSUM_ALGORITHM("checksum_algorithm"); | ||
23 | + | ||
24 | + @Getter | ||
25 | + private final String value; | ||
26 | + | ||
27 | + FirmwareKey(String value) { | ||
28 | + this.value = value; | ||
29 | + } | ||
30 | +} |
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.common.data.firmware; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | + | ||
20 | +public enum FirmwareType { | ||
21 | + | ||
22 | + FIRMWARE("fw"), SOFTWARE("sw"); | ||
23 | + | ||
24 | + @Getter | ||
25 | + private final String keyPrefix; | ||
26 | + | ||
27 | + FirmwareType(String keyPrefix) { | ||
28 | + this.keyPrefix = keyPrefix; | ||
29 | + } | ||
30 | +} |
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.common.data.firmware; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | +import org.thingsboard.server.common.data.HasFirmware; | ||
20 | +import org.thingsboard.server.common.data.id.FirmwareId; | ||
21 | + | ||
22 | +import java.util.ArrayList; | ||
23 | +import java.util.Collections; | ||
24 | +import java.util.List; | ||
25 | + | ||
26 | +import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE; | ||
27 | +import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE; | ||
28 | + | ||
29 | +@Slf4j | ||
30 | +public class FirmwareUtil { | ||
31 | + | ||
32 | + public static final List<String> ALL_FW_ATTRIBUTE_KEYS; | ||
33 | + | ||
34 | + public static final List<String> ALL_SW_ATTRIBUTE_KEYS; | ||
35 | + | ||
36 | + static { | ||
37 | + ALL_FW_ATTRIBUTE_KEYS = new ArrayList<>(); | ||
38 | + for (FirmwareKey key : FirmwareKey.values()) { | ||
39 | + ALL_FW_ATTRIBUTE_KEYS.add(getAttributeKey(FIRMWARE, key)); | ||
40 | + | ||
41 | + } | ||
42 | + | ||
43 | + ALL_SW_ATTRIBUTE_KEYS = new ArrayList<>(); | ||
44 | + for (FirmwareKey key : FirmwareKey.values()) { | ||
45 | + ALL_SW_ATTRIBUTE_KEYS.add(getAttributeKey(SOFTWARE, key)); | ||
46 | + | ||
47 | + } | ||
48 | + } | ||
49 | + | ||
50 | + public static List<String> getAttributeKeys(FirmwareType firmwareType) { | ||
51 | + switch (firmwareType) { | ||
52 | + case FIRMWARE: | ||
53 | + return ALL_FW_ATTRIBUTE_KEYS; | ||
54 | + case SOFTWARE: | ||
55 | + return ALL_SW_ATTRIBUTE_KEYS; | ||
56 | + } | ||
57 | + return Collections.emptyList(); | ||
58 | + } | ||
59 | + | ||
60 | + public static String getAttributeKey(FirmwareType type, FirmwareKey key) { | ||
61 | + return type.getKeyPrefix() + "_" + key.getValue(); | ||
62 | + } | ||
63 | + | ||
64 | + public static String getTargetTelemetryKey(FirmwareType type, FirmwareKey key) { | ||
65 | + return getTelemetryKey("target_", type, key); | ||
66 | + } | ||
67 | + | ||
68 | + public static String getCurrentTelemetryKey(FirmwareType type, FirmwareKey key) { | ||
69 | + return getTelemetryKey("current_", type, key); | ||
70 | + } | ||
71 | + | ||
72 | + private static String getTelemetryKey(String prefix, FirmwareType type, FirmwareKey key) { | ||
73 | + return prefix + type.getKeyPrefix() + "_" + key.getValue(); | ||
74 | + } | ||
75 | + | ||
76 | + public static String getTelemetryKey(FirmwareType type, FirmwareKey key) { | ||
77 | + return type.getKeyPrefix() + "_" + key.getValue(); | ||
78 | + } | ||
79 | + | ||
80 | + public static FirmwareId getFirmwareId(HasFirmware entity, FirmwareType firmwareType) { | ||
81 | + switch (firmwareType) { | ||
82 | + case FIRMWARE: | ||
83 | + return entity.getFirmwareId(); | ||
84 | + case SOFTWARE: | ||
85 | + return entity.getSoftwareId(); | ||
86 | + default: | ||
87 | + log.warn("Unsupported firmware type: [{}]", firmwareType); | ||
88 | + return null; | ||
89 | + } | ||
90 | + } | ||
91 | +} |
@@ -16,5 +16,5 @@ | @@ -16,5 +16,5 @@ | ||
16 | package org.thingsboard.server.common.msg.session; | 16 | package org.thingsboard.server.common.msg.session; |
17 | 17 | ||
18 | public enum FeatureType { | 18 | public enum FeatureType { |
19 | - ATTRIBUTES, TELEMETRY, RPC, CLAIM, PROVISION, FIRMWARE | 19 | + ATTRIBUTES, TELEMETRY, RPC, CLAIM, PROVISION, FIRMWARE, SOFTWARE |
20 | } | 20 | } |
@@ -32,7 +32,8 @@ public enum SessionMsgType { | @@ -32,7 +32,8 @@ public enum SessionMsgType { | ||
32 | 32 | ||
33 | CLAIM_REQUEST(), | 33 | CLAIM_REQUEST(), |
34 | 34 | ||
35 | - GET_FIRMWARE_REQUEST; | 35 | + GET_FIRMWARE_REQUEST, |
36 | + GET_SOFTWARE_REQUEST; | ||
36 | 37 | ||
37 | private final boolean requiresRulesProcessing; | 38 | private final boolean requiresRulesProcessing; |
38 | 39 |
@@ -388,16 +388,18 @@ message GetFirmwareRequestMsg { | @@ -388,16 +388,18 @@ message GetFirmwareRequestMsg { | ||
388 | int64 deviceIdLSB = 2; | 388 | int64 deviceIdLSB = 2; |
389 | int64 tenantIdMSB = 3; | 389 | int64 tenantIdMSB = 3; |
390 | int64 tenantIdLSB = 4; | 390 | int64 tenantIdLSB = 4; |
391 | + string type = 5; | ||
391 | } | 392 | } |
392 | 393 | ||
393 | message GetFirmwareResponseMsg { | 394 | message GetFirmwareResponseMsg { |
394 | ResponseStatus responseStatus = 1; | 395 | ResponseStatus responseStatus = 1; |
395 | int64 firmwareIdMSB = 2; | 396 | int64 firmwareIdMSB = 2; |
396 | int64 firmwareIdLSB = 3; | 397 | int64 firmwareIdLSB = 3; |
397 | - string title = 4; | ||
398 | - string version = 5; | ||
399 | - string contentType = 6; | ||
400 | - string fileName = 7; | 398 | + string type = 4; |
399 | + string title = 5; | ||
400 | + string version = 6; | ||
401 | + string contentType = 7; | ||
402 | + string fileName = 8; | ||
401 | } | 403 | } |
402 | 404 | ||
403 | //Used to report session state to tb-Service and persist this state in the cache on the tb-Service level. | 405 | //Used to report session state to tb-Service and persist this state in the cache on the tb-Service level. |
@@ -711,4 +713,5 @@ message ToFirmwareStateServiceMsg { | @@ -711,4 +713,5 @@ message ToFirmwareStateServiceMsg { | ||
711 | int64 deviceIdLSB = 5; | 713 | int64 deviceIdLSB = 5; |
712 | int64 firmwareIdMSB = 6; | 714 | int64 firmwareIdMSB = 6; |
713 | int64 firmwareIdLSB = 7; | 715 | int64 firmwareIdLSB = 7; |
716 | + string type = 8; | ||
714 | } | 717 | } |
common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java
@@ -43,6 +43,7 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportC | @@ -43,6 +43,7 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportC | ||
43 | import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration; | 43 | import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration; |
44 | import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | 44 | import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; |
45 | import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | 45 | import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; |
46 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
46 | import org.thingsboard.server.common.data.security.DeviceTokenCredentials; | 47 | import org.thingsboard.server.common.data.security.DeviceTokenCredentials; |
47 | import org.thingsboard.server.common.msg.session.FeatureType; | 48 | import org.thingsboard.server.common.msg.session.FeatureType; |
48 | import org.thingsboard.server.common.msg.session.SessionMsgType; | 49 | import org.thingsboard.server.common.msg.session.SessionMsgType; |
@@ -122,6 +123,8 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | @@ -122,6 +123,8 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | ||
122 | processRequest(exchange, SessionMsgType.GET_ATTRIBUTES_REQUEST); | 123 | processRequest(exchange, SessionMsgType.GET_ATTRIBUTES_REQUEST); |
123 | } else if (featureType.get() == FeatureType.FIRMWARE) { | 124 | } else if (featureType.get() == FeatureType.FIRMWARE) { |
124 | processRequest(exchange, SessionMsgType.GET_FIRMWARE_REQUEST); | 125 | processRequest(exchange, SessionMsgType.GET_FIRMWARE_REQUEST); |
126 | + } else if (featureType.get() == FeatureType.SOFTWARE) { | ||
127 | + processRequest(exchange, SessionMsgType.GET_SOFTWARE_REQUEST); | ||
125 | } else { | 128 | } else { |
126 | log.trace("Invalid feature type parameter"); | 129 | log.trace("Invalid feature type parameter"); |
127 | exchange.respond(CoAP.ResponseCode.BAD_REQUEST); | 130 | exchange.respond(CoAP.ResponseCode.BAD_REQUEST); |
@@ -326,12 +329,10 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | @@ -326,12 +329,10 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | ||
326 | new CoapNoOpCallback(exchange)); | 329 | new CoapNoOpCallback(exchange)); |
327 | break; | 330 | break; |
328 | case GET_FIRMWARE_REQUEST: | 331 | case GET_FIRMWARE_REQUEST: |
329 | - TransportProtos.GetFirmwareRequestMsg requestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder() | ||
330 | - .setTenantIdMSB(sessionInfo.getTenantIdMSB()) | ||
331 | - .setTenantIdLSB(sessionInfo.getTenantIdLSB()) | ||
332 | - .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) | ||
333 | - .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()).build(); | ||
334 | - transportContext.getTransportService().process(sessionInfo, requestMsg, new FirmwareCallback(exchange)); | 332 | + getFirmwareCallback(sessionInfo, exchange, FirmwareType.FIRMWARE); |
333 | + break; | ||
334 | + case GET_SOFTWARE_REQUEST: | ||
335 | + getFirmwareCallback(sessionInfo, exchange, FirmwareType.SOFTWARE); | ||
335 | break; | 336 | break; |
336 | } | 337 | } |
337 | } catch (AdaptorException e) { | 338 | } catch (AdaptorException e) { |
@@ -340,6 +341,16 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | @@ -340,6 +341,16 @@ public class CoapTransportResource extends AbstractCoapTransportResource { | ||
340 | } | 341 | } |
341 | } | 342 | } |
342 | 343 | ||
344 | + private void getFirmwareCallback(TransportProtos.SessionInfoProto sessionInfo, CoapExchange exchange, FirmwareType firmwareType) { | ||
345 | + TransportProtos.GetFirmwareRequestMsg requestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder() | ||
346 | + .setTenantIdMSB(sessionInfo.getTenantIdMSB()) | ||
347 | + .setTenantIdLSB(sessionInfo.getTenantIdLSB()) | ||
348 | + .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) | ||
349 | + .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) | ||
350 | + .setType(firmwareType.name()).build(); | ||
351 | + transportContext.getTransportService().process(sessionInfo, requestMsg, new FirmwareCallback(exchange)); | ||
352 | + } | ||
353 | + | ||
343 | private TransportProtos.SessionInfoProto lookupAsyncSessionInfo(String token) { | 354 | private TransportProtos.SessionInfoProto lookupAsyncSessionInfo(String token) { |
344 | tokenToNotificationCounterMap.remove(token); | 355 | tokenToNotificationCounterMap.remove(token); |
345 | return tokenToSessionIdMap.remove(token); | 356 | return tokenToSessionIdMap.remove(token); |
@@ -34,6 +34,7 @@ import org.springframework.web.bind.annotation.RequestParam; | @@ -34,6 +34,7 @@ import org.springframework.web.bind.annotation.RequestParam; | ||
34 | import org.springframework.web.bind.annotation.RestController; | 34 | import org.springframework.web.bind.annotation.RestController; |
35 | import org.springframework.web.context.request.async.DeferredResult; | 35 | import org.springframework.web.context.request.async.DeferredResult; |
36 | import org.thingsboard.server.common.data.DeviceTransportType; | 36 | import org.thingsboard.server.common.data.DeviceTransportType; |
37 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
37 | import org.thingsboard.server.common.data.TbTransportService; | 38 | import org.thingsboard.server.common.data.TbTransportService; |
38 | import org.thingsboard.server.common.data.id.DeviceId; | 39 | import org.thingsboard.server.common.data.id.DeviceId; |
39 | import org.thingsboard.server.common.transport.SessionMsgListener; | 40 | import org.thingsboard.server.common.transport.SessionMsgListener; |
@@ -210,8 +211,29 @@ public class DeviceApiController implements TbTransportService { | @@ -210,8 +211,29 @@ public class DeviceApiController implements TbTransportService { | ||
210 | public DeferredResult<ResponseEntity> getFirmware(@PathVariable("deviceToken") String deviceToken, | 211 | public DeferredResult<ResponseEntity> getFirmware(@PathVariable("deviceToken") String deviceToken, |
211 | @RequestParam(value = "title") String title, | 212 | @RequestParam(value = "title") String title, |
212 | @RequestParam(value = "version") String version, | 213 | @RequestParam(value = "version") String version, |
213 | - @RequestParam(value = "chunkSize", required = false, defaultValue = "0") int chunkSize, | 214 | + @RequestParam(value = "size", required = false, defaultValue = "0") int size, |
214 | @RequestParam(value = "chunk", required = false, defaultValue = "0") int chunk) { | 215 | @RequestParam(value = "chunk", required = false, defaultValue = "0") int chunk) { |
216 | + return getFirmwareCallback(deviceToken, title, version, size, chunk, FirmwareType.FIRMWARE); | ||
217 | + } | ||
218 | + | ||
219 | + @RequestMapping(value = "/{deviceToken}/software", method = RequestMethod.GET) | ||
220 | + public DeferredResult<ResponseEntity> getSoftware(@PathVariable("deviceToken") String deviceToken, | ||
221 | + @RequestParam(value = "title") String title, | ||
222 | + @RequestParam(value = "version") String version, | ||
223 | + @RequestParam(value = "size", required = false, defaultValue = "0") int size, | ||
224 | + @RequestParam(value = "chunk", required = false, defaultValue = "0") int chunk) { | ||
225 | + return getFirmwareCallback(deviceToken, title, version, size, chunk, FirmwareType.SOFTWARE); | ||
226 | + } | ||
227 | + | ||
228 | + @RequestMapping(value = "/provision", method = RequestMethod.POST) | ||
229 | + public DeferredResult<ResponseEntity> provisionDevice(@RequestBody String json, HttpServletRequest httpRequest) { | ||
230 | + DeferredResult<ResponseEntity> responseWriter = new DeferredResult<>(); | ||
231 | + transportContext.getTransportService().process(JsonConverter.convertToProvisionRequestMsg(json), | ||
232 | + new DeviceProvisionCallback(responseWriter)); | ||
233 | + return responseWriter; | ||
234 | + } | ||
235 | + | ||
236 | + private DeferredResult<ResponseEntity> getFirmwareCallback(String deviceToken, String title, String version, int size, int chunk, FirmwareType firmwareType) { | ||
215 | DeferredResult<ResponseEntity> responseWriter = new DeferredResult<>(); | 237 | DeferredResult<ResponseEntity> responseWriter = new DeferredResult<>(); |
216 | transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), | 238 | transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), |
217 | new DeviceAuthCallback(transportContext, responseWriter, sessionInfo -> { | 239 | new DeviceAuthCallback(transportContext, responseWriter, sessionInfo -> { |
@@ -219,20 +241,13 @@ public class DeviceApiController implements TbTransportService { | @@ -219,20 +241,13 @@ public class DeviceApiController implements TbTransportService { | ||
219 | .setTenantIdMSB(sessionInfo.getTenantIdMSB()) | 241 | .setTenantIdMSB(sessionInfo.getTenantIdMSB()) |
220 | .setTenantIdLSB(sessionInfo.getTenantIdLSB()) | 242 | .setTenantIdLSB(sessionInfo.getTenantIdLSB()) |
221 | .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) | 243 | .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) |
222 | - .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()).build(); | ||
223 | - transportContext.getTransportService().process(sessionInfo, requestMsg, new GetFirmwareCallback(responseWriter, title, version, chunkSize, chunk)); | 244 | + .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) |
245 | + .setType(firmwareType.name()).build(); | ||
246 | + transportContext.getTransportService().process(sessionInfo, requestMsg, new GetFirmwareCallback(responseWriter, title, version, size, chunk)); | ||
224 | })); | 247 | })); |
225 | return responseWriter; | 248 | return responseWriter; |
226 | } | 249 | } |
227 | 250 | ||
228 | - @RequestMapping(value = "/provision", method = RequestMethod.POST) | ||
229 | - public DeferredResult<ResponseEntity> provisionDevice(@RequestBody String json, HttpServletRequest httpRequest) { | ||
230 | - DeferredResult<ResponseEntity> responseWriter = new DeferredResult<>(); | ||
231 | - transportContext.getTransportService().process(JsonConverter.convertToProvisionRequestMsg(json), | ||
232 | - new DeviceProvisionCallback(responseWriter)); | ||
233 | - return responseWriter; | ||
234 | - } | ||
235 | - | ||
236 | private static class DeviceAuthCallback implements TransportServiceCallback<ValidateDeviceCredentialsResponse> { | 251 | private static class DeviceAuthCallback implements TransportServiceCallback<ValidateDeviceCredentialsResponse> { |
237 | private final TransportContext transportContext; | 252 | private final TransportContext transportContext; |
238 | private final DeferredResult<ResponseEntity> responseWriter; | 253 | private final DeferredResult<ResponseEntity> responseWriter; |
@@ -25,10 +25,13 @@ import org.springframework.beans.factory.annotation.Autowired; | @@ -25,10 +25,13 @@ import org.springframework.beans.factory.annotation.Autowired; | ||
25 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | 25 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
26 | import org.springframework.context.annotation.Bean; | 26 | import org.springframework.context.annotation.Bean; |
27 | import org.springframework.stereotype.Component; | 27 | import org.springframework.stereotype.Component; |
28 | +import org.thingsboard.server.common.data.StringUtils; | ||
28 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapSecurityStore; | 29 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapSecurityStore; |
29 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MInMemoryBootstrapConfigStore; | 30 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MInMemoryBootstrapConfigStore; |
30 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2mDefaultBootstrapSessionManager; | 31 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2mDefaultBootstrapSessionManager; |
31 | -import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContextServer; | 32 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportBootstrapConfig; |
33 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; | ||
34 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper; | ||
32 | 35 | ||
33 | import java.math.BigInteger; | 36 | import java.math.BigInteger; |
34 | import java.security.AlgorithmParameters; | 37 | import java.security.AlgorithmParameters; |
@@ -55,7 +58,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE | @@ -55,7 +58,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE | ||
55 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; | 58 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; |
56 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; | 59 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; |
57 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8; | 60 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8; |
58 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getCoapConfig; | 61 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mNetworkConfig.getCoapConfig; |
59 | 62 | ||
60 | @Slf4j | 63 | @Slf4j |
61 | @Component | 64 | @Component |
@@ -66,10 +69,10 @@ public class LwM2MTransportBootstrapServerConfiguration { | @@ -66,10 +69,10 @@ public class LwM2MTransportBootstrapServerConfiguration { | ||
66 | private boolean pskMode = false; | 69 | private boolean pskMode = false; |
67 | 70 | ||
68 | @Autowired | 71 | @Autowired |
69 | - private LwM2MTransportContextBootstrap contextBs; | 72 | + private LwM2MTransportServerConfig serverConfig; |
70 | 73 | ||
71 | @Autowired | 74 | @Autowired |
72 | - private LwM2mTransportContextServer contextS; | 75 | + private LwM2MTransportContextBootstrap contextBs; |
73 | 76 | ||
74 | @Autowired | 77 | @Autowired |
75 | private LwM2MBootstrapSecurityStore lwM2MBootstrapSecurityStore; | 78 | private LwM2MBootstrapSecurityStore lwM2MBootstrapSecurityStore; |
@@ -81,19 +84,18 @@ public class LwM2MTransportBootstrapServerConfiguration { | @@ -81,19 +84,18 @@ public class LwM2MTransportBootstrapServerConfiguration { | ||
81 | @Bean | 84 | @Bean |
82 | public LeshanBootstrapServer getLeshanBootstrapServer() { | 85 | public LeshanBootstrapServer getLeshanBootstrapServer() { |
83 | log.info("Prepare and start BootstrapServer... PostConstruct"); | 86 | log.info("Prepare and start BootstrapServer... PostConstruct"); |
84 | - return this.getLhBootstrapServer(this.contextBs.getCtxBootStrap().getBootstrapPortNoSec(), this.contextBs.getCtxBootStrap().getBootstrapPortSecurity()); | 87 | + return this.getLhBootstrapServer(this.contextBs.getCtxBootStrap().getPort(), this.contextBs.getCtxBootStrap().getSecurePort()); |
85 | } | 88 | } |
86 | 89 | ||
87 | public LeshanBootstrapServer getLhBootstrapServer(Integer bootstrapPortNoSec, Integer bootstrapSecurePort) { | 90 | public LeshanBootstrapServer getLhBootstrapServer(Integer bootstrapPortNoSec, Integer bootstrapSecurePort) { |
88 | LeshanBootstrapServerBuilder builder = new LeshanBootstrapServerBuilder(); | 91 | LeshanBootstrapServerBuilder builder = new LeshanBootstrapServerBuilder(); |
89 | - builder.setLocalAddress(this.contextBs.getCtxBootStrap().getBootstrapHost(), bootstrapPortNoSec); | ||
90 | - builder.setLocalSecureAddress(this.contextBs.getCtxBootStrap().getBootstrapHostSecurity(), bootstrapSecurePort); | 92 | + builder.setLocalAddress(this.contextBs.getCtxBootStrap().getHost(), bootstrapPortNoSec); |
93 | + builder.setLocalSecureAddress(this.contextBs.getCtxBootStrap().getSecureHost(), bootstrapSecurePort); | ||
91 | 94 | ||
92 | /** Create CoAP Config */ | 95 | /** Create CoAP Config */ |
93 | builder.setCoapConfig(getCoapConfig(bootstrapPortNoSec, bootstrapSecurePort)); | 96 | builder.setCoapConfig(getCoapConfig(bootstrapPortNoSec, bootstrapSecurePort)); |
94 | 97 | ||
95 | /** Define model provider (Create Models )*/ | 98 | /** Define model provider (Create Models )*/ |
96 | -// builder.setModel(new StaticModel(contextS.getLwM2MTransportConfigServer().getModelsValueCommon())); | ||
97 | 99 | ||
98 | /** Create credentials */ | 100 | /** Create credentials */ |
99 | this.setServerWithCredentials(builder); | 101 | this.setServerWithCredentials(builder); |
@@ -107,14 +109,13 @@ public class LwM2MTransportBootstrapServerConfiguration { | @@ -107,14 +109,13 @@ public class LwM2MTransportBootstrapServerConfiguration { | ||
107 | 109 | ||
108 | /** Create and Set DTLS Config */ | 110 | /** Create and Set DTLS Config */ |
109 | DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); | 111 | DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); |
110 | - dtlsConfig.setRecommendedSupportedGroupsOnly(this.contextS.getLwM2MTransportConfigServer().isRecommendedSupportedGroups()); | ||
111 | - dtlsConfig.setRecommendedCipherSuitesOnly(this.contextS.getLwM2MTransportConfigServer().isRecommendedCiphers()); | 112 | + dtlsConfig.setRecommendedSupportedGroupsOnly(serverConfig.isRecommendedSupportedGroups()); |
113 | + dtlsConfig.setRecommendedCipherSuitesOnly(serverConfig.isRecommendedCiphers()); | ||
112 | if (this.pskMode) { | 114 | if (this.pskMode) { |
113 | dtlsConfig.setSupportedCipherSuites( | 115 | dtlsConfig.setSupportedCipherSuites( |
114 | TLS_PSK_WITH_AES_128_CCM_8, | 116 | TLS_PSK_WITH_AES_128_CCM_8, |
115 | TLS_PSK_WITH_AES_128_CBC_SHA256); | 117 | TLS_PSK_WITH_AES_128_CBC_SHA256); |
116 | - } | ||
117 | - else { | 118 | + } else { |
118 | dtlsConfig.setSupportedCipherSuites( | 119 | dtlsConfig.setSupportedCipherSuites( |
119 | TLS_PSK_WITH_AES_128_CCM_8, | 120 | TLS_PSK_WITH_AES_128_CCM_8, |
120 | TLS_PSK_WITH_AES_128_CBC_SHA256, | 121 | TLS_PSK_WITH_AES_128_CBC_SHA256, |
@@ -134,10 +135,10 @@ public class LwM2MTransportBootstrapServerConfiguration { | @@ -134,10 +135,10 @@ public class LwM2MTransportBootstrapServerConfiguration { | ||
134 | 135 | ||
135 | private void setServerWithCredentials(LeshanBootstrapServerBuilder builder) { | 136 | private void setServerWithCredentials(LeshanBootstrapServerBuilder builder) { |
136 | try { | 137 | try { |
137 | - if (this.contextS.getLwM2MTransportConfigServer().getKeyStoreValue() != null) { | ||
138 | - KeyStore keyStoreServer = this.contextS.getLwM2MTransportConfigServer().getKeyStoreValue(); | 138 | + if (serverConfig.getKeyStoreValue() != null) { |
139 | + KeyStore keyStoreServer = serverConfig.getKeyStoreValue(); | ||
139 | if (this.setBuilderX509(builder)) { | 140 | if (this.setBuilderX509(builder)) { |
140 | - X509Certificate rootCAX509Cert = (X509Certificate) keyStoreServer.getCertificate(this.contextS.getLwM2MTransportConfigServer().getRootAlias()); | 141 | + X509Certificate rootCAX509Cert = (X509Certificate) keyStoreServer.getCertificate(serverConfig.getRootCertificateAlias()); |
141 | if (rootCAX509Cert != null) { | 142 | if (rootCAX509Cert != null) { |
142 | X509Certificate[] trustedCertificates = new X509Certificate[1]; | 143 | X509Certificate[] trustedCertificates = new X509Certificate[1]; |
143 | trustedCertificates[0] = rootCAX509Cert; | 144 | trustedCertificates[0] = rootCAX509Cert; |
@@ -168,12 +169,10 @@ public class LwM2MTransportBootstrapServerConfiguration { | @@ -168,12 +169,10 @@ public class LwM2MTransportBootstrapServerConfiguration { | ||
168 | * For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks | 169 | * For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks |
169 | */ | 170 | */ |
170 | try { | 171 | try { |
171 | - X509Certificate serverCertificate = (X509Certificate) this.contextS.getLwM2MTransportConfigServer().getKeyStoreValue().getCertificate(this.contextBs.getCtxBootStrap().getBootstrapAlias()); | ||
172 | - PrivateKey privateKey = (PrivateKey) this.contextS.getLwM2MTransportConfigServer().getKeyStoreValue().getKey(this.contextBs.getCtxBootStrap().getBootstrapAlias(), this.contextS.getLwM2MTransportConfigServer().getKeyStorePasswordServer() == null ? null : this.contextS.getLwM2MTransportConfigServer().getKeyStorePasswordServer().toCharArray()); | 172 | + X509Certificate serverCertificate = (X509Certificate) serverConfig.getKeyStoreValue().getCertificate(this.contextBs.getCtxBootStrap().getCertificateAlias()); |
173 | + PrivateKey privateKey = (PrivateKey) serverConfig.getKeyStoreValue().getKey(this.contextBs.getCtxBootStrap().getCertificateAlias(), serverConfig.getKeyStorePassword() == null ? null : serverConfig.getKeyStorePassword().toCharArray()); | ||
173 | PublicKey publicKey = serverCertificate.getPublicKey(); | 174 | PublicKey publicKey = serverCertificate.getPublicKey(); |
174 | - if (serverCertificate != null && | ||
175 | - privateKey != null && privateKey.getEncoded().length > 0 && | ||
176 | - publicKey != null && publicKey.getEncoded().length > 0) { | 175 | + if (privateKey != null && privateKey.getEncoded().length > 0 && publicKey != null && publicKey.getEncoded().length > 0) { |
177 | builder.setPublicKey(serverCertificate.getPublicKey()); | 176 | builder.setPublicKey(serverCertificate.getPublicKey()); |
178 | builder.setPrivateKey(privateKey); | 177 | builder.setPrivateKey(privateKey); |
179 | builder.setCertificateChain(new X509Certificate[]{serverCertificate}); | 178 | builder.setCertificateChain(new X509Certificate[]{serverCertificate}); |
@@ -200,10 +199,12 @@ public class LwM2MTransportBootstrapServerConfiguration { | @@ -200,10 +199,12 @@ public class LwM2MTransportBootstrapServerConfiguration { | ||
200 | } | 199 | } |
201 | 200 | ||
202 | private void infoPramsUri(String mode) { | 201 | private void infoPramsUri(String mode) { |
203 | - log.info("Bootstrap Server uses [{}]: serverNoSecureURI : [{}], serverSecureURI : [{}]", | 202 | + log.info("Bootstrap Server uses [{}]: serverNoSecureURI : [{}:{}], serverSecureURI : [{}:{}]", |
204 | mode, | 203 | mode, |
205 | - this.contextBs.getCtxBootStrap().getBootstrapHost() + ":" + this.contextBs.getCtxBootStrap().getBootstrapPortNoSec(), | ||
206 | - this.contextBs.getCtxBootStrap().getBootstrapHostSecurity() + ":" + this.contextBs.getCtxBootStrap().getBootstrapPortSecurity()); | 204 | + this.contextBs.getCtxBootStrap().getHost(), |
205 | + this.contextBs.getCtxBootStrap().getPort(), | ||
206 | + this.contextBs.getCtxBootStrap().getSecureHost(), | ||
207 | + this.contextBs.getCtxBootStrap().getSecurePort()); | ||
207 | } | 208 | } |
208 | 209 | ||
209 | 210 | ||
@@ -237,23 +238,25 @@ public class LwM2MTransportBootstrapServerConfiguration { | @@ -237,23 +238,25 @@ public class LwM2MTransportBootstrapServerConfiguration { | ||
237 | AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); | 238 | AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); |
238 | algoParameters.init(new ECGenParameterSpec("secp256r1")); | 239 | algoParameters.init(new ECGenParameterSpec("secp256r1")); |
239 | ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); | 240 | ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); |
240 | - if (this.contextBs.getCtxBootStrap().getBootstrapPublicX() != null && !this.contextBs.getCtxBootStrap().getBootstrapPublicX().isEmpty() && this.contextBs.getCtxBootStrap().getBootstrapPublicY() != null && !this.contextBs.getCtxBootStrap().getBootstrapPublicY().isEmpty()) { | 241 | + LwM2MTransportBootstrapConfig serverConfig = this.contextBs.getCtxBootStrap(); |
242 | + if (StringUtils.isNotEmpty(serverConfig.getPublicX()) && StringUtils.isNotEmpty(serverConfig.getPublicY())) { | ||
241 | /** Get point values */ | 243 | /** Get point values */ |
242 | - byte[] publicX = Hex.decodeHex(this.contextBs.getCtxBootStrap().getBootstrapPublicX().toCharArray()); | ||
243 | - byte[] publicY = Hex.decodeHex(this.contextBs.getCtxBootStrap().getBootstrapPublicY().toCharArray()); | 244 | + byte[] publicX = Hex.decodeHex(serverConfig.getPublicX().toCharArray()); |
245 | + byte[] publicY = Hex.decodeHex(serverConfig.getPublicY().toCharArray()); | ||
244 | /** Create key specs */ | 246 | /** Create key specs */ |
245 | KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), | 247 | KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), |
246 | parameterSpec); | 248 | parameterSpec); |
247 | /** Get public key */ | 249 | /** Get public key */ |
248 | this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); | 250 | this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); |
249 | } | 251 | } |
250 | - if (this.contextBs.getCtxBootStrap().getBootstrapPrivateEncoded() != null && !this.contextBs.getCtxBootStrap().getBootstrapPrivateEncoded().isEmpty()) { | 252 | + String privateEncodedKey = serverConfig.getPrivateEncoded(); |
253 | + if (StringUtils.isNotEmpty(privateEncodedKey)) { | ||
251 | /** Get private key */ | 254 | /** Get private key */ |
252 | - byte[] privateS = Hex.decodeHex(this.contextBs.getCtxBootStrap().getBootstrapPrivateEncoded().toCharArray()); | 255 | + byte[] privateS = Hex.decodeHex(privateEncodedKey.toCharArray()); |
253 | try { | 256 | try { |
254 | this.privateKey = KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(privateS)); | 257 | this.privateKey = KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(privateS)); |
255 | } catch (InvalidKeySpecException ignore2) { | 258 | } catch (InvalidKeySpecException ignore2) { |
256 | - log.error("Invalid Bootstrap Server rpk.PrivateKey.getEncoded () [{}}]. PrivateKey has no EC algorithm", this.contextBs.getCtxBootStrap().getBootstrapPrivateEncoded()); | 259 | + log.error("Invalid Bootstrap Server rpk.PrivateKey.getEncoded () [{}}]. PrivateKey has no EC algorithm", privateEncodedKey); |
257 | } | 260 | } |
258 | } | 261 | } |
259 | } | 262 | } |
@@ -34,7 +34,7 @@ import lombok.extern.slf4j.Slf4j; | @@ -34,7 +34,7 @@ import lombok.extern.slf4j.Slf4j; | ||
34 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | 34 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
35 | import org.springframework.stereotype.Component; | 35 | import org.springframework.stereotype.Component; |
36 | import org.thingsboard.server.common.transport.TransportContext; | 36 | import org.thingsboard.server.common.transport.TransportContext; |
37 | -import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstrap; | 37 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportBootstrapConfig; |
38 | 38 | ||
39 | 39 | ||
40 | @Slf4j | 40 | @Slf4j |
@@ -42,13 +42,13 @@ import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstr | @@ -42,13 +42,13 @@ import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstr | ||
42 | @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith'") | 42 | @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith'") |
43 | public class LwM2MTransportContextBootstrap extends TransportContext { | 43 | public class LwM2MTransportContextBootstrap extends TransportContext { |
44 | 44 | ||
45 | - private final LwM2MTransportConfigBootstrap lwM2MTransportConfigBootstrap; | 45 | + private final LwM2MTransportBootstrapConfig lwM2MTransportBootstrapConfig; |
46 | 46 | ||
47 | - public LwM2MTransportContextBootstrap(LwM2MTransportConfigBootstrap ctxBootStrap) { | ||
48 | - this.lwM2MTransportConfigBootstrap = ctxBootStrap; | 47 | + public LwM2MTransportContextBootstrap(LwM2MTransportBootstrapConfig ctxBootStrap) { |
48 | + this.lwM2MTransportBootstrapConfig = ctxBootStrap; | ||
49 | } | 49 | } |
50 | 50 | ||
51 | - public LwM2MTransportConfigBootstrap getCtxBootStrap() { | ||
52 | - return this.lwM2MTransportConfigBootstrap; | 51 | + public LwM2MTransportBootstrapConfig getCtxBootStrap() { |
52 | + return this.lwM2MTransportBootstrapConfig; | ||
53 | } | 53 | } |
54 | } | 54 | } |
@@ -34,8 +34,9 @@ import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; | @@ -34,8 +34,9 @@ import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; | ||
34 | import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; | 34 | import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; |
35 | import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore; | 35 | import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore; |
36 | import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener; | 36 | import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener; |
37 | -import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContextServer; | ||
38 | -import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler; | 37 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; |
38 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper; | ||
39 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil; | ||
39 | 40 | ||
40 | import java.io.IOException; | 41 | import java.io.IOException; |
41 | import java.security.GeneralSecurityException; | 42 | import java.security.GeneralSecurityException; |
@@ -43,12 +44,12 @@ import java.util.Collections; | @@ -43,12 +44,12 @@ import java.util.Collections; | ||
43 | import java.util.List; | 44 | import java.util.List; |
44 | import java.util.UUID; | 45 | import java.util.UUID; |
45 | 46 | ||
46 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.BOOTSTRAP_SERVER; | ||
47 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR; | ||
48 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO; | ||
49 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LWM2M_SERVER; | ||
50 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.SERVERS; | ||
51 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getBootstrapParametersFromThingsboard; | 47 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.BOOTSTRAP_SERVER; |
48 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LOG_LW2M_ERROR; | ||
49 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LOG_LW2M_INFO; | ||
50 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LWM2M_SERVER; | ||
51 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.SERVERS; | ||
52 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.getBootstrapParametersFromThingsboard; | ||
52 | 53 | ||
53 | @Slf4j | 54 | @Slf4j |
54 | @Service("LwM2MBootstrapSecurityStore") | 55 | @Service("LwM2MBootstrapSecurityStore") |
@@ -59,17 +60,19 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { | @@ -59,17 +60,19 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { | ||
59 | 60 | ||
60 | private final LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator; | 61 | private final LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator; |
61 | 62 | ||
62 | - private final LwM2mTransportContextServer context; | 63 | + private final LwM2mTransportContext context; |
64 | + private final LwM2mTransportServerHelper helper; | ||
63 | 65 | ||
64 | - public LwM2MBootstrapSecurityStore(EditableBootstrapConfigStore bootstrapConfigStore, LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator, LwM2mTransportContextServer context) { | 66 | + public LwM2MBootstrapSecurityStore(EditableBootstrapConfigStore bootstrapConfigStore, LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator, LwM2mTransportContext context, LwM2mTransportServerHelper helper) { |
65 | this.bootstrapConfigStore = bootstrapConfigStore; | 67 | this.bootstrapConfigStore = bootstrapConfigStore; |
66 | this.lwM2MCredentialsSecurityInfoValidator = lwM2MCredentialsSecurityInfoValidator; | 68 | this.lwM2MCredentialsSecurityInfoValidator = lwM2MCredentialsSecurityInfoValidator; |
67 | this.context = context; | 69 | this.context = context; |
70 | + this.helper = helper; | ||
68 | } | 71 | } |
69 | 72 | ||
70 | @Override | 73 | @Override |
71 | public List<SecurityInfo> getAllByEndpoint(String endPoint) { | 74 | public List<SecurityInfo> getAllByEndpoint(String endPoint) { |
72 | - ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(endPoint, LwM2mTransportHandler.LwM2mTypeServer.BOOTSTRAP); | 75 | + ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(endPoint, LwM2mTransportHandlerUtil.LwM2mTypeServer.BOOTSTRAP); |
73 | if (store.getBootstrapJsonCredential() != null && store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { | 76 | if (store.getBootstrapJsonCredential() != null && store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { |
74 | /** add value to store from BootstrapJson */ | 77 | /** add value to store from BootstrapJson */ |
75 | this.setBootstrapConfigScurityInfo(store); | 78 | this.setBootstrapConfigScurityInfo(store); |
@@ -93,7 +96,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { | @@ -93,7 +96,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { | ||
93 | 96 | ||
94 | @Override | 97 | @Override |
95 | public SecurityInfo getByIdentity(String identity) { | 98 | public SecurityInfo getByIdentity(String identity) { |
96 | - ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(identity, LwM2mTransportHandler.LwM2mTypeServer.BOOTSTRAP); | 99 | + ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(identity, LwM2mTransportHandlerUtil.LwM2mTypeServer.BOOTSTRAP); |
97 | if (store.getBootstrapJsonCredential() != null && store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { | 100 | if (store.getBootstrapJsonCredential() != null && store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { |
98 | /** add value to store from BootstrapJson */ | 101 | /** add value to store from BootstrapJson */ |
99 | this.setBootstrapConfigScurityInfo(store); | 102 | this.setBootstrapConfigScurityInfo(store); |
@@ -158,19 +161,19 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { | @@ -158,19 +161,19 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { | ||
158 | LwM2MServerBootstrap profileServerBootstrap = mapper.readValue(bootstrapObject.get(BOOTSTRAP_SERVER).toString(), LwM2MServerBootstrap.class); | 161 | LwM2MServerBootstrap profileServerBootstrap = mapper.readValue(bootstrapObject.get(BOOTSTRAP_SERVER).toString(), LwM2MServerBootstrap.class); |
159 | LwM2MServerBootstrap profileLwm2mServer = mapper.readValue(bootstrapObject.get(LWM2M_SERVER).toString(), LwM2MServerBootstrap.class); | 162 | LwM2MServerBootstrap profileLwm2mServer = mapper.readValue(bootstrapObject.get(LWM2M_SERVER).toString(), LwM2MServerBootstrap.class); |
160 | UUID sessionUUiD = UUID.randomUUID(); | 163 | UUID sessionUUiD = UUID.randomUUID(); |
161 | - TransportProtos.SessionInfoProto sessionInfo = context.getValidateSessionInfo(store.getMsg(), sessionUUiD.getMostSignificantBits(), sessionUUiD.getLeastSignificantBits()); | 164 | + TransportProtos.SessionInfoProto sessionInfo = helper.getValidateSessionInfo(store.getMsg(), sessionUUiD.getMostSignificantBits(), sessionUUiD.getLeastSignificantBits()); |
162 | context.getTransportService().registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(null, sessionInfo)); | 165 | context.getTransportService().registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(null, sessionInfo)); |
163 | if (this.getValidatedSecurityMode(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap, lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer)) { | 166 | if (this.getValidatedSecurityMode(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap, lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer)) { |
164 | lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap); | 167 | lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap); |
165 | lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer); | 168 | lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer); |
166 | String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LW2M_INFO, store.getEndPoint()); | 169 | String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LW2M_INFO, store.getEndPoint()); |
167 | - context.sendParametersOnThingsboardTelemetry(context.getKvLogyToThingsboard(logMsg), sessionInfo); | 170 | + helper.sendParametersOnThingsboardTelemetry(helper.getKvLogyToThingsboard(logMsg), sessionInfo); |
168 | return lwM2MBootstrapConfig; | 171 | return lwM2MBootstrapConfig; |
169 | } else { | 172 | } else { |
170 | log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndPoint()); | 173 | log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndPoint()); |
171 | log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint()); | 174 | log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint()); |
172 | String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint()); | 175 | String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint()); |
173 | - context.sendParametersOnThingsboardTelemetry(context.getKvLogyToThingsboard(logMsg), sessionInfo); | 176 | + helper.sendParametersOnThingsboardTelemetry(helper.getKvLogyToThingsboard(logMsg), sessionInfo); |
174 | return null; | 177 | return null; |
175 | } | 178 | } |
176 | } | 179 | } |
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.client; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | + | ||
20 | +import java.util.UUID; | ||
21 | + | ||
22 | +@Data | ||
23 | +public class LwM2mSoftwareUpdate { | ||
24 | + private volatile String clientSwVersion; | ||
25 | + private volatile String currentSwVersion; | ||
26 | + private volatile UUID currentSwId; | ||
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.config; | ||
17 | + | ||
18 | +public interface LwM2MSecureServerConfig { | ||
19 | + | ||
20 | + Integer getId(); | ||
21 | + | ||
22 | + String getHost(); | ||
23 | + | ||
24 | + Integer getPort(); | ||
25 | + | ||
26 | + String getSecureHost(); | ||
27 | + | ||
28 | + Integer getSecurePort(); | ||
29 | + | ||
30 | + String getPublicX(); | ||
31 | + | ||
32 | + String getPublicY(); | ||
33 | + | ||
34 | + String getPrivateEncoded(); | ||
35 | + | ||
36 | + String getCertificateAlias(); | ||
37 | + | ||
38 | +} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportBootstrapConfig.java
renamed from
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigBootstrap.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.common.transport.lwm2m; | 16 | +package org.thingsboard.server.transport.lwm2m.config; |
17 | 17 | ||
18 | import lombok.Getter; | 18 | import lombok.Getter; |
19 | import lombok.Setter; | 19 | import lombok.Setter; |
@@ -29,53 +29,42 @@ import java.util.Map; | @@ -29,53 +29,42 @@ import java.util.Map; | ||
29 | @Slf4j | 29 | @Slf4j |
30 | @Component | 30 | @Component |
31 | @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core'") | 31 | @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core'") |
32 | -public class LwM2MTransportConfigBootstrap { | ||
33 | - | ||
34 | - @Getter | ||
35 | - @Value("${transport.lwm2m.bootstrap.enable:}") | ||
36 | - private Boolean bootstrapEnable; | 32 | +public class LwM2MTransportBootstrapConfig implements LwM2MSecureServerConfig { |
37 | 33 | ||
38 | @Getter | 34 | @Getter |
39 | @Value("${transport.lwm2m.bootstrap.id:}") | 35 | @Value("${transport.lwm2m.bootstrap.id:}") |
40 | - private Integer bootstrapServerId; | 36 | + private Integer id; |
41 | 37 | ||
42 | @Getter | 38 | @Getter |
43 | @Value("${transport.lwm2m.bootstrap.bind_address:}") | 39 | @Value("${transport.lwm2m.bootstrap.bind_address:}") |
44 | - private String bootstrapHost; | 40 | + private String host; |
45 | 41 | ||
46 | @Getter | 42 | @Getter |
47 | - @Value("${transport.lwm2m.bootstrap.bind_port_no_sec:}") | ||
48 | - private Integer bootstrapPortNoSec; | 43 | + @Value("${transport.lwm2m.bootstrap.bind_port:}") |
44 | + private Integer port; | ||
49 | 45 | ||
50 | @Getter | 46 | @Getter |
51 | - @Value("${transport.lwm2m.bootstrap.secure.bind_address_security:}") | ||
52 | - private String bootstrapHostSecurity; | 47 | + @Value("${transport.lwm2m.bootstrap.security.bind_address:}") |
48 | + private String secureHost; | ||
53 | 49 | ||
54 | @Getter | 50 | @Getter |
55 | - @Value("${transport.lwm2m.bootstrap.secure.bind_port_security:}") | ||
56 | - private Integer bootstrapPortSecurity; | 51 | + @Value("${transport.lwm2m.bootstrap.security.bind_port:}") |
52 | + private Integer securePort; | ||
57 | 53 | ||
58 | @Getter | 54 | @Getter |
59 | - @Value("${transport.lwm2m.bootstrap.secure.public_x:}") | ||
60 | - private String bootstrapPublicX; | 55 | + @Value("${transport.lwm2m.bootstrap.security.public_x:}") |
56 | + private String publicX; | ||
61 | 57 | ||
62 | @Getter | 58 | @Getter |
63 | - @Value("${transport.lwm2m.bootstrap.secure.public_y:}") | ||
64 | - private String bootstrapPublicY; | 59 | + @Value("${transport.lwm2m.bootstrap.security.public_y:}") |
60 | + private String publicY; | ||
65 | 61 | ||
66 | @Getter | 62 | @Getter |
67 | - @Setter | ||
68 | - private PublicKey bootstrapPublicKey; | 63 | + @Value("${transport.lwm2m.bootstrap.security.private_encoded:}") |
64 | + private String privateEncoded; | ||
69 | 65 | ||
70 | @Getter | 66 | @Getter |
71 | - @Value("${transport.lwm2m.bootstrap.secure.private_encoded:}") | ||
72 | - private String bootstrapPrivateEncoded; | 67 | + @Value("${transport.lwm2m.bootstrap.security.alias:}") |
68 | + private String certificateAlias; | ||
73 | 69 | ||
74 | - @Getter | ||
75 | - @Value("${transport.lwm2m.bootstrap.secure.alias:}") | ||
76 | - private String bootstrapAlias; | ||
77 | - | ||
78 | - @Getter | ||
79 | - @Setter | ||
80 | - private Map<String /** clientEndPoint */, TransportProtos.ValidateDeviceCredentialsResponseMsg> sessions; | ||
81 | } | 70 | } |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java
renamed from
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java
@@ -13,8 +13,9 @@ | @@ -13,8 +13,9 @@ | ||
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.common.transport.lwm2m; | 16 | +package org.thingsboard.server.transport.lwm2m.config; |
17 | 17 | ||
18 | +import com.google.common.io.Resources; | ||
18 | import lombok.Getter; | 19 | import lombok.Getter; |
19 | import lombok.Setter; | 20 | import lombok.Setter; |
20 | import lombok.extern.slf4j.Slf4j; | 21 | import lombok.extern.slf4j.Slf4j; |
@@ -28,6 +29,7 @@ import java.io.File; | @@ -28,6 +29,7 @@ import java.io.File; | ||
28 | import java.io.FileInputStream; | 29 | import java.io.FileInputStream; |
29 | import java.io.IOException; | 30 | import java.io.IOException; |
30 | import java.io.InputStream; | 31 | import java.io.InputStream; |
32 | +import java.net.URI; | ||
31 | import java.nio.file.Path; | 33 | import java.nio.file.Path; |
32 | import java.nio.file.Paths; | 34 | import java.nio.file.Paths; |
33 | import java.security.KeyStore; | 35 | import java.security.KeyStore; |
@@ -38,38 +40,7 @@ import java.security.cert.CertificateException; | @@ -38,38 +40,7 @@ import java.security.cert.CertificateException; | ||
38 | @Slf4j | 40 | @Slf4j |
39 | @Component | 41 | @Component |
40 | @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core'") | 42 | @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core'") |
41 | -public class LwM2MTransportConfigServer { | ||
42 | - | ||
43 | - @Getter | ||
44 | - private String KEY_STORE_DEFAULT_RESOURCE_PATH = "credentials"; | ||
45 | - | ||
46 | - @Getter | ||
47 | - private String KEY_STORE_DEFAULT_FILE = "serverKeyStore.jks"; | ||
48 | - | ||
49 | - @Getter | ||
50 | - private String APP_DIR = "common"; | ||
51 | - | ||
52 | - @Getter | ||
53 | - private String TRANSPORT_DIR = "transport"; | ||
54 | - | ||
55 | - @Getter | ||
56 | - private String LWM2M_DIR = "lwm2m"; | ||
57 | - | ||
58 | - @Getter | ||
59 | - private String SRC_DIR = "src"; | ||
60 | - | ||
61 | - @Getter | ||
62 | - private String MAIN_DIR = "main"; | ||
63 | - | ||
64 | - @Getter | ||
65 | - private String RESOURCES_DIR = "resources"; | ||
66 | - | ||
67 | - @Getter | ||
68 | - private String BASE_DIR_PATH = System.getProperty("user.dir"); | ||
69 | - | ||
70 | - @Getter | ||
71 | - // private String PATH_DATA_MICROSERVICE = "/usr/share/tb-lwm2m-transport/data$"; | ||
72 | - private String PATH_DATA = "data"; | 43 | +public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { |
73 | 44 | ||
74 | @Getter | 45 | @Getter |
75 | @Setter | 46 | @Setter |
@@ -108,11 +79,11 @@ public class LwM2MTransportConfigServer { | @@ -108,11 +79,11 @@ public class LwM2MTransportConfigServer { | ||
108 | private int unRegisteredPoolSize; | 79 | private int unRegisteredPoolSize; |
109 | 80 | ||
110 | @Getter | 81 | @Getter |
111 | - @Value("${transport.lwm2m.secure.key_store_type:}") | 82 | + @Value("${transport.lwm2m.security.key_store_type:}") |
112 | private String keyStoreType; | 83 | private String keyStoreType; |
113 | 84 | ||
114 | @Getter | 85 | @Getter |
115 | - @Value("${transport.lwm2m.secure.key_store_path_file:}") | 86 | + @Value("${transport.lwm2m.security.key_store:}") |
116 | private String keyStorePathFile; | 87 | private String keyStorePathFile; |
117 | 88 | ||
118 | @Getter | 89 | @Getter |
@@ -120,98 +91,72 @@ public class LwM2MTransportConfigServer { | @@ -120,98 +91,72 @@ public class LwM2MTransportConfigServer { | ||
120 | private KeyStore keyStoreValue; | 91 | private KeyStore keyStoreValue; |
121 | 92 | ||
122 | @Getter | 93 | @Getter |
123 | - @Value("${transport.lwm2m.secure.key_store_password:}") | ||
124 | - private String keyStorePasswordServer; | 94 | + @Value("${transport.lwm2m.security.key_store_password:}") |
95 | + private String keyStorePassword; | ||
125 | 96 | ||
126 | @Getter | 97 | @Getter |
127 | - @Value("${transport.lwm2m.secure.root_alias:}") | ||
128 | - private String rootAlias; | 98 | + @Value("${transport.lwm2m.security.root_alias:}") |
99 | + private String rootCertificateAlias; | ||
129 | 100 | ||
130 | @Getter | 101 | @Getter |
131 | - @Value("${transport.lwm2m.secure.enable_gen_new_key_psk_rpk:}") | 102 | + @Value("${transport.lwm2m.security.enable_gen_new_key_psk_rpk:}") |
132 | private Boolean enableGenNewKeyPskRpk; | 103 | private Boolean enableGenNewKeyPskRpk; |
133 | 104 | ||
134 | @Getter | 105 | @Getter |
135 | @Value("${transport.lwm2m.server.id:}") | 106 | @Value("${transport.lwm2m.server.id:}") |
136 | - private Integer serverId; | 107 | + private Integer id; |
137 | 108 | ||
138 | @Getter | 109 | @Getter |
139 | @Value("${transport.lwm2m.server.bind_address:}") | 110 | @Value("${transport.lwm2m.server.bind_address:}") |
140 | - private String serverHost; | 111 | + private String host; |
112 | + | ||
113 | + @Getter | ||
114 | + @Value("${transport.lwm2m.server.bind_port:}") | ||
115 | + private Integer port; | ||
141 | 116 | ||
142 | @Getter | 117 | @Getter |
143 | - @Value("${transport.lwm2m.server.secure.bind_address_security:}") | ||
144 | - private String serverHostSecurity; | 118 | + @Value("${transport.lwm2m.server.security.bind_address:}") |
119 | + private String secureHost; | ||
145 | 120 | ||
146 | @Getter | 121 | @Getter |
147 | - @Value("${transport.lwm2m.server.bind_port_no_sec:}") | ||
148 | - private Integer serverPortNoSec; | 122 | + @Value("${transport.lwm2m.server.security.bind_port:}") |
123 | + private Integer securePort; | ||
149 | 124 | ||
150 | @Getter | 125 | @Getter |
151 | - @Value("${transport.lwm2m.server.secure.bind_port_security:}") | ||
152 | - private Integer serverPortSecurity; | 126 | + @Value("${transport.lwm2m.server.security.public_x:}") |
127 | + private String publicX; | ||
153 | 128 | ||
154 | @Getter | 129 | @Getter |
155 | - @Value("${transport.lwm2m.server.secure.public_x:}") | ||
156 | - private String serverPublicX; | 130 | + @Value("${transport.lwm2m.server.security.public_y:}") |
131 | + private String publicY; | ||
157 | 132 | ||
158 | @Getter | 133 | @Getter |
159 | - @Value("${transport.lwm2m.server.secure.public_y:}") | ||
160 | - private String serverPublicY; | 134 | + @Value("${transport.lwm2m.server.security.private_encoded:}") |
135 | + private String privateEncoded; | ||
161 | 136 | ||
162 | @Getter | 137 | @Getter |
163 | - @Value("${transport.lwm2m.server.secure.private_encoded:}") | ||
164 | - private String serverPrivateEncoded; | 138 | + @Value("${transport.lwm2m.server.security.alias:}") |
139 | + private String certificateAlias; | ||
165 | 140 | ||
166 | @Getter | 141 | @Getter |
167 | - @Value("${transport.lwm2m.server.secure.alias:}") | ||
168 | - private String serverAlias; | 142 | + @Value("${transport.lwm2m.log_max_length:}") |
143 | + private int logMaxLength; | ||
144 | + | ||
169 | 145 | ||
170 | @PostConstruct | 146 | @PostConstruct |
171 | public void init() { | 147 | public void init() { |
172 | - this.getInKeyStore(); | ||
173 | - } | ||
174 | - | ||
175 | - private KeyStore getInKeyStore() { | 148 | + URI uri = null; |
176 | try { | 149 | try { |
177 | - if (keyStoreValue != null && keyStoreValue.size() > 0) | ||
178 | - return keyStoreValue; | ||
179 | - } catch (KeyStoreException e) { | ||
180 | - log.error("Uninitialized keystore [{}]", keyStoreValue.toString()); | ||
181 | - } | ||
182 | - Path keyStorePath = (keyStorePathFile != null && !keyStorePathFile.isEmpty()) ? Paths.get(keyStorePathFile) : | ||
183 | - (new File(Paths.get(getBaseDirPath(), PATH_DATA, KEY_STORE_DEFAULT_RESOURCE_PATH, KEY_STORE_DEFAULT_FILE).toUri()).isFile()) ? | ||
184 | - Paths.get(getBaseDirPath(), PATH_DATA, KEY_STORE_DEFAULT_RESOURCE_PATH, KEY_STORE_DEFAULT_FILE) : | ||
185 | - Paths.get(getBaseDirPath(), APP_DIR, TRANSPORT_DIR, LWM2M_DIR, SRC_DIR, MAIN_DIR, RESOURCES_DIR, KEY_STORE_DEFAULT_RESOURCE_PATH, KEY_STORE_DEFAULT_FILE); | ||
186 | - File keyStoreFile = new File(keyStorePath.toUri()); | ||
187 | - if (keyStoreFile.isFile()) { | ||
188 | - try { | ||
189 | - InputStream inKeyStore = new FileInputStream(keyStoreFile); | ||
190 | - keyStoreValue = KeyStore.getInstance(keyStoreType); | ||
191 | - keyStoreValue.load(inKeyStore, keyStorePasswordServer == null ? null : keyStorePasswordServer.toCharArray()); | ||
192 | - } catch (CertificateException | NoSuchAlgorithmException | IOException | KeyStoreException e) { | ||
193 | - log.error("[{}] Unable to load KeyStore files server, folder is not a directory", e.getMessage()); | ||
194 | - keyStoreValue = null; | ||
195 | - } | ||
196 | - log.info("[{}] Load KeyStore files server, folder is a directory", keyStoreFile.getAbsoluteFile()); | ||
197 | - } else { | ||
198 | - log.error("[{}] Unable to load KeyStore files server, is not a file", keyStoreFile.getAbsoluteFile()); | ||
199 | - keyStoreValue = null; | ||
200 | - } | ||
201 | - return keyStoreValue; | ||
202 | - } | ||
203 | - | ||
204 | - private String getBaseDirPath() { | ||
205 | - Path FULL_FILE_PATH; | ||
206 | - if (BASE_DIR_PATH.endsWith("bin")) { | ||
207 | - FULL_FILE_PATH = Paths.get(BASE_DIR_PATH.replaceAll("bin$", "")); | ||
208 | - } else if (BASE_DIR_PATH.endsWith("conf")) { | ||
209 | - FULL_FILE_PATH = Paths.get(BASE_DIR_PATH.replaceAll("conf$", "")); | ||
210 | - } else if (BASE_DIR_PATH.endsWith("application")) { | ||
211 | - FULL_FILE_PATH = Paths.get(BASE_DIR_PATH.substring(0, BASE_DIR_PATH.length() - "application".length())); | ||
212 | - } else { | ||
213 | - FULL_FILE_PATH = Paths.get(BASE_DIR_PATH); | 150 | + uri = Resources.getResource(keyStorePathFile).toURI(); |
151 | + log.error("URI: {}", uri); | ||
152 | + File keyStoreFile = new File(uri); | ||
153 | + InputStream inKeyStore = new FileInputStream(keyStoreFile); | ||
154 | + keyStoreValue = KeyStore.getInstance(keyStoreType); | ||
155 | + keyStoreValue.load(inKeyStore, keyStorePassword == null ? null : keyStorePassword.toCharArray()); | ||
156 | + } catch (Exception e) { | ||
157 | + log.warn("Unable to lookup LwM2M keystore. Reason: {}, {}" , uri, e.getMessage()); | ||
158 | +// Absence of the key store should not block user from using plain LwM2M | ||
159 | +// throw new RuntimeException("Failed to lookup LwM2M keystore: " + (uri != null ? uri.toString() : ""), e); | ||
214 | } | 160 | } |
215 | - return FULL_FILE_PATH.toUri().getPath(); | ||
216 | } | 161 | } |
217 | } | 162 | } |
@@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
16 | package org.thingsboard.server.transport.lwm2m.secure; | 16 | package org.thingsboard.server.transport.lwm2m.secure; |
17 | 17 | ||
18 | import com.google.gson.JsonObject; | 18 | import com.google.gson.JsonObject; |
19 | +import lombok.RequiredArgsConstructor; | ||
19 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
20 | import org.eclipse.leshan.core.util.Hex; | 21 | import org.eclipse.leshan.core.util.Hex; |
21 | import org.eclipse.leshan.core.util.SecurityUtil; | 22 | import org.eclipse.leshan.core.util.SecurityUtil; |
@@ -26,8 +27,10 @@ import org.thingsboard.server.common.transport.TransportServiceCallback; | @@ -26,8 +27,10 @@ import org.thingsboard.server.common.transport.TransportServiceCallback; | ||
26 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; | 27 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; |
27 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; | 28 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; |
28 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | 29 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
29 | -import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContextServer; | ||
30 | -import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler; | 30 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; |
31 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; | ||
32 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper; | ||
33 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil; | ||
31 | 34 | ||
32 | import java.io.IOException; | 35 | import java.io.IOException; |
33 | import java.security.GeneralSecurityException; | 36 | import java.security.GeneralSecurityException; |
@@ -44,13 +47,11 @@ import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.X5 | @@ -44,13 +47,11 @@ import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.X5 | ||
44 | @Slf4j | 47 | @Slf4j |
45 | @Component | 48 | @Component |
46 | @TbLwM2mTransportComponent | 49 | @TbLwM2mTransportComponent |
50 | +@RequiredArgsConstructor | ||
47 | public class LwM2mCredentialsSecurityInfoValidator { | 51 | public class LwM2mCredentialsSecurityInfoValidator { |
48 | 52 | ||
49 | - private final LwM2mTransportContextServer contextS; | ||
50 | - | ||
51 | - public LwM2mCredentialsSecurityInfoValidator(LwM2mTransportContextServer contextS) { | ||
52 | - this.contextS = contextS; | ||
53 | - } | 53 | + private final LwM2mTransportContext context; |
54 | + private final LwM2MTransportServerConfig config; | ||
54 | 55 | ||
55 | /** | 56 | /** |
56 | * Request to thingsboard Response from thingsboard ValidateDeviceLwM2MCredentials | 57 | * Request to thingsboard Response from thingsboard ValidateDeviceLwM2MCredentials |
@@ -58,17 +59,17 @@ public class LwM2mCredentialsSecurityInfoValidator { | @@ -58,17 +59,17 @@ public class LwM2mCredentialsSecurityInfoValidator { | ||
58 | * @param keyValue - | 59 | * @param keyValue - |
59 | * @return ValidateDeviceCredentialsResponseMsg and SecurityInfo | 60 | * @return ValidateDeviceCredentialsResponseMsg and SecurityInfo |
60 | */ | 61 | */ |
61 | - public ReadResultSecurityStore createAndValidateCredentialsSecurityInfo(String endpoint, LwM2mTransportHandler.LwM2mTypeServer keyValue) { | 62 | + public ReadResultSecurityStore createAndValidateCredentialsSecurityInfo(String endpoint, LwM2mTransportHandlerUtil.LwM2mTypeServer keyValue) { |
62 | CountDownLatch latch = new CountDownLatch(1); | 63 | CountDownLatch latch = new CountDownLatch(1); |
63 | final ReadResultSecurityStore[] resultSecurityStore = new ReadResultSecurityStore[1]; | 64 | final ReadResultSecurityStore[] resultSecurityStore = new ReadResultSecurityStore[1]; |
64 | - contextS.getTransportService().process(ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(endpoint).build(), | 65 | + context.getTransportService().process(ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(endpoint).build(), |
65 | new TransportServiceCallback<>() { | 66 | new TransportServiceCallback<>() { |
66 | @Override | 67 | @Override |
67 | public void onSuccess(ValidateDeviceCredentialsResponseMsg msg) { | 68 | public void onSuccess(ValidateDeviceCredentialsResponseMsg msg) { |
68 | String credentialsBody = msg.getCredentialsBody(); | 69 | String credentialsBody = msg.getCredentialsBody(); |
69 | resultSecurityStore[0] = createSecurityInfo(endpoint, credentialsBody, keyValue); | 70 | resultSecurityStore[0] = createSecurityInfo(endpoint, credentialsBody, keyValue); |
70 | resultSecurityStore[0].setMsg(msg); | 71 | resultSecurityStore[0].setMsg(msg); |
71 | - Optional<DeviceProfile> deviceProfileOpt = LwM2mTransportHandler.decode(msg.getProfileBody().toByteArray()); | 72 | + Optional<DeviceProfile> deviceProfileOpt = LwM2mTransportHandlerUtil.decode(msg.getProfileBody().toByteArray()); |
72 | deviceProfileOpt.ifPresent(profile -> resultSecurityStore[0].setDeviceProfile(profile)); | 73 | deviceProfileOpt.ifPresent(profile -> resultSecurityStore[0].setDeviceProfile(profile)); |
73 | latch.countDown(); | 74 | latch.countDown(); |
74 | } | 75 | } |
@@ -81,7 +82,7 @@ public class LwM2mCredentialsSecurityInfoValidator { | @@ -81,7 +82,7 @@ public class LwM2mCredentialsSecurityInfoValidator { | ||
81 | } | 82 | } |
82 | }); | 83 | }); |
83 | try { | 84 | try { |
84 | - latch.await(contextS.getLwM2MTransportConfigServer().getTimeout(), TimeUnit.MILLISECONDS); | 85 | + latch.await(config.getTimeout(), TimeUnit.MILLISECONDS); |
85 | } catch (InterruptedException e) { | 86 | } catch (InterruptedException e) { |
86 | log.error("Failed to await credentials!", e); | 87 | log.error("Failed to await credentials!", e); |
87 | } | 88 | } |
@@ -95,9 +96,9 @@ public class LwM2mCredentialsSecurityInfoValidator { | @@ -95,9 +96,9 @@ public class LwM2mCredentialsSecurityInfoValidator { | ||
95 | * @param keyValue - | 96 | * @param keyValue - |
96 | * @return SecurityInfo | 97 | * @return SecurityInfo |
97 | */ | 98 | */ |
98 | - private ReadResultSecurityStore createSecurityInfo(String endPoint, String jsonStr, LwM2mTransportHandler.LwM2mTypeServer keyValue) { | 99 | + private ReadResultSecurityStore createSecurityInfo(String endPoint, String jsonStr, LwM2mTransportHandlerUtil.LwM2mTypeServer keyValue) { |
99 | ReadResultSecurityStore result = new ReadResultSecurityStore(); | 100 | ReadResultSecurityStore result = new ReadResultSecurityStore(); |
100 | - JsonObject objectMsg = LwM2mTransportHandler.validateJson(jsonStr); | 101 | + JsonObject objectMsg = LwM2mTransportHandlerUtil.validateJson(jsonStr); |
101 | if (objectMsg != null && !objectMsg.isJsonNull()) { | 102 | if (objectMsg != null && !objectMsg.isJsonNull()) { |
102 | JsonObject object = (objectMsg.has(keyValue.type) && !objectMsg.get(keyValue.type).isJsonNull()) ? objectMsg.get(keyValue.type).getAsJsonObject() : null; | 103 | JsonObject object = (objectMsg.has(keyValue.type) && !objectMsg.get(keyValue.type).isJsonNull()) ? objectMsg.get(keyValue.type).getAsJsonObject() : null; |
103 | /** | 104 | /** |
@@ -108,7 +109,7 @@ public class LwM2mCredentialsSecurityInfoValidator { | @@ -108,7 +109,7 @@ public class LwM2mCredentialsSecurityInfoValidator { | ||
108 | && objectMsg.get("client").getAsJsonObject().get("endpoint").isJsonPrimitive()) ? objectMsg.get("client").getAsJsonObject().get("endpoint").getAsString() : null; | 109 | && objectMsg.get("client").getAsJsonObject().get("endpoint").isJsonPrimitive()) ? objectMsg.get("client").getAsJsonObject().get("endpoint").getAsString() : null; |
109 | endPoint = (endPointPsk == null || endPointPsk.isEmpty()) ? endPoint : endPointPsk; | 110 | endPoint = (endPointPsk == null || endPointPsk.isEmpty()) ? endPoint : endPointPsk; |
110 | if (object != null && !object.isJsonNull()) { | 111 | if (object != null && !object.isJsonNull()) { |
111 | - if (keyValue.equals(LwM2mTransportHandler.LwM2mTypeServer.BOOTSTRAP)) { | 112 | + if (keyValue.equals(LwM2mTransportHandlerUtil.LwM2mTypeServer.BOOTSTRAP)) { |
112 | result.setBootstrapJsonCredential(object); | 113 | result.setBootstrapJsonCredential(object); |
113 | result.setEndPoint(endPoint); | 114 | result.setEndPoint(endPoint); |
114 | result.setSecurityMode(LwM2MSecurityMode.fromSecurityMode(object.get("bootstrapServer").getAsJsonObject().get("securityMode").getAsString().toLowerCase()).code); | 115 | result.setSecurityMode(LwM2MSecurityMode.fromSecurityMode(object.get("bootstrapServer").getAsJsonObject().get("securityMode").getAsString().toLowerCase()).code); |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java
@@ -38,10 +38,15 @@ import org.eclipse.leshan.server.registration.Registration; | @@ -38,10 +38,15 @@ import org.eclipse.leshan.server.registration.Registration; | ||
38 | import org.springframework.context.annotation.Lazy; | 38 | import org.springframework.context.annotation.Lazy; |
39 | import org.springframework.stereotype.Service; | 39 | import org.springframework.stereotype.Service; |
40 | import org.thingsboard.common.util.JacksonUtil; | 40 | import org.thingsboard.common.util.JacksonUtil; |
41 | +import org.thingsboard.server.cache.firmware.FirmwareDataCache; | ||
41 | import org.thingsboard.server.common.data.Device; | 42 | import org.thingsboard.server.common.data.Device; |
42 | import org.thingsboard.server.common.data.DeviceProfile; | 43 | import org.thingsboard.server.common.data.DeviceProfile; |
43 | -import org.thingsboard.server.common.data.DeviceTransportType; | 44 | +import org.thingsboard.server.common.data.firmware.FirmwareKey; |
45 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
46 | +import org.thingsboard.server.common.data.firmware.FirmwareUtil; | ||
47 | +import org.thingsboard.server.common.data.id.FirmwareId; | ||
44 | import org.thingsboard.server.common.transport.TransportService; | 48 | import org.thingsboard.server.common.transport.TransportService; |
49 | +import org.thingsboard.server.common.transport.TransportServiceCallback; | ||
45 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; | 50 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
46 | import org.thingsboard.server.common.transport.service.DefaultTransportService; | 51 | import org.thingsboard.server.common.transport.service.DefaultTransportService; |
47 | import org.thingsboard.server.gen.transport.TransportProtos; | 52 | import org.thingsboard.server.gen.transport.TransportProtos; |
@@ -49,6 +54,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotif | @@ -49,6 +54,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotif | ||
49 | import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent; | 54 | import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent; |
50 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; | 55 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
51 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | 56 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
57 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; | ||
52 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; | 58 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
53 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; | 59 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; |
54 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; | 60 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; |
@@ -77,34 +83,37 @@ import java.util.stream.Collectors; | @@ -77,34 +83,37 @@ import java.util.stream.Collectors; | ||
77 | 83 | ||
78 | import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST; | 84 | import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST; |
79 | import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION; | 85 | import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION; |
86 | +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; | ||
80 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; | 87 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; |
81 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.CLIENT_NOT_AUTHORIZED; | ||
82 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEVICE_ATTRIBUTES_REQUEST; | ||
83 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR; | ||
84 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO; | ||
85 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_VALUE; | ||
86 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LWM2M_STRATEGY_2; | ||
87 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper; | ||
88 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper.DISCOVER; | ||
89 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper.EXECUTE; | ||
90 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper.OBSERVE; | ||
91 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper.OBSERVE_CANCEL; | ||
92 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper.OBSERVE_READ_ALL; | ||
93 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper.READ; | ||
94 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper.WRITE_ATTRIBUTES; | ||
95 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper.WRITE_REPLACE; | ||
96 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper.WRITE_UPDATE; | ||
97 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.SERVICE_CHANNEL; | ||
98 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertJsonArrayToSet; | ||
99 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromIdVerToObjectId; | ||
100 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromObjectIdToIdVer; | ||
101 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getAckCallback; | ||
102 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.validateObjectVerFromKey; | 88 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.CLIENT_NOT_AUTHORIZED; |
89 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.DEVICE_ATTRIBUTES_REQUEST; | ||
90 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.FR_OBJECT_ID; | ||
91 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.FR_PATH_RESOURCE_VER_ID; | ||
92 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LOG_LW2M_ERROR; | ||
93 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LOG_LW2M_INFO; | ||
94 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LOG_LW2M_VALUE; | ||
95 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LWM2M_STRATEGY_2; | ||
96 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper; | ||
97 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.DISCOVER; | ||
98 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.EXECUTE; | ||
99 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.OBSERVE; | ||
100 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.OBSERVE_CANCEL; | ||
101 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.OBSERVE_READ_ALL; | ||
102 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.READ; | ||
103 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.WRITE_ATTRIBUTES; | ||
104 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.WRITE_REPLACE; | ||
105 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.WRITE_UPDATE; | ||
106 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.SERVICE_CHANNEL; | ||
107 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.convertJsonArrayToSet; | ||
108 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.convertPathFromIdVerToObjectId; | ||
109 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.convertPathFromObjectIdToIdVer; | ||
110 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.getAckCallback; | ||
111 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.validateObjectVerFromKey; | ||
103 | 112 | ||
104 | @Slf4j | 113 | @Slf4j |
105 | @Service | 114 | @Service |
106 | @TbLwM2mTransportComponent | 115 | @TbLwM2mTransportComponent |
107 | -public class LwM2mTransportServiceImpl implements LwM2mTransportService { | 116 | +public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler { |
108 | 117 | ||
109 | private ExecutorService executorRegistered; | 118 | private ExecutorService executorRegistered; |
110 | private ExecutorService executorUpdateRegistered; | 119 | private ExecutorService executorUpdateRegistered; |
@@ -112,31 +121,35 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -112,31 +121,35 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
112 | private LwM2mValueConverterImpl converter; | 121 | private LwM2mValueConverterImpl converter; |
113 | 122 | ||
114 | private final TransportService transportService; | 123 | private final TransportService transportService; |
115 | - | ||
116 | - public final LwM2mTransportContextServer lwM2mTransportContextServer; | ||
117 | - | 124 | + private final LwM2mTransportContext context; |
125 | + private final LwM2MTransportServerConfig config; | ||
126 | + private final FirmwareDataCache firmwareDataCache; | ||
127 | + private final LwM2mTransportServerHelper helper; | ||
118 | private final LwM2mClientContext lwM2mClientContext; | 128 | private final LwM2mClientContext lwM2mClientContext; |
119 | - | ||
120 | - private final LeshanServer leshanServer; | ||
121 | - | ||
122 | private final LwM2mTransportRequest lwM2mTransportRequest; | 129 | private final LwM2mTransportRequest lwM2mTransportRequest; |
123 | 130 | ||
124 | - public LwM2mTransportServiceImpl(TransportService transportService, LwM2mTransportContextServer lwM2mTransportContextServer, LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer, @Lazy LwM2mTransportRequest lwM2mTransportRequest) { | 131 | + public DefaultLwM2MTransportMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper, |
132 | + LwM2mClientContext lwM2mClientContext, | ||
133 | + @Lazy LwM2mTransportRequest lwM2mTransportRequest, | ||
134 | + FirmwareDataCache firmwareDataCache, | ||
135 | + LwM2mTransportContext context) { | ||
125 | this.transportService = transportService; | 136 | this.transportService = transportService; |
126 | - this.lwM2mTransportContextServer = lwM2mTransportContextServer; | 137 | + this.config = config; |
138 | + this.helper = helper; | ||
127 | this.lwM2mClientContext = lwM2mClientContext; | 139 | this.lwM2mClientContext = lwM2mClientContext; |
128 | - this.leshanServer = leshanServer; | ||
129 | this.lwM2mTransportRequest = lwM2mTransportRequest; | 140 | this.lwM2mTransportRequest = lwM2mTransportRequest; |
141 | + this.firmwareDataCache = firmwareDataCache; | ||
142 | + this.context = context; | ||
130 | } | 143 | } |
131 | 144 | ||
132 | @PostConstruct | 145 | @PostConstruct |
133 | public void init() { | 146 | public void init() { |
134 | - this.lwM2mTransportContextServer.getScheduler().scheduleAtFixedRate(this::checkInactivityAndReportActivity, new Random().nextInt((int) lwM2mTransportContextServer.getLwM2MTransportConfigServer().getSessionReportTimeout()), lwM2mTransportContextServer.getLwM2MTransportConfigServer().getSessionReportTimeout(), TimeUnit.MILLISECONDS); | ||
135 | - this.executorRegistered = Executors.newFixedThreadPool(this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getRegisteredPoolSize(), | 147 | + this.context.getScheduler().scheduleAtFixedRate(this::checkInactivityAndReportActivity, new Random().nextInt((int) config.getSessionReportTimeout()), config.getSessionReportTimeout(), TimeUnit.MILLISECONDS); |
148 | + this.executorRegistered = Executors.newFixedThreadPool(this.config.getRegisteredPoolSize(), | ||
136 | new NamedThreadFactory(String.format("LwM2M %s channel registered", SERVICE_CHANNEL))); | 149 | new NamedThreadFactory(String.format("LwM2M %s channel registered", SERVICE_CHANNEL))); |
137 | - this.executorUpdateRegistered = Executors.newFixedThreadPool(this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getUpdateRegisteredPoolSize(), | 150 | + this.executorUpdateRegistered = Executors.newFixedThreadPool(this.config.getUpdateRegisteredPoolSize(), |
138 | new NamedThreadFactory(String.format("LwM2M %s channel update registered", SERVICE_CHANNEL))); | 151 | new NamedThreadFactory(String.format("LwM2M %s channel update registered", SERVICE_CHANNEL))); |
139 | - this.executorUnRegistered = Executors.newFixedThreadPool(this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getUnRegisteredPoolSize(), | 152 | + this.executorUnRegistered = Executors.newFixedThreadPool(this.config.getUnRegisteredPoolSize(), |
140 | new NamedThreadFactory(String.format("LwM2M %s channel un registered", SERVICE_CHANNEL))); | 153 | new NamedThreadFactory(String.format("LwM2M %s channel un registered", SERVICE_CHANNEL))); |
141 | this.converter = LwM2mValueConverterImpl.getInstance(); | 154 | this.converter = LwM2mValueConverterImpl.getInstance(); |
142 | } | 155 | } |
@@ -168,8 +181,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -168,8 +181,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
168 | transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null); | 181 | transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null); |
169 | transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null); | 182 | transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null); |
170 | transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null); | 183 | transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null); |
184 | + this.getInfoFirmwareUpdate(lwM2MClient); | ||
171 | this.initLwM2mFromClientValue(registration, lwM2MClient); | 185 | this.initLwM2mFromClientValue(registration, lwM2MClient); |
172 | - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration); | 186 | + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration.getId()); |
173 | } else { | 187 | } else { |
174 | log.error("Client: [{}] onRegistered [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null); | 188 | log.error("Client: [{}] onRegistered [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null); |
175 | } | 189 | } |
@@ -224,7 +238,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -224,7 +238,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
224 | executorUnRegistered.submit(() -> { | 238 | executorUnRegistered.submit(() -> { |
225 | try { | 239 | try { |
226 | this.setCancelObservations(registration); | 240 | this.setCancelObservations(registration); |
227 | - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration); | 241 | + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId()); |
228 | this.closeClientSession(registration); | 242 | this.closeClientSession(registration); |
229 | } catch (Throwable t) { | 243 | } catch (Throwable t) { |
230 | log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t); | 244 | log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t); |
@@ -257,7 +271,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -257,7 +271,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
257 | @Override | 271 | @Override |
258 | public void onSleepingDev(Registration registration) { | 272 | public void onSleepingDev(Registration registration) { |
259 | log.info("[{}] [{}] Received endpoint Sleeping version event", registration.getId(), registration.getEndpoint()); | 273 | log.info("[{}] [{}] Received endpoint Sleeping version event", registration.getId(), registration.getEndpoint()); |
260 | - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is sleeping!", registration); | 274 | + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is sleeping!", registration.getId()); |
261 | 275 | ||
262 | //TODO: associate endpointId with device information. | 276 | //TODO: associate endpointId with device information. |
263 | } | 277 | } |
@@ -265,10 +279,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -265,10 +279,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
265 | @Override | 279 | @Override |
266 | public void setCancelObservations(Registration registration) { | 280 | public void setCancelObservations(Registration registration) { |
267 | if (registration != null) { | 281 | if (registration != null) { |
268 | - Set<Observation> observations = leshanServer.getObservationService().getObservations(registration); | 282 | + Set<Observation> observations = context.getServer().getObservationService().getObservations(registration); |
269 | observations.forEach(observation -> lwM2mTransportRequest.sendAllRequest(registration, | 283 | observations.forEach(observation -> lwM2mTransportRequest.sendAllRequest(registration, |
270 | convertPathFromObjectIdToIdVer(observation.getPath().toString(), registration), OBSERVE_CANCEL, | 284 | convertPathFromObjectIdToIdVer(observation.getPath().toString(), registration), OBSERVE_CANCEL, |
271 | - null, null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null)); | 285 | + null, null, this.config.getTimeout(), null)); |
272 | } | 286 | } |
273 | } | 287 | } |
274 | 288 | ||
@@ -280,7 +294,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -280,7 +294,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
280 | * @param response - observe | 294 | * @param response - observe |
281 | */ | 295 | */ |
282 | @Override | 296 | @Override |
283 | - public void onObservationResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) { | 297 | + public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) { |
284 | if (response.getContent() != null) { | 298 | if (response.getContent() != null) { |
285 | if (response.getContent() instanceof LwM2mObject) { | 299 | if (response.getContent() instanceof LwM2mObject) { |
286 | LwM2mObject lwM2mObject = (LwM2mObject) response.getContent(); | 300 | LwM2mObject lwM2mObject = (LwM2mObject) response.getContent(); |
@@ -304,22 +318,29 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -304,22 +318,29 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
304 | 318 | ||
305 | /** | 319 | /** |
306 | * Update - send request in change value resources in Client | 320 | * Update - send request in change value resources in Client |
307 | - * Path to resources from profile equal keyName or from ModelObject equal name | ||
308 | - * Only for resources: isWritable && isPresent as attribute in profile -> LwM2MClientProfile (format: CamelCase) | ||
309 | - * Delete - nothing * | 321 | + * 1. FirmwareUpdate: |
322 | + * - If msg.getSharedUpdatedList().forEach(tsKvProto -> {tsKvProto.getKv().getKey().indexOf(FIRMWARE_UPDATE_PREFIX, 0) == 0 | ||
323 | + * 2. Shared Other AttributeUpdate | ||
324 | + * -- Path to resources from profile equal keyName or from ModelObject equal name | ||
325 | + * -- Only for resources: isWritable && isPresent as attribute in profile -> LwM2MClientProfile (format: CamelCase) | ||
326 | + * 3. Delete - nothing | ||
310 | * | 327 | * |
311 | * @param msg - | 328 | * @param msg - |
312 | */ | 329 | */ |
313 | @Override | 330 | @Override |
314 | public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) { | 331 | public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) { |
332 | + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); | ||
315 | if (msg.getSharedUpdatedCount() > 0) { | 333 | if (msg.getSharedUpdatedCount() > 0) { |
316 | msg.getSharedUpdatedList().forEach(tsKvProto -> { | 334 | msg.getSharedUpdatedList().forEach(tsKvProto -> { |
317 | String pathName = tsKvProto.getKv().getKey(); | 335 | String pathName = tsKvProto.getKv().getKey(); |
318 | String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName); | 336 | String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName); |
319 | - Object valueNew = this.lwM2mTransportContextServer.getValueFromKvProto(tsKvProto.getKv()); | ||
320 | - LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); | 337 | + Object valueNew = this.helper.getValueFromKvProto(tsKvProto.getKv()); |
338 | + //TODO: react on change of the firmware name. | ||
339 | + if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) { | ||
340 | + this.getInfoFirmwareUpdate(lwM2MClient); | ||
341 | + } | ||
321 | if (pathIdVer != null) { | 342 | if (pathIdVer != null) { |
322 | - ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer() | 343 | + ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.config |
323 | .getModelProvider()); | 344 | .getModelProvider()); |
324 | if (resourceModel != null && resourceModel.operations.isWritable()) { | 345 | if (resourceModel != null && resourceModel.operations.isWritable()) { |
325 | this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer), valueNew, pathIdVer); | 346 | this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer), valueNew, pathIdVer); |
@@ -327,19 +348,26 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -327,19 +348,26 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
327 | log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, valueNew); | 348 | log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, valueNew); |
328 | String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated", | 349 | String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated", |
329 | LOG_LW2M_ERROR, pathIdVer, valueNew); | 350 | LOG_LW2M_ERROR, pathIdVer, valueNew); |
330 | - this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration()); | 351 | + this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId()); |
331 | } | 352 | } |
332 | } else { | 353 | } else { |
333 | log.error("Resource name name - [{}] value - [{}] is not present as attribute/telemetry in profile and cannot be updated", pathName, valueNew); | 354 | log.error("Resource name name - [{}] value - [{}] is not present as attribute/telemetry in profile and cannot be updated", pathName, valueNew); |
334 | String logMsg = String.format("%s: attributeUpdate: attribute name - %s value - %s is not present as attribute in profile and cannot be updated", | 355 | String logMsg = String.format("%s: attributeUpdate: attribute name - %s value - %s is not present as attribute in profile and cannot be updated", |
335 | LOG_LW2M_ERROR, pathName, valueNew); | 356 | LOG_LW2M_ERROR, pathName, valueNew); |
336 | - this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration()); | 357 | + this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId()); |
337 | } | 358 | } |
359 | + | ||
338 | }); | 360 | }); |
339 | } else if (msg.getSharedDeletedCount() > 0) { | 361 | } else if (msg.getSharedDeletedCount() > 0) { |
362 | + msg.getSharedUpdatedList().forEach(tsKvProto -> { | ||
363 | + String pathName = tsKvProto.getKv().getKey(); | ||
364 | + Object valueNew = this.helper.getValueFromKvProto(tsKvProto.getKv()); | ||
365 | + if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) { | ||
366 | + lwM2MClient.getFrUpdate().setCurrentFwVersion((String) valueNew); | ||
367 | + } | ||
368 | + }); | ||
340 | log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo); | 369 | log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo); |
341 | } | 370 | } |
342 | - | ||
343 | } | 371 | } |
344 | 372 | ||
345 | /** | 373 | /** |
@@ -377,7 +405,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -377,7 +405,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
377 | @Override | 405 | @Override |
378 | public void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) { | 406 | public void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) { |
379 | String idVer = resourceUpdateMsgOpt.get().getResourceKey(); | 407 | String idVer = resourceUpdateMsgOpt.get().getResourceKey(); |
380 | - lwM2mClientContext.getLwM2mClients().values().stream().forEach(e -> e.updateResourceModel(idVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelProvider())); | 408 | + lwM2mClientContext.getLwM2mClients().values().stream().forEach(e -> e.updateResourceModel(idVer, this.config.getModelProvider())); |
381 | } | 409 | } |
382 | 410 | ||
383 | /** | 411 | /** |
@@ -386,7 +414,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -386,7 +414,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
386 | @Override | 414 | @Override |
387 | public void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) { | 415 | public void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) { |
388 | String pathIdVer = resourceDeleteMsgOpt.get().getResourceKey(); | 416 | String pathIdVer = resourceDeleteMsgOpt.get().getResourceKey(); |
389 | - lwM2mClientContext.getLwM2mClients().values().stream().forEach(e -> e.deleteResources(pathIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelProvider())); | 417 | + lwM2mClientContext.getLwM2mClients().values().stream().forEach(e -> e.deleteResources(pathIdVer, this.config.getModelProvider())); |
390 | } | 418 | } |
391 | 419 | ||
392 | @Override | 420 | @Override |
@@ -402,7 +430,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -402,7 +430,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
402 | } else { | 430 | } else { |
403 | lwM2mTransportRequest.sendAllRequest(registration, lwm2mClientRpcRequest.getTargetIdVer(), lwm2mClientRpcRequest.getTypeOper(), lwm2mClientRpcRequest.getContentFormatName(), | 431 | lwM2mTransportRequest.sendAllRequest(registration, lwm2mClientRpcRequest.getTargetIdVer(), lwm2mClientRpcRequest.getTypeOper(), lwm2mClientRpcRequest.getContentFormatName(), |
404 | lwm2mClientRpcRequest.getValue() == null ? lwm2mClientRpcRequest.getParams() : lwm2mClientRpcRequest.getValue(), | 432 | lwm2mClientRpcRequest.getValue() == null ? lwm2mClientRpcRequest.getParams() : lwm2mClientRpcRequest.getValue(), |
405 | - this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), lwm2mClientRpcRequest); | 433 | + this.config.getTimeout(), lwm2mClientRpcRequest); |
406 | } | 434 | } |
407 | } catch (Exception e) { | 435 | } catch (Exception e) { |
408 | if (lwm2mClientRpcRequest == null) { | 436 | if (lwm2mClientRpcRequest == null) { |
@@ -430,7 +458,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -430,7 +458,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
430 | lwm2mClientRpcRequest.setRequestId(toDeviceRequest.getRequestId()); | 458 | lwm2mClientRpcRequest.setRequestId(toDeviceRequest.getRequestId()); |
431 | lwm2mClientRpcRequest.setSessionInfo(sessionInfo); | 459 | lwm2mClientRpcRequest.setSessionInfo(sessionInfo); |
432 | lwm2mClientRpcRequest.setValidTypeOper(toDeviceRequest.getMethodName()); | 460 | lwm2mClientRpcRequest.setValidTypeOper(toDeviceRequest.getMethodName()); |
433 | - JsonObject rpcRequest = LwM2mTransportHandler.validateJson(toDeviceRequest.getParams()); | 461 | + JsonObject rpcRequest = LwM2mTransportHandlerUtil.validateJson(toDeviceRequest.getParams()); |
434 | if (rpcRequest != null) { | 462 | if (rpcRequest != null) { |
435 | if (rpcRequest.has(lwm2mClientRpcRequest.keyNameKey)) { | 463 | if (rpcRequest.has(lwm2mClientRpcRequest.keyNameKey)) { |
436 | String targetIdVer = this.getPresentPathIntoProfile(sessionInfo, | 464 | String targetIdVer = this.getPresentPathIntoProfile(sessionInfo, |
@@ -455,23 +483,21 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -455,23 +483,21 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
455 | } | 483 | } |
456 | if (rpcRequest.has(lwm2mClientRpcRequest.paramsKey) && rpcRequest.get(lwm2mClientRpcRequest.paramsKey).isJsonObject()) { | 484 | if (rpcRequest.has(lwm2mClientRpcRequest.paramsKey) && rpcRequest.get(lwm2mClientRpcRequest.paramsKey).isJsonObject()) { |
457 | lwm2mClientRpcRequest.setParams(new Gson().fromJson(rpcRequest.get(lwm2mClientRpcRequest.paramsKey) | 485 | lwm2mClientRpcRequest.setParams(new Gson().fromJson(rpcRequest.get(lwm2mClientRpcRequest.paramsKey) |
458 | - .getAsJsonObject().toString(), new TypeToken<ConcurrentHashMap<String, Object>>() { | ||
459 | - }.getType())); | 486 | + .getAsJsonObject().toString(), new TypeToken<ConcurrentHashMap<String, Object>>() { |
487 | + }.getType())); | ||
460 | } | 488 | } |
461 | lwm2mClientRpcRequest.setSessionInfo(sessionInfo); | 489 | lwm2mClientRpcRequest.setSessionInfo(sessionInfo); |
462 | if (OBSERVE_READ_ALL != lwm2mClientRpcRequest.getTypeOper() && lwm2mClientRpcRequest.getTargetIdVer() == null) { | 490 | if (OBSERVE_READ_ALL != lwm2mClientRpcRequest.getTypeOper() && lwm2mClientRpcRequest.getTargetIdVer() == null) { |
463 | lwm2mClientRpcRequest.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " + | 491 | lwm2mClientRpcRequest.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " + |
464 | lwm2mClientRpcRequest.keyNameKey + " is null or bad format"); | 492 | lwm2mClientRpcRequest.keyNameKey + " is null or bad format"); |
465 | - } | ||
466 | - else if ((EXECUTE == lwm2mClientRpcRequest.getTypeOper() | 493 | + } else if ((EXECUTE == lwm2mClientRpcRequest.getTypeOper() |
467 | || WRITE_REPLACE == lwm2mClientRpcRequest.getTypeOper()) | 494 | || WRITE_REPLACE == lwm2mClientRpcRequest.getTypeOper()) |
468 | - && lwm2mClientRpcRequest.getTargetIdVer() !=null | 495 | + && lwm2mClientRpcRequest.getTargetIdVer() != null |
469 | && !(new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResource() | 496 | && !(new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResource() |
470 | || new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResourceInstance())) { | 497 | || new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResourceInstance())) { |
471 | - lwm2mClientRpcRequest.setErrorMsg("Invalid parameter " + lwm2mClientRpcRequest.targetIdVerKey | 498 | + lwm2mClientRpcRequest.setErrorMsg("Invalid parameter " + lwm2mClientRpcRequest.targetIdVerKey |
472 | + ". Only Resource or ResourceInstance can be this operation"); | 499 | + ". Only Resource or ResourceInstance can be this operation"); |
473 | - } | ||
474 | - else if (WRITE_UPDATE == lwm2mClientRpcRequest.getTypeOper()){ | 500 | + } else if (WRITE_UPDATE == lwm2mClientRpcRequest.getTypeOper()) { |
475 | lwm2mClientRpcRequest.setErrorMsg("Procedures In Development..."); | 501 | lwm2mClientRpcRequest.setErrorMsg("Procedures In Development..."); |
476 | } | 502 | } |
477 | } else { | 503 | } else { |
@@ -483,23 +509,23 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -483,23 +509,23 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
483 | return lwm2mClientRpcRequest; | 509 | return lwm2mClientRpcRequest; |
484 | } | 510 | } |
485 | 511 | ||
486 | - public void sentRpcRequest (Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) { | 512 | + public void sentRpcRequest(Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) { |
487 | rpcRequest.setResponseCode(requestCode); | 513 | rpcRequest.setResponseCode(requestCode); |
488 | - if (LOG_LW2M_ERROR.equals(typeMsg)) { | ||
489 | - rpcRequest.setInfoMsg(null); | ||
490 | - rpcRequest.setValueMsg(null); | ||
491 | - if (rpcRequest.getErrorMsg() == null) { | ||
492 | - msg = msg.isEmpty() ? null : msg; | ||
493 | - rpcRequest.setErrorMsg(msg); | ||
494 | - } | ||
495 | - } else if (LOG_LW2M_INFO.equals(typeMsg)) { | ||
496 | - if (rpcRequest.getInfoMsg() == null) { | ||
497 | - rpcRequest.setInfoMsg(msg); | ||
498 | - } | ||
499 | - } else if (LOG_LW2M_VALUE.equals(typeMsg)) { | ||
500 | - if (rpcRequest.getValueMsg() == null) { | ||
501 | - rpcRequest.setValueMsg(msg); | ||
502 | - } | 514 | + if (LOG_LW2M_ERROR.equals(typeMsg)) { |
515 | + rpcRequest.setInfoMsg(null); | ||
516 | + rpcRequest.setValueMsg(null); | ||
517 | + if (rpcRequest.getErrorMsg() == null) { | ||
518 | + msg = msg.isEmpty() ? null : msg; | ||
519 | + rpcRequest.setErrorMsg(msg); | ||
520 | + } | ||
521 | + } else if (LOG_LW2M_INFO.equals(typeMsg)) { | ||
522 | + if (rpcRequest.getInfoMsg() == null) { | ||
523 | + rpcRequest.setInfoMsg(msg); | ||
524 | + } | ||
525 | + } else if (LOG_LW2M_VALUE.equals(typeMsg)) { | ||
526 | + if (rpcRequest.getValueMsg() == null) { | ||
527 | + rpcRequest.setValueMsg(msg); | ||
528 | + } | ||
503 | } | 529 | } |
504 | this.onToDeviceRpcResponse(rpcRequest.getDeviceRpcResponseResultMsg(), rpcRequest.getSessionInfo()); | 530 | this.onToDeviceRpcResponse(rpcRequest.getDeviceRpcResponseResultMsg(), rpcRequest.getSessionInfo()); |
505 | } | 531 | } |
@@ -521,7 +547,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -521,7 +547,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
521 | @Override | 547 | @Override |
522 | public void doTrigger(Registration registration, String path) { | 548 | public void doTrigger(Registration registration, String path) { |
523 | lwM2mTransportRequest.sendAllRequest(registration, path, EXECUTE, | 549 | lwM2mTransportRequest.sendAllRequest(registration, path, EXECUTE, |
524 | - ContentFormat.TLV.getName(), null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null); | 550 | + ContentFormat.TLV.getName(), null, this.config.getTimeout(), null); |
525 | } | 551 | } |
526 | 552 | ||
527 | /** | 553 | /** |
@@ -554,9 +580,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -554,9 +580,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
554 | * | 580 | * |
555 | * @param registration - | 581 | * @param registration - |
556 | */ | 582 | */ |
557 | - protected void onAwakeDev(Registration registration) { | 583 | + @Override |
584 | + public void onAwakeDev(Registration registration) { | ||
558 | log.info("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint()); | 585 | log.info("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint()); |
559 | - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is awake!", registration); | 586 | + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is awake!", registration.getId()); |
560 | //TODO: associate endpointId with device information. | 587 | //TODO: associate endpointId with device information. |
561 | } | 588 | } |
562 | 589 | ||
@@ -583,12 +610,16 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -583,12 +610,16 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
583 | 610 | ||
584 | /** | 611 | /** |
585 | * @param logMsg - text msg | 612 | * @param logMsg - text msg |
586 | - * @param registration - Id of Registration LwM2M Client | 613 | + * @param registrationId - Id of Registration LwM2M Client |
587 | */ | 614 | */ |
588 | - public void sendLogsToThingsboard(String logMsg, Registration registration) { | ||
589 | - SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration); | 615 | + @Override |
616 | + public void sendLogsToThingsboard(String logMsg, String registrationId) { | ||
617 | + SessionInfoProto sessionInfo = this.getValidateSessionInfo(registrationId); | ||
590 | if (logMsg != null && sessionInfo != null) { | 618 | if (logMsg != null && sessionInfo != null) { |
591 | - this.lwM2mTransportContextServer.sendParametersOnThingsboardTelemetry(this.lwM2mTransportContextServer.getKvLogyToThingsboard(logMsg), sessionInfo); | 619 | + if(logMsg.length() > 1024){ |
620 | + logMsg = logMsg.substring(0, 1024); | ||
621 | + } | ||
622 | + this.helper.sendParametersOnThingsboardTelemetry(this.helper.getKvLogyToThingsboard(logMsg), sessionInfo); | ||
592 | } | 623 | } |
593 | } | 624 | } |
594 | 625 | ||
@@ -608,11 +639,11 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -608,11 +639,11 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
608 | LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration); | 639 | LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration); |
609 | Set<String> clientObjects = lwM2mClientContext.getSupportedIdVerInClient(registration); | 640 | Set<String> clientObjects = lwM2mClientContext.getSupportedIdVerInClient(registration); |
610 | if (clientObjects != null && clientObjects.size() > 0) { | 641 | if (clientObjects != null && clientObjects.size() > 0) { |
611 | - if (LWM2M_STRATEGY_2 == LwM2mTransportHandler.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) { | 642 | + if (LWM2M_STRATEGY_2 == LwM2mTransportHandlerUtil.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) { |
612 | // #2 | 643 | // #2 |
613 | - lwM2MClient.getPendingRequests().addAll(clientObjects); | 644 | + lwM2MClient.getPendingReadRequests().addAll(clientObjects); |
614 | clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(registration, path, READ, ContentFormat.TLV.getName(), | 645 | clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(registration, path, READ, ContentFormat.TLV.getName(), |
615 | - null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null)); | 646 | + null, this.config.getTimeout(), null)); |
616 | } | 647 | } |
617 | // #1 | 648 | // #1 |
618 | this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, READ, clientObjects); | 649 | this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, READ, clientObjects); |
@@ -652,6 +683,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -652,6 +683,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
652 | * Sending observe value of resources to thingsboard | 683 | * Sending observe value of resources to thingsboard |
653 | * #1 Return old Value Resource from LwM2MClient | 684 | * #1 Return old Value Resource from LwM2MClient |
654 | * #2 Update new Resources (replace old Resource Value on new Resource Value) | 685 | * #2 Update new Resources (replace old Resource Value on new Resource Value) |
686 | + * #3 If fr_update -> UpdateFirmware | ||
687 | + * #4 updateAttrTelemetry | ||
655 | * | 688 | * |
656 | * @param registration - Registration LwM2M Client | 689 | * @param registration - Registration LwM2M Client |
657 | * @param lwM2mResource - LwM2mSingleResource response.getContent() | 690 | * @param lwM2mResource - LwM2mSingleResource response.getContent() |
@@ -659,8 +692,21 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -659,8 +692,21 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
659 | */ | 692 | */ |
660 | private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) { | 693 | private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) { |
661 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); | 694 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); |
662 | - if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer() | 695 | + if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.config |
663 | .getModelProvider())) { | 696 | .getModelProvider())) { |
697 | + if (FR_PATH_RESOURCE_VER_ID.equals(convertPathFromIdVerToObjectId(path)) && | ||
698 | + lwM2MClient.getFrUpdate().getCurrentFwVersion() != null | ||
699 | + && !lwM2MClient.getFrUpdate().getCurrentFwVersion().equals(lwM2MClient.getFrUpdate().getClientFwVersion()) | ||
700 | + && lwM2MClient.isUpdateFw()) { | ||
701 | + | ||
702 | + /** version != null | ||
703 | + * set setClient_fw_version = value | ||
704 | + **/ | ||
705 | + lwM2MClient.setUpdateFw(false); | ||
706 | + lwM2MClient.getFrUpdate().setClientFwVersion(lwM2mResource.getValue().toString()); | ||
707 | + log.warn("updateFirmwareClient3"); | ||
708 | + this.updateFirmwareClient(lwM2MClient); | ||
709 | + } | ||
664 | Set<String> paths = new HashSet<>(); | 710 | Set<String> paths = new HashSet<>(); |
665 | paths.add(path); | 711 | paths.add(path); |
666 | this.updateAttrTelemetry(registration, paths); | 712 | this.updateAttrTelemetry(registration, paths); |
@@ -669,6 +715,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -669,6 +715,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
669 | } | 715 | } |
670 | } | 716 | } |
671 | 717 | ||
718 | + | ||
672 | /** | 719 | /** |
673 | * send Attribute and Telemetry to Thingsboard | 720 | * send Attribute and Telemetry to Thingsboard |
674 | * #1 - get AttrName/TelemetryName with value from LwM2MClient: | 721 | * #1 - get AttrName/TelemetryName with value from LwM2MClient: |
@@ -684,10 +731,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -684,10 +731,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
684 | SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration); | 731 | SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration); |
685 | if (results != null && sessionInfo != null) { | 732 | if (results != null && sessionInfo != null) { |
686 | if (results.getResultAttributes().size() > 0) { | 733 | if (results.getResultAttributes().size() > 0) { |
687 | - this.lwM2mTransportContextServer.sendParametersOnThingsboardAttribute(results.getResultAttributes(), sessionInfo); | 734 | + this.helper.sendParametersOnThingsboardAttribute(results.getResultAttributes(), sessionInfo); |
688 | } | 735 | } |
689 | if (results.getResultTelemetries().size() > 0) { | 736 | if (results.getResultTelemetries().size() > 0) { |
690 | - this.lwM2mTransportContextServer.sendParametersOnThingsboardTelemetry(results.getResultTelemetries(), sessionInfo); | 737 | + this.helper.sendParametersOnThingsboardTelemetry(results.getResultTelemetries(), sessionInfo); |
691 | } | 738 | } |
692 | } | 739 | } |
693 | } catch (Exception e) { | 740 | } catch (Exception e) { |
@@ -723,22 +770,23 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -723,22 +770,23 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
723 | params = this.getPathForWriteAttributes(lwM2MClientProfile.getPostAttributeLwm2mProfile()); | 770 | params = this.getPathForWriteAttributes(lwM2MClientProfile.getPostAttributeLwm2mProfile()); |
724 | result = params.keySet(); | 771 | result = params.keySet(); |
725 | } | 772 | } |
726 | - if (!result.isEmpty()) { | 773 | + if (result != null && !result.isEmpty()) { |
727 | // #1 | 774 | // #1 |
728 | Set<String> pathSend = result.stream().filter(target -> { | 775 | Set<String> pathSend = result.stream().filter(target -> { |
729 | return target.split(LWM2M_SEPARATOR_PATH).length < 3 ? | 776 | return target.split(LWM2M_SEPARATOR_PATH).length < 3 ? |
730 | clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]) : | 777 | clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]) : |
731 | clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1] + "/" + target.split(LWM2M_SEPARATOR_PATH)[2]); | 778 | clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1] + "/" + target.split(LWM2M_SEPARATOR_PATH)[2]); |
732 | } | 779 | } |
733 | - ) | ||
734 | - .collect(Collectors.toUnmodifiableSet()); | 780 | + ).collect(Collectors.toUnmodifiableSet()); |
735 | if (!pathSend.isEmpty()) { | 781 | if (!pathSend.isEmpty()) { |
736 | - lwM2MClient.getPendingRequests().addAll(pathSend); | 782 | + lwM2MClient.getPendingReadRequests().addAll(pathSend); |
737 | ConcurrentHashMap<String, Object> finalParams = params; | 783 | ConcurrentHashMap<String, Object> finalParams = params; |
738 | - pathSend.forEach(target -> lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, ContentFormat.TLV.getName(), | ||
739 | - finalParams != null ? finalParams.get(target) : null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null)); | 784 | + pathSend.forEach(target -> { |
785 | + lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, ContentFormat.TLV.getName(), | ||
786 | + finalParams != null ? finalParams.get(target) : null, this.config.getTimeout(), null); | ||
787 | + }); | ||
740 | if (OBSERVE.equals(typeOper)) { | 788 | if (OBSERVE.equals(typeOper)) { |
741 | - lwM2MClient.initValue(this, null); | 789 | + lwM2MClient.initReadValue(this, null); |
742 | } | 790 | } |
743 | } | 791 | } |
744 | } | 792 | } |
@@ -820,7 +868,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -820,7 +868,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
820 | LwM2mResource resourceValue = lwM2MClient != null ? getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) : null; | 868 | LwM2mResource resourceValue = lwM2MClient != null ? getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) : null; |
821 | if (resourceValue != null) { | 869 | if (resourceValue != null) { |
822 | ResourceModel.Type currentType = resourceValue.getType(); | 870 | ResourceModel.Type currentType = resourceValue.getType(); |
823 | - ResourceModel.Type expectedType = this.lwM2mTransportContextServer.getResourceModelTypeEqualsKvProtoValueType(currentType, pathIdVer); | 871 | + ResourceModel.Type expectedType = this.helper.getResourceModelTypeEqualsKvProtoValueType(currentType, pathIdVer); |
824 | Object valueKvProto = null; | 872 | Object valueKvProto = null; |
825 | if (resourceValue.isMultiInstances()) { | 873 | if (resourceValue.isMultiInstances()) { |
826 | valueKvProto = new JsonObject(); | 874 | valueKvProto = new JsonObject(); |
@@ -837,7 +885,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -837,7 +885,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
837 | valueKvProto = this.converter.convertValue(resourceValue.getValue(), currentType, expectedType, | 885 | valueKvProto = this.converter.convertValue(resourceValue.getValue(), currentType, expectedType, |
838 | new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); | 886 | new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); |
839 | } | 887 | } |
840 | - return valueKvProto != null ? this.lwM2mTransportContextServer.getKvAttrTelemetryToThingsboard(currentType, resourceName, valueKvProto, resourceValue.isMultiInstances()) : null; | 888 | + return valueKvProto != null ? this.helper.getKvAttrTelemetryToThingsboard(currentType, resourceName, valueKvProto, resourceValue.isMultiInstances()) : null; |
841 | } | 889 | } |
842 | } catch (Exception e) { | 890 | } catch (Exception e) { |
843 | log.error("Failed to add parameters.", e); | 891 | log.error("Failed to add parameters.", e); |
@@ -856,7 +904,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -856,7 +904,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
856 | private Object getResourceValueFormatKv(LwM2mClient lwM2MClient, String pathIdVer) { | 904 | private Object getResourceValueFormatKv(LwM2mClient lwM2MClient, String pathIdVer) { |
857 | LwM2mResource resourceValue = this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer); | 905 | LwM2mResource resourceValue = this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer); |
858 | ResourceModel.Type currentType = resourceValue.getType(); | 906 | ResourceModel.Type currentType = resourceValue.getType(); |
859 | - ResourceModel.Type expectedType = this.lwM2mTransportContextServer.getResourceModelTypeEqualsKvProtoValueType(currentType, pathIdVer); | 907 | + ResourceModel.Type expectedType = this.helper.getResourceModelTypeEqualsKvProtoValueType(currentType, pathIdVer); |
860 | return this.converter.convertValue(resourceValue.getValue(), currentType, expectedType, | 908 | return this.converter.convertValue(resourceValue.getValue(), currentType, expectedType, |
861 | new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); | 909 | new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); |
862 | } | 910 | } |
@@ -969,7 +1017,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -969,7 +1017,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
969 | // update value in Resources | 1017 | // update value in Resources |
970 | registrationIds.forEach(registrationId -> { | 1018 | registrationIds.forEach(registrationId -> { |
971 | Registration registration = lwM2mClientContext.getRegistration(registrationId); | 1019 | Registration registration = lwM2mClientContext.getRegistration(registrationId); |
972 | - this.readResourceValueObserve(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ); | 1020 | + this.readObserveFromProfile(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ); |
973 | // send attr/telemetry to tingsboard for new path | 1021 | // send attr/telemetry to tingsboard for new path |
974 | this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd()); | 1022 | this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd()); |
975 | }); | 1023 | }); |
@@ -998,12 +1046,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -998,12 +1046,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
998 | registrationIds.forEach(registrationId -> { | 1046 | registrationIds.forEach(registrationId -> { |
999 | Registration registration = lwM2mClientContext.getRegistration(registrationId); | 1047 | Registration registration = lwM2mClientContext.getRegistration(registrationId); |
1000 | if (postObserveAnalyzer.getPathPostParametersAdd().size() > 0) { | 1048 | if (postObserveAnalyzer.getPathPostParametersAdd().size() > 0) { |
1001 | - this.readResourceValueObserve(registration, postObserveAnalyzer.getPathPostParametersAdd(), OBSERVE); | 1049 | + this.readObserveFromProfile(registration, postObserveAnalyzer.getPathPostParametersAdd(), OBSERVE); |
1002 | } | 1050 | } |
1003 | // 5.3 del | 1051 | // 5.3 del |
1004 | // send Request cancel observe to Client | 1052 | // send Request cancel observe to Client |
1005 | if (postObserveAnalyzer.getPathPostParametersDel().size() > 0) { | 1053 | if (postObserveAnalyzer.getPathPostParametersDel().size() > 0) { |
1006 | - this.cancelObserveIsValue(registration, postObserveAnalyzer.getPathPostParametersDel()); | 1054 | + this.cancelObserveFromProfile(registration, postObserveAnalyzer.getPathPostParametersDel()); |
1007 | } | 1055 | } |
1008 | }); | 1056 | }); |
1009 | } | 1057 | } |
@@ -1043,16 +1091,16 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1043,16 +1091,16 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1043 | * @param registration - Registration LwM2M Client | 1091 | * @param registration - Registration LwM2M Client |
1044 | * @param targets - path Resources == [ "/2/0/0", "/2/0/1"] | 1092 | * @param targets - path Resources == [ "/2/0/0", "/2/0/1"] |
1045 | */ | 1093 | */ |
1046 | - private void readResourceValueObserve(Registration registration, Set<String> targets, LwM2mTypeOper typeOper) { | 1094 | + private void readObserveFromProfile(Registration registration, Set<String> targets, LwM2mTypeOper typeOper) { |
1047 | targets.forEach(target -> { | 1095 | targets.forEach(target -> { |
1048 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(target)); | 1096 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(target)); |
1049 | if (pathIds.isResource()) { | 1097 | if (pathIds.isResource()) { |
1050 | if (READ.equals(typeOper)) { | 1098 | if (READ.equals(typeOper)) { |
1051 | lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, | 1099 | lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, |
1052 | - ContentFormat.TLV.getName(), null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null); | 1100 | + ContentFormat.TLV.getName(), null, this.config.getTimeout(), null); |
1053 | } else if (OBSERVE.equals(typeOper)) { | 1101 | } else if (OBSERVE.equals(typeOper)) { |
1054 | lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, | 1102 | lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, |
1055 | - null, null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null); | 1103 | + null, null, this.config.getTimeout(), null); |
1056 | } | 1104 | } |
1057 | } | 1105 | } |
1058 | }); | 1106 | }); |
@@ -1108,7 +1156,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1108,7 +1156,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1108 | if (!pathSend.isEmpty()) { | 1156 | if (!pathSend.isEmpty()) { |
1109 | ConcurrentHashMap<String, Object> finalParams = lwm2mAttributesNew; | 1157 | ConcurrentHashMap<String, Object> finalParams = lwm2mAttributesNew; |
1110 | pathSend.forEach(target -> lwM2mTransportRequest.sendAllRequest(registration, target, WRITE_ATTRIBUTES, ContentFormat.TLV.getName(), | 1158 | pathSend.forEach(target -> lwM2mTransportRequest.sendAllRequest(registration, target, WRITE_ATTRIBUTES, ContentFormat.TLV.getName(), |
1111 | - finalParams.get(target), this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null)); | 1159 | + finalParams.get(target), this.config.getTimeout(), null)); |
1112 | } | 1160 | } |
1113 | }); | 1161 | }); |
1114 | } | 1162 | } |
@@ -1125,7 +1173,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1125,7 +1173,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1125 | params.clear(); | 1173 | params.clear(); |
1126 | params.put(OBJECT_VERSION, ""); | 1174 | params.put(OBJECT_VERSION, ""); |
1127 | lwM2mTransportRequest.sendAllRequest(registration, target, WRITE_ATTRIBUTES, ContentFormat.TLV.getName(), | 1175 | lwM2mTransportRequest.sendAllRequest(registration, target, WRITE_ATTRIBUTES, ContentFormat.TLV.getName(), |
1128 | - params, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null); | 1176 | + params, this.config.getTimeout(), null); |
1129 | }); | 1177 | }); |
1130 | } | 1178 | } |
1131 | }); | 1179 | }); |
@@ -1133,12 +1181,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1133,12 +1181,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1133 | 1181 | ||
1134 | } | 1182 | } |
1135 | 1183 | ||
1136 | - private void cancelObserveIsValue(Registration registration, Set<String> paramAnallyzer) { | 1184 | + private void cancelObserveFromProfile(Registration registration, Set<String> paramAnallyzer) { |
1137 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); | 1185 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); |
1138 | paramAnallyzer.forEach(pathIdVer -> { | 1186 | paramAnallyzer.forEach(pathIdVer -> { |
1139 | if (this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) != null) { | 1187 | if (this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) != null) { |
1140 | lwM2mTransportRequest.sendAllRequest(registration, pathIdVer, OBSERVE_CANCEL, null, | 1188 | lwM2mTransportRequest.sendAllRequest(registration, pathIdVer, OBSERVE_CANCEL, null, |
1141 | - null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null); | 1189 | + null, this.config.getTimeout(), null); |
1142 | } | 1190 | } |
1143 | } | 1191 | } |
1144 | ); | 1192 | ); |
@@ -1148,12 +1196,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1148,12 +1196,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1148 | if (valueNew != null && (valueOld == null || !valueNew.toString().equals(valueOld.toString()))) { | 1196 | if (valueNew != null && (valueOld == null || !valueNew.toString().equals(valueOld.toString()))) { |
1149 | lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), path, WRITE_REPLACE, | 1197 | lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), path, WRITE_REPLACE, |
1150 | ContentFormat.TLV.getName(), valueNew, | 1198 | ContentFormat.TLV.getName(), valueNew, |
1151 | - this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null); | 1199 | + this.config.getTimeout(), null); |
1152 | } else { | 1200 | } else { |
1153 | log.error("Failed update resource [{}] [{}]", path, valueNew); | 1201 | log.error("Failed update resource [{}] [{}]", path, valueNew); |
1154 | String logMsg = String.format("%s: Failed update resource path - %s value - %s. Value is not changed or bad", | 1202 | String logMsg = String.format("%s: Failed update resource path - %s value - %s. Value is not changed or bad", |
1155 | LOG_LW2M_ERROR, path, valueNew); | 1203 | LOG_LW2M_ERROR, path, valueNew); |
1156 | - this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration()); | 1204 | + this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId()); |
1157 | log.info("Failed update resource [{}] [{}]", path, valueNew); | 1205 | log.info("Failed update resource [{}] [{}]", path, valueNew); |
1158 | } | 1206 | } |
1159 | } | 1207 | } |
@@ -1182,8 +1230,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1182,8 +1230,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1182 | } | 1230 | } |
1183 | 1231 | ||
1184 | /** | 1232 | /** |
1185 | - * Update resource value on client: if there is a difference in values between the current resource values and the shared attribute values | ||
1186 | - * #1 Get path resource by result attributesResponse | 1233 | + * 1. FirmwareUpdate: |
1234 | + * - msg.getSharedUpdatedList().forEach(tsKvProto -> {tsKvProto.getKv().getKey().indexOf(FIRMWARE_UPDATE_PREFIX, 0) == 0 | ||
1235 | + * 2. Update resource value on client: if there is a difference in values between the current resource values and the shared attribute values | ||
1236 | + * - Get path resource by result attributesResponse | ||
1187 | * | 1237 | * |
1188 | * @param attributesResponse - | 1238 | * @param attributesResponse - |
1189 | * @param sessionInfo - | 1239 | * @param sessionInfo - |
@@ -1191,6 +1241,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1191,6 +1241,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1191 | public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg attributesResponse, TransportProtos.SessionInfoProto sessionInfo) { | 1241 | public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg attributesResponse, TransportProtos.SessionInfoProto sessionInfo) { |
1192 | try { | 1242 | try { |
1193 | List<TransportProtos.TsKvProto> tsKvProtos = attributesResponse.getSharedAttributeListList(); | 1243 | List<TransportProtos.TsKvProto> tsKvProtos = attributesResponse.getSharedAttributeListList(); |
1244 | + | ||
1194 | this.updateAttriuteFromThingsboard(tsKvProtos, sessionInfo); | 1245 | this.updateAttriuteFromThingsboard(tsKvProtos, sessionInfo); |
1195 | } catch (Exception e) { | 1246 | } catch (Exception e) { |
1196 | log.error(String.valueOf(e)); | 1247 | log.error(String.valueOf(e)); |
@@ -1223,7 +1274,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1223,7 +1274,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1223 | // #2.1 | 1274 | // #2.1 |
1224 | lwM2MClient.getDelayedRequests().forEach((pathIdVer, tsKvProto) -> { | 1275 | lwM2MClient.getDelayedRequests().forEach((pathIdVer, tsKvProto) -> { |
1225 | this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer), | 1276 | this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer), |
1226 | - this.lwM2mTransportContextServer.getValueFromKvProto(tsKvProto.getKv()), pathIdVer); | 1277 | + this.helper.getValueFromKvProto(tsKvProto.getKv()), pathIdVer); |
1227 | }); | 1278 | }); |
1228 | } | 1279 | } |
1229 | 1280 | ||
@@ -1240,7 +1291,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1240,7 +1291,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1240 | return null; | 1291 | return null; |
1241 | } else { | 1292 | } else { |
1242 | return SessionInfoProto.newBuilder() | 1293 | return SessionInfoProto.newBuilder() |
1243 | - .setNodeId(this.lwM2mTransportContextServer.getNodeId()) | 1294 | + .setNodeId(this.context.getNodeId()) |
1244 | .setSessionIdMSB(lwM2MClient.getSessionId().getMostSignificantBits()) | 1295 | .setSessionIdMSB(lwM2MClient.getSessionId().getMostSignificantBits()) |
1245 | .setSessionIdLSB(lwM2MClient.getSessionId().getLeastSignificantBits()) | 1296 | .setSessionIdLSB(lwM2MClient.getSessionId().getLeastSignificantBits()) |
1246 | .setDeviceIdMSB(msg.getDeviceInfo().getDeviceIdMSB()) | 1297 | .setDeviceIdMSB(msg.getDeviceInfo().getDeviceIdMSB()) |
@@ -1274,7 +1325,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1274,7 +1325,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1274 | */ | 1325 | */ |
1275 | private SessionInfoProto getValidateSessionInfo(String registrationId) { | 1326 | private SessionInfoProto getValidateSessionInfo(String registrationId) { |
1276 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(null, registrationId); | 1327 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(null, registrationId); |
1277 | - return getNewSessionInfoProto(lwM2MClient); | 1328 | + return lwM2MClient != null ? this.getNewSessionInfoProto(lwM2MClient) : null; |
1278 | } | 1329 | } |
1279 | 1330 | ||
1280 | /** | 1331 | /** |
@@ -1293,28 +1344,88 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1293,28 +1344,88 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1293 | } | 1344 | } |
1294 | 1345 | ||
1295 | /** | 1346 | /** |
1296 | - * !!! sharedAttr === profileAttr !!! | ||
1297 | - * If there is a difference in values between the current resource values and the shared attribute values | ||
1298 | - * when the client connects to the server | ||
1299 | - * #1 get attributes name from profile include name resources in ModelObject if resource isWritable | ||
1300 | - * #2.1 #1 size > 0 => send Request getAttributes to thingsboard | 1347 | + * #1. !!! sharedAttr === profileAttr !!! |
1348 | + * - If there is a difference in values between the current resource values and the shared attribute values | ||
1349 | + * - when the client connects to the server | ||
1350 | + * #1.1 get attributes name from profile include name resources in ModelObject if resource isWritable | ||
1351 | + * #1.2 #1 size > 0 => send Request getAttributes to thingsboard | ||
1352 | + * #2. FirmwareAttribute subscribe: | ||
1301 | * | 1353 | * |
1302 | * @param lwM2MClient - LwM2M Client | 1354 | * @param lwM2MClient - LwM2M Client |
1303 | */ | 1355 | */ |
1304 | public void putDelayedUpdateResourcesThingsboard(LwM2mClient lwM2MClient) { | 1356 | public void putDelayedUpdateResourcesThingsboard(LwM2mClient lwM2MClient) { |
1305 | SessionInfoProto sessionInfo = this.getValidateSessionInfo(lwM2MClient.getRegistration()); | 1357 | SessionInfoProto sessionInfo = this.getValidateSessionInfo(lwM2MClient.getRegistration()); |
1306 | if (sessionInfo != null) { | 1358 | if (sessionInfo != null) { |
1307 | - //#1.1 + #1.2 | ||
1308 | - List<String> attrSharedNames = this.getNamesAttrFromProfileIsWritable(lwM2MClient); | ||
1309 | - if (attrSharedNames.size() > 0) { | ||
1310 | - //#2.1 | 1359 | + //#1.1 |
1360 | + ConcurrentMap<String, String> keyNamesMap = this.getNamesFromProfileForSharedAttributes(lwM2MClient); | ||
1361 | + if (keyNamesMap.values().size() > 0) { | ||
1311 | try { | 1362 | try { |
1312 | - TransportProtos.GetAttributeRequestMsg getAttributeMsg = lwM2mTransportContextServer.getAdaptor().convertToGetAttributes(null, attrSharedNames); | 1363 | + //#1.2 |
1364 | + TransportProtos.GetAttributeRequestMsg getAttributeMsg = helper.getAdaptor().convertToGetAttributes(null, keyNamesMap.values()); | ||
1313 | transportService.process(sessionInfo, getAttributeMsg, getAckCallback(lwM2MClient, getAttributeMsg.getRequestId(), DEVICE_ATTRIBUTES_REQUEST)); | 1365 | transportService.process(sessionInfo, getAttributeMsg, getAckCallback(lwM2MClient, getAttributeMsg.getRequestId(), DEVICE_ATTRIBUTES_REQUEST)); |
1314 | } catch (AdaptorException e) { | 1366 | } catch (AdaptorException e) { |
1315 | log.warn("Failed to decode get attributes request", e); | 1367 | log.warn("Failed to decode get attributes request", e); |
1316 | } | 1368 | } |
1317 | } | 1369 | } |
1370 | + | ||
1371 | + } | ||
1372 | + } | ||
1373 | + | ||
1374 | + public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient) { | ||
1375 | + SessionInfoProto sessionInfo = this.getValidateSessionInfo(lwM2MClient.getRegistration()); | ||
1376 | + if (sessionInfo != null) { | ||
1377 | + TransportProtos.GetFirmwareRequestMsg getFirmwareRequestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder() | ||
1378 | + .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) | ||
1379 | + .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) | ||
1380 | + .setTenantIdMSB(sessionInfo.getTenantIdMSB()) | ||
1381 | + .setTenantIdLSB(sessionInfo.getTenantIdLSB()) | ||
1382 | + .setType(FirmwareType.FIRMWARE.name()) | ||
1383 | + .build(); | ||
1384 | + transportService.process(sessionInfo, getFirmwareRequestMsg, | ||
1385 | + new TransportServiceCallback<>() { | ||
1386 | + @Override | ||
1387 | + public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) { | ||
1388 | + if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())) { | ||
1389 | + lwM2MClient.getFrUpdate().setCurrentFwVersion(response.getVersion()); | ||
1390 | + lwM2MClient.getFrUpdate().setCurrentFwId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId()); | ||
1391 | + lwM2MClient.setUpdateFw(true); | ||
1392 | + readRequestToClientFirmwareVer(lwM2MClient.getRegistration()); | ||
1393 | + } else { | ||
1394 | + log.trace("Firmware [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString()); | ||
1395 | + } | ||
1396 | + } | ||
1397 | + | ||
1398 | + @Override | ||
1399 | + public void onError(Throwable e) { | ||
1400 | + log.trace("Failed to process credentials ", e); | ||
1401 | + } | ||
1402 | + }); | ||
1403 | + } | ||
1404 | + } | ||
1405 | + | ||
1406 | + /** | ||
1407 | + * @param registration | ||
1408 | + */ | ||
1409 | + public void readRequestToClientFirmwareVer(Registration registration) { | ||
1410 | + String pathIdVer = convertPathFromObjectIdToIdVer(FR_PATH_RESOURCE_VER_ID, registration); | ||
1411 | + lwM2mTransportRequest.sendAllRequest(registration, pathIdVer, READ, ContentFormat.TLV.getName(), | ||
1412 | + null, config.getTimeout(), null); | ||
1413 | + } | ||
1414 | + | ||
1415 | + /** | ||
1416 | + * | ||
1417 | + * @param lwM2MClient - | ||
1418 | + */ | ||
1419 | + public void updateFirmwareClient(LwM2mClient lwM2MClient) { | ||
1420 | + if (!lwM2MClient.getFrUpdate().getCurrentFwVersion().equals(lwM2MClient.getFrUpdate().getClientFwVersion())) { | ||
1421 | + int chunkSize = 0; | ||
1422 | + int chunk = 0; | ||
1423 | + byte[] firmwareChunk = firmwareDataCache.get(lwM2MClient.getFrUpdate().getCurrentFwId().toString(), chunkSize, chunk); | ||
1424 | + String verSupportedObject = lwM2MClient.getRegistration().getSupportedObject().get(FR_OBJECT_ID); | ||
1425 | + String targetIdVer = LWM2M_SEPARATOR_PATH + FR_OBJECT_ID + LWM2M_SEPARATOR_KEY + verSupportedObject + LWM2M_SEPARATOR_PATH + 0 + LWM2M_SEPARATOR_PATH + 0; | ||
1426 | + lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE.getName(), | ||
1427 | + firmwareChunk, config.getTimeout(), null); | ||
1428 | + log.warn("updateFirmwareClient [{}] [{}]", lwM2MClient.getFrUpdate().getCurrentFwVersion(), lwM2MClient.getFrUpdate().getClientFwVersion()); | ||
1318 | } | 1429 | } |
1319 | } | 1430 | } |
1320 | 1431 | ||
@@ -1326,27 +1437,16 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1326,27 +1437,16 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1326 | * @param lwM2MClient - | 1437 | * @param lwM2MClient - |
1327 | * @return ArrayList keyNames from profile profileAttr && IsWritable | 1438 | * @return ArrayList keyNames from profile profileAttr && IsWritable |
1328 | */ | 1439 | */ |
1329 | - private List<String> getNamesAttrFromProfileIsWritable(LwM2mClient lwM2MClient) { | 1440 | + private ConcurrentMap<String, String> getNamesFromProfileForSharedAttributes(LwM2mClient lwM2MClient) { |
1441 | + | ||
1330 | LwM2mClientProfile profile = lwM2mClientContext.getProfile(lwM2MClient.getProfileId()); | 1442 | LwM2mClientProfile profile = lwM2mClientContext.getProfile(lwM2MClient.getProfileId()); |
1331 | - Set<String> attrSet = new Gson().fromJson(profile.getPostAttributeProfile(), | ||
1332 | - new TypeToken<HashSet<String>>() { | ||
1333 | - }.getType()); | ||
1334 | - ConcurrentMap<String, String> keyNamesMap = new Gson().fromJson(profile.getPostKeyNameProfile().toString(), | 1443 | + return new Gson().fromJson(profile.getPostKeyNameProfile().toString(), |
1335 | new TypeToken<ConcurrentHashMap<String, String>>() { | 1444 | new TypeToken<ConcurrentHashMap<String, String>>() { |
1336 | }.getType()); | 1445 | }.getType()); |
1337 | - | ||
1338 | - ConcurrentMap<String, String> keyNamesIsWritable = keyNamesMap.entrySet() | ||
1339 | - .stream() | ||
1340 | - .filter(e -> (attrSet.contains(e.getKey()) && validateResourceInModel(lwM2MClient, e.getKey(), true))) | ||
1341 | - .collect(Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue)); | ||
1342 | - | ||
1343 | - Set<String> namesIsWritable = ConcurrentHashMap.newKeySet(); | ||
1344 | - namesIsWritable.addAll(new HashSet<>(keyNamesIsWritable.values())); | ||
1345 | - return new ArrayList<>(namesIsWritable); | ||
1346 | } | 1446 | } |
1347 | 1447 | ||
1348 | private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathIdVer, boolean isWritableNotOptional) { | 1448 | private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathIdVer, boolean isWritableNotOptional) { |
1349 | - ResourceModel resourceModel = lwM2mClient.getResourceModel(pathIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer() | 1449 | + ResourceModel resourceModel = lwM2mClient.getResourceModel(pathIdVer, this.config |
1350 | .getModelProvider()); | 1450 | .getModelProvider()); |
1351 | Integer objectId = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)).getObjectId(); | 1451 | Integer objectId = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)).getObjectId(); |
1352 | String objectVer = validateObjectVerFromKey(pathIdVer); | 1452 | String objectVer = validateObjectVerFromKey(pathIdVer); |
@@ -1355,9 +1455,4 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | @@ -1355,9 +1455,4 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { | ||
1355 | objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId))); | 1455 | objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId))); |
1356 | } | 1456 | } |
1357 | 1457 | ||
1358 | - @Override | ||
1359 | - public String getName() { | ||
1360 | - return "LWM2M"; | ||
1361 | - } | ||
1362 | - | ||
1363 | } | 1458 | } |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java
@@ -15,7 +15,10 @@ | @@ -15,7 +15,10 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.transport.lwm2m.server; | 16 | package org.thingsboard.server.transport.lwm2m.server; |
17 | 17 | ||
18 | +import lombok.RequiredArgsConstructor; | ||
18 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
20 | +import org.eclipse.californium.core.network.config.NetworkConfig; | ||
21 | +import org.eclipse.californium.core.network.stack.BlockwiseLayer; | ||
19 | import org.eclipse.californium.scandium.config.DtlsConnectorConfig; | 22 | import org.eclipse.californium.scandium.config.DtlsConnectorConfig; |
20 | import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeDecoder; | 23 | import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeDecoder; |
21 | import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder; | 24 | import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder; |
@@ -27,12 +30,16 @@ import org.eclipse.leshan.server.model.LwM2mModelProvider; | @@ -27,12 +30,16 @@ import org.eclipse.leshan.server.model.LwM2mModelProvider; | ||
27 | import org.eclipse.leshan.server.security.DefaultAuthorizer; | 30 | import org.eclipse.leshan.server.security.DefaultAuthorizer; |
28 | import org.eclipse.leshan.server.security.EditableSecurityStore; | 31 | import org.eclipse.leshan.server.security.EditableSecurityStore; |
29 | import org.eclipse.leshan.server.security.SecurityChecker; | 32 | import org.eclipse.leshan.server.security.SecurityChecker; |
30 | -import org.springframework.context.annotation.Bean; | ||
31 | import org.springframework.stereotype.Component; | 33 | import org.springframework.stereotype.Component; |
34 | +import org.thingsboard.server.common.data.StringUtils; | ||
32 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | 35 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
36 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; | ||
37 | +import org.thingsboard.server.transport.lwm2m.secure.LWM2MGenerationPSkRPkECC; | ||
33 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; | 38 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; |
34 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; | 39 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; |
35 | 40 | ||
41 | +import javax.annotation.PostConstruct; | ||
42 | +import javax.annotation.PreDestroy; | ||
36 | import java.math.BigInteger; | 43 | import java.math.BigInteger; |
37 | import java.security.AlgorithmParameters; | 44 | import java.security.AlgorithmParameters; |
38 | import java.security.KeyFactory; | 45 | import java.security.KeyFactory; |
@@ -57,61 +64,86 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE | @@ -57,61 +64,86 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE | ||
57 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; | 64 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; |
58 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; | 65 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; |
59 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8; | 66 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8; |
60 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getCoapConfig; | 67 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mNetworkConfig.getCoapConfig; |
61 | 68 | ||
62 | @Slf4j | 69 | @Slf4j |
63 | @Component | 70 | @Component |
64 | @TbLwM2mTransportComponent | 71 | @TbLwM2mTransportComponent |
65 | -public class LwM2mTransportServerConfiguration { | 72 | +@RequiredArgsConstructor |
73 | +public class DefaultLwM2mTransportService implements LwM2MTransportService { | ||
74 | + | ||
66 | private PublicKey publicKey; | 75 | private PublicKey publicKey; |
67 | private PrivateKey privateKey; | 76 | private PrivateKey privateKey; |
68 | private boolean pskMode = false; | 77 | private boolean pskMode = false; |
69 | - private final LwM2mTransportContextServer context; | 78 | + |
79 | + private final LwM2mTransportContext context; | ||
80 | + private final LwM2MTransportServerConfig config; | ||
81 | + private final LwM2mTransportServerHelper helper; | ||
82 | + private final LwM2mTransportMsgHandler handler; | ||
70 | private final CaliforniumRegistrationStore registrationStore; | 83 | private final CaliforniumRegistrationStore registrationStore; |
71 | private final EditableSecurityStore securityStore; | 84 | private final EditableSecurityStore securityStore; |
72 | private final LwM2mClientContext lwM2mClientContext; | 85 | private final LwM2mClientContext lwM2mClientContext; |
73 | 86 | ||
74 | - public LwM2mTransportServerConfiguration(LwM2mTransportContextServer context, CaliforniumRegistrationStore registrationStore, EditableSecurityStore securityStore, LwM2mClientContext lwM2mClientContext) { | ||
75 | - this.context = context; | ||
76 | - this.registrationStore = registrationStore; | ||
77 | - this.securityStore = securityStore; | ||
78 | - this.lwM2mClientContext = lwM2mClientContext; | 87 | + private LeshanServer server; |
88 | + | ||
89 | + @PostConstruct | ||
90 | + public void init() { | ||
91 | + if (config.getEnableGenNewKeyPskRpk()) { | ||
92 | + new LWM2MGenerationPSkRPkECC(); | ||
93 | + } | ||
94 | + this.server = getLhServer(config.getPort(), config.getSecurePort()); | ||
95 | + this.startLhServer(); | ||
96 | + this.context.setServer(server); | ||
97 | + } | ||
98 | + | ||
99 | + private void startLhServer() { | ||
100 | + log.info("Starting LwM2M transport Server..."); | ||
101 | + this.server.start(); | ||
102 | + LwM2mServerListener lhServerCertListener = new LwM2mServerListener(handler); | ||
103 | + this.server.getRegistrationService().addListener(lhServerCertListener.registrationListener); | ||
104 | + this.server.getPresenceService().addListener(lhServerCertListener.presenceListener); | ||
105 | + this.server.getObservationService().addListener(lhServerCertListener.observationListener); | ||
79 | } | 106 | } |
80 | 107 | ||
81 | - @Bean | ||
82 | - public LeshanServer getLeshanServer() { | ||
83 | - log.info("Starting LwM2M transport Server... PostConstruct"); | ||
84 | - return this.getLhServer(this.context.getLwM2MTransportConfigServer().getServerPortNoSec(), this.context.getLwM2MTransportConfigServer().getServerPortSecurity()); | 108 | + @PreDestroy |
109 | + public void shutdown() { | ||
110 | + log.info("Stopping LwM2M transport Server!"); | ||
111 | + server.destroy(); | ||
112 | + log.info("LwM2M transport Server stopped!"); | ||
85 | } | 113 | } |
86 | 114 | ||
87 | private LeshanServer getLhServer(Integer serverPortNoSec, Integer serverSecurePort) { | 115 | private LeshanServer getLhServer(Integer serverPortNoSec, Integer serverSecurePort) { |
88 | LeshanServerBuilder builder = new LeshanServerBuilder(); | 116 | LeshanServerBuilder builder = new LeshanServerBuilder(); |
89 | - builder.setLocalAddress(this.context.getLwM2MTransportConfigServer().getServerHost(), serverPortNoSec); | ||
90 | - builder.setLocalSecureAddress(this.context.getLwM2MTransportConfigServer().getServerHostSecurity(), serverSecurePort); | 117 | + builder.setLocalAddress(config.getHost(), serverPortNoSec); |
118 | + builder.setLocalSecureAddress(config.getSecureHost(), serverSecurePort); | ||
91 | builder.setDecoder(new DefaultLwM2mNodeDecoder()); | 119 | builder.setDecoder(new DefaultLwM2mNodeDecoder()); |
92 | - /** Use a magic converter to support bad type send by the UI. */ | 120 | + /* Use a magic converter to support bad type send by the UI. */ |
93 | builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance())); | 121 | builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance())); |
94 | 122 | ||
95 | - /** Create CoAP Config */ | 123 | + |
124 | + /* Create CoAP Config */ | ||
125 | + NetworkConfig networkConfig = getCoapConfig(serverPortNoSec, serverSecurePort); | ||
126 | + BlockwiseLayer blockwiseLayer = new BlockwiseLayer(networkConfig); | ||
96 | builder.setCoapConfig(getCoapConfig(serverPortNoSec, serverSecurePort)); | 127 | builder.setCoapConfig(getCoapConfig(serverPortNoSec, serverSecurePort)); |
97 | 128 | ||
98 | - /** Define model provider (Create Models )*/ | ||
99 | - LwM2mModelProvider modelProvider = new LwM2mVersionedModelProvider(this.lwM2mClientContext, this.context); | ||
100 | - this.context.getLwM2MTransportConfigServer().setModelProvider(modelProvider); | 129 | + /* Define model provider (Create Models )*/ |
130 | + LwM2mModelProvider modelProvider = new LwM2mVersionedModelProvider(this.lwM2mClientContext, this.helper, this.context); | ||
131 | + config.setModelProvider(modelProvider); | ||
101 | builder.setObjectModelProvider(modelProvider); | 132 | builder.setObjectModelProvider(modelProvider); |
102 | 133 | ||
103 | - /** Create credentials */ | 134 | + /* Create credentials */ |
104 | this.setServerWithCredentials(builder); | 135 | this.setServerWithCredentials(builder); |
105 | 136 | ||
106 | - /** Set securityStore with new registrationStore */ | 137 | + /* Set securityStore with new registrationStore */ |
107 | builder.setSecurityStore(securityStore); | 138 | builder.setSecurityStore(securityStore); |
108 | builder.setRegistrationStore(registrationStore); | 139 | builder.setRegistrationStore(registrationStore); |
109 | 140 | ||
110 | 141 | ||
111 | - /** Create DTLS Config */ | 142 | + /* Create DTLS Config */ |
112 | DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); | 143 | DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); |
113 | - dtlsConfig.setRecommendedSupportedGroupsOnly(this.context.getLwM2MTransportConfigServer().isRecommendedSupportedGroups()); | ||
114 | - dtlsConfig.setRecommendedCipherSuitesOnly(this.context.getLwM2MTransportConfigServer().isRecommendedCiphers()); | 144 | + dtlsConfig.setServerOnly(true); |
145 | + dtlsConfig.setRecommendedSupportedGroupsOnly(config.isRecommendedSupportedGroups()); | ||
146 | + dtlsConfig.setRecommendedCipherSuitesOnly(config.isRecommendedCiphers()); | ||
115 | if (this.pskMode) { | 147 | if (this.pskMode) { |
116 | dtlsConfig.setSupportedCipherSuites( | 148 | dtlsConfig.setSupportedCipherSuites( |
117 | TLS_PSK_WITH_AES_128_CCM_8, | 149 | TLS_PSK_WITH_AES_128_CCM_8, |
@@ -124,27 +156,27 @@ public class LwM2mTransportServerConfiguration { | @@ -124,27 +156,27 @@ public class LwM2mTransportServerConfiguration { | ||
124 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256); | 156 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256); |
125 | } | 157 | } |
126 | 158 | ||
127 | - /** Set DTLS Config */ | 159 | + /* Set DTLS Config */ |
128 | builder.setDtlsConfig(dtlsConfig); | 160 | builder.setDtlsConfig(dtlsConfig); |
129 | 161 | ||
130 | - /** Create LWM2M server */ | 162 | + /* Create LWM2M server */ |
131 | return builder.build(); | 163 | return builder.build(); |
132 | } | 164 | } |
133 | 165 | ||
134 | private void setServerWithCredentials(LeshanServerBuilder builder) { | 166 | private void setServerWithCredentials(LeshanServerBuilder builder) { |
135 | try { | 167 | try { |
136 | - if (this.context.getLwM2MTransportConfigServer().getKeyStoreValue() != null) { | 168 | + if (config.getKeyStoreValue() != null) { |
137 | if (this.setBuilderX509(builder)) { | 169 | if (this.setBuilderX509(builder)) { |
138 | - X509Certificate rootCAX509Cert = (X509Certificate) this.context.getLwM2MTransportConfigServer().getKeyStoreValue().getCertificate(this.context.getLwM2MTransportConfigServer().getRootAlias()); | 170 | + X509Certificate rootCAX509Cert = (X509Certificate) config.getKeyStoreValue().getCertificate(config.getRootCertificateAlias()); |
139 | if (rootCAX509Cert != null) { | 171 | if (rootCAX509Cert != null) { |
140 | X509Certificate[] trustedCertificates = new X509Certificate[1]; | 172 | X509Certificate[] trustedCertificates = new X509Certificate[1]; |
141 | trustedCertificates[0] = rootCAX509Cert; | 173 | trustedCertificates[0] = rootCAX509Cert; |
142 | builder.setTrustedCertificates(trustedCertificates); | 174 | builder.setTrustedCertificates(trustedCertificates); |
143 | } else { | 175 | } else { |
144 | - /** by default trust all */ | 176 | + /* by default trust all */ |
145 | builder.setTrustedCertificates(new X509Certificate[0]); | 177 | builder.setTrustedCertificates(new X509Certificate[0]); |
146 | } | 178 | } |
147 | - /** Set securityStore with registrationStore*/ | 179 | + /* Set securityStore with registrationStore*/ |
148 | builder.setAuthorizer(new DefaultAuthorizer(securityStore, new SecurityChecker() { | 180 | builder.setAuthorizer(new DefaultAuthorizer(securityStore, new SecurityChecker() { |
149 | @Override | 181 | @Override |
150 | protected boolean matchX509Identity(String endpoint, String receivedX509CommonName, | 182 | protected boolean matchX509Identity(String endpoint, String receivedX509CommonName, |
@@ -157,7 +189,7 @@ public class LwM2mTransportServerConfiguration { | @@ -157,7 +189,7 @@ public class LwM2mTransportServerConfiguration { | ||
157 | this.infoPramsUri("RPK"); | 189 | this.infoPramsUri("RPK"); |
158 | this.infoParamsServerKey(this.publicKey, this.privateKey); | 190 | this.infoParamsServerKey(this.publicKey, this.privateKey); |
159 | } else { | 191 | } else { |
160 | - /** by default trust all */ | 192 | + /* by default trust all */ |
161 | builder.setTrustedCertificates(new X509Certificate[0]); | 193 | builder.setTrustedCertificates(new X509Certificate[0]); |
162 | log.info("Unable to load X509 files for LWM2MServer"); | 194 | log.info("Unable to load X509 files for LWM2MServer"); |
163 | this.pskMode = true; | 195 | this.pskMode = true; |
@@ -169,17 +201,11 @@ public class LwM2mTransportServerConfiguration { | @@ -169,17 +201,11 @@ public class LwM2mTransportServerConfiguration { | ||
169 | } | 201 | } |
170 | 202 | ||
171 | private boolean setBuilderX509(LeshanServerBuilder builder) { | 203 | private boolean setBuilderX509(LeshanServerBuilder builder) { |
172 | - /** | ||
173 | - * For deb => KeyStorePathFile == yml or commandline: KEY_STORE_PATH_FILE | ||
174 | - * For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks | ||
175 | - */ | ||
176 | try { | 204 | try { |
177 | - X509Certificate serverCertificate = (X509Certificate) this.context.getLwM2MTransportConfigServer().getKeyStoreValue().getCertificate(this.context.getLwM2MTransportConfigServer().getServerAlias()); | ||
178 | - PrivateKey privateKey = (PrivateKey) this.context.getLwM2MTransportConfigServer().getKeyStoreValue().getKey(this.context.getLwM2MTransportConfigServer().getServerAlias(), this.context.getLwM2MTransportConfigServer().getKeyStorePasswordServer() == null ? null : this.context.getLwM2MTransportConfigServer().getKeyStorePasswordServer().toCharArray()); | 205 | + X509Certificate serverCertificate = (X509Certificate) config.getKeyStoreValue().getCertificate(config.getCertificateAlias()); |
206 | + PrivateKey privateKey = (PrivateKey) config.getKeyStoreValue().getKey(config.getCertificateAlias(), config.getKeyStorePassword() == null ? null : config.getKeyStorePassword().toCharArray()); | ||
179 | PublicKey publicKey = serverCertificate.getPublicKey(); | 207 | PublicKey publicKey = serverCertificate.getPublicKey(); |
180 | - if (serverCertificate != null && | ||
181 | - privateKey != null && privateKey.getEncoded().length > 0 && | ||
182 | - publicKey != null && publicKey.getEncoded().length > 0) { | 208 | + if (privateKey != null && privateKey.getEncoded().length > 0 && publicKey != null && publicKey.getEncoded().length > 0) { |
183 | builder.setPublicKey(serverCertificate.getPublicKey()); | 209 | builder.setPublicKey(serverCertificate.getPublicKey()); |
184 | builder.setPrivateKey(privateKey); | 210 | builder.setPrivateKey(privateKey); |
185 | builder.setCertificateChain(new X509Certificate[]{serverCertificate}); | 211 | builder.setCertificateChain(new X509Certificate[]{serverCertificate}); |
@@ -206,10 +232,12 @@ public class LwM2mTransportServerConfiguration { | @@ -206,10 +232,12 @@ public class LwM2mTransportServerConfiguration { | ||
206 | } | 232 | } |
207 | 233 | ||
208 | private void infoPramsUri(String mode) { | 234 | private void infoPramsUri(String mode) { |
209 | - log.info("Server uses [{}]: serverNoSecureURI : [{}], serverSecureURI : [{}]", | ||
210 | - mode, | ||
211 | - this.context.getLwM2MTransportConfigServer().getServerHost() + ":" + this.context.getLwM2MTransportConfigServer().getServerPortNoSec(), | ||
212 | - this.context.getLwM2MTransportConfigServer().getServerHostSecurity() + ":" + this.context.getLwM2MTransportConfigServer().getServerPortSecurity()); | 235 | + LwM2MTransportServerConfig lwM2MTransportServerConfig = config; |
236 | + log.info("Server uses [{}]: serverNoSecureURI : [{}:{}], serverSecureURI : [{}:{}]", mode, | ||
237 | + lwM2MTransportServerConfig.getHost(), | ||
238 | + lwM2MTransportServerConfig.getPort(), | ||
239 | + lwM2MTransportServerConfig.getSecureHost(), | ||
240 | + lwM2MTransportServerConfig.getSecurePort()); | ||
213 | } | 241 | } |
214 | 242 | ||
215 | private boolean setServerRPK(LeshanServerBuilder builder) { | 243 | private boolean setServerRPK(LeshanServerBuilder builder) { |
@@ -227,55 +255,42 @@ public class LwM2mTransportServerConfiguration { | @@ -227,55 +255,42 @@ public class LwM2mTransportServerConfiguration { | ||
227 | return false; | 255 | return false; |
228 | } | 256 | } |
229 | 257 | ||
230 | - | ||
231 | - /** | ||
232 | - * From yml: server | ||
233 | - * public_x: "${LWM2M_SERVER_PUBLIC_X:405354ea8893471d9296afbc8b020a5c6201b0bb25812a53b849d4480fa5f069}" | ||
234 | - * public_y: "${LWM2M_SERVER_PUBLIC_Y:30c9237e946a3a1692c1cafaa01a238a077f632c99371348337512363f28212b}" | ||
235 | - * private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:274671fe40ce937b8a6352cf0a418e8a39e4bf0bb9bf74c910db953c20c73802}" | ||
236 | - */ | ||
237 | private void generateKeyForRPK() throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidKeySpecException { | 258 | private void generateKeyForRPK() throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidKeySpecException { |
238 | - /** Get Elliptic Curve Parameter spec for secp256r1 */ | 259 | + /* Get Elliptic Curve Parameter spec for secp256r1 */ |
239 | AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); | 260 | AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); |
240 | algoParameters.init(new ECGenParameterSpec("secp256r1")); | 261 | algoParameters.init(new ECGenParameterSpec("secp256r1")); |
241 | ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); | 262 | ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); |
242 | - if (this.context.getLwM2MTransportConfigServer().getServerPublicX() != null && | ||
243 | - !this.context.getLwM2MTransportConfigServer().getServerPublicX().isEmpty() && | ||
244 | - this.context.getLwM2MTransportConfigServer().getServerPublicY() != null && | ||
245 | - !this.context.getLwM2MTransportConfigServer().getServerPublicY().isEmpty()) { | ||
246 | - /** Get point values */ | ||
247 | - byte[] publicX = Hex.decodeHex(this.context.getLwM2MTransportConfigServer().getServerPublicX().toCharArray()); | ||
248 | - byte[] publicY = Hex.decodeHex(this.context.getLwM2MTransportConfigServer().getServerPublicY().toCharArray()); | ||
249 | - /** Create key specs */ | 263 | + LwM2MTransportServerConfig serverConfig = config; |
264 | + if (StringUtils.isNotEmpty(serverConfig.getPublicX()) && StringUtils.isNotEmpty(serverConfig.getPublicY())) { | ||
265 | + byte[] publicX = Hex.decodeHex(serverConfig.getPublicX().toCharArray()); | ||
266 | + byte[] publicY = Hex.decodeHex(serverConfig.getPublicY().toCharArray()); | ||
250 | KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), | 267 | KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), |
251 | parameterSpec); | 268 | parameterSpec); |
252 | - /** Get keys */ | ||
253 | this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); | 269 | this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); |
254 | } | 270 | } |
255 | - if (this.context.getLwM2MTransportConfigServer().getServerPrivateEncoded() != null && | ||
256 | - !this.context.getLwM2MTransportConfigServer().getServerPrivateEncoded().isEmpty()) { | ||
257 | - /** Get private key */ | ||
258 | - byte[] privateS = Hex.decodeHex(this.context.getLwM2MTransportConfigServer().getServerPrivateEncoded().toCharArray()); | 271 | + String privateEncodedKey = serverConfig.getPrivateEncoded(); |
272 | + if (StringUtils.isNotEmpty(privateEncodedKey)) { | ||
273 | + byte[] privateS = Hex.decodeHex(privateEncodedKey.toCharArray()); | ||
259 | try { | 274 | try { |
260 | this.privateKey = KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(privateS)); | 275 | this.privateKey = KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(privateS)); |
261 | } catch (InvalidKeySpecException ignore2) { | 276 | } catch (InvalidKeySpecException ignore2) { |
262 | - log.error("Invalid Server rpk.PrivateKey.getEncoded () [{}}]. PrivateKey has no EC algorithm", this.context.getLwM2MTransportConfigServer().getServerPrivateEncoded()); | 277 | + log.error("Invalid Server rpk.PrivateKey.getEncoded () [{}}]. PrivateKey has no EC algorithm", privateEncodedKey); |
263 | } | 278 | } |
264 | } | 279 | } |
265 | } | 280 | } |
266 | 281 | ||
267 | private void infoParamsServerKey(PublicKey publicKey, PrivateKey privateKey) { | 282 | private void infoParamsServerKey(PublicKey publicKey, PrivateKey privateKey) { |
268 | - /** Get x coordinate */ | 283 | + /* Get x coordinate */ |
269 | byte[] x = ((ECPublicKey) publicKey).getW().getAffineX().toByteArray(); | 284 | byte[] x = ((ECPublicKey) publicKey).getW().getAffineX().toByteArray(); |
270 | if (x[0] == 0) | 285 | if (x[0] == 0) |
271 | x = Arrays.copyOfRange(x, 1, x.length); | 286 | x = Arrays.copyOfRange(x, 1, x.length); |
272 | 287 | ||
273 | - /** Get Y coordinate */ | 288 | + /* Get Y coordinate */ |
274 | byte[] y = ((ECPublicKey) publicKey).getW().getAffineY().toByteArray(); | 289 | byte[] y = ((ECPublicKey) publicKey).getW().getAffineY().toByteArray(); |
275 | if (y[0] == 0) | 290 | if (y[0] == 0) |
276 | y = Arrays.copyOfRange(y, 1, y.length); | 291 | y = Arrays.copyOfRange(y, 1, y.length); |
277 | 292 | ||
278 | - /** Get Curves params */ | 293 | + /* Get Curves params */ |
279 | String params = ((ECPublicKey) publicKey).getParams().toString(); | 294 | String params = ((ECPublicKey) publicKey).getParams().toString(); |
280 | String privHex = Hex.encodeHexString(privateKey.getEncoded()); | 295 | String privHex = Hex.encodeHexString(privateKey.getEncoded()); |
281 | log.info(" \n- Public Key (Hex): [{}] \n" + | 296 | log.info(" \n- Public Key (Hex): [{}] \n" + |
@@ -292,4 +307,9 @@ public class LwM2mTransportServerConfiguration { | @@ -292,4 +307,9 @@ public class LwM2mTransportServerConfiguration { | ||
292 | params); | 307 | params); |
293 | } | 308 | } |
294 | 309 | ||
310 | + @Override | ||
311 | + public String getName() { | ||
312 | + return "LWM2M"; | ||
313 | + } | ||
314 | + | ||
295 | } | 315 | } |
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; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.TbTransportService; | ||
19 | + | ||
20 | +public interface LwM2MTransportService extends TbTransportService { | ||
21 | + | ||
22 | +} |
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; | ||
17 | + | ||
18 | +import org.eclipse.californium.core.network.config.NetworkConfig; | ||
19 | + | ||
20 | +public class LwM2mNetworkConfig { | ||
21 | + | ||
22 | + public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort) { | ||
23 | + NetworkConfig coapConfig = new NetworkConfig(); | ||
24 | + coapConfig.setInt(NetworkConfig.Keys.COAP_PORT,serverPortNoSec); | ||
25 | + coapConfig.setInt(NetworkConfig.Keys.COAP_SECURE_PORT,serverSecurePort); | ||
26 | + /* | ||
27 | + Example:Property for large packet: | ||
28 | + #NetworkConfig config = new NetworkConfig(); | ||
29 | + #config.setInt(NetworkConfig.Keys.MAX_MESSAGE_SIZE,32); | ||
30 | + #config.setInt(NetworkConfig.Keys.PREFERRED_BLOCK_SIZE,32); | ||
31 | + #config.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE,2048); | ||
32 | + #config.setInt(NetworkConfig.Keys.MAX_RETRANSMIT,3); | ||
33 | + #config.setInt(NetworkConfig.Keys.MAX_TRANSMIT_WAIT,120000); | ||
34 | + */ | ||
35 | + | ||
36 | + /* | ||
37 | + Property to indicate if the response should always include the Block2 option \ | ||
38 | + when client request early blockwise negociation but the response can be sent on one packet. | ||
39 | + - value of false indicate that the server will respond without block2 option if no further blocks are required. | ||
40 | + - value of true indicate that the server will response with block2 option event if no further blocks are required. | ||
41 | + CoAP client will try to use block mode | ||
42 | + or adapt the block size when receiving a 4.13 Entity too large response code | ||
43 | + */ | ||
44 | + coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_STRICT_BLOCK2_OPTION, true); | ||
45 | + /* | ||
46 | + Property to indicate if the response should always include the Block2 option \ | ||
47 | + when client request early blockwise negociation but the response can be sent on one packet. | ||
48 | + - value of false indicate that the server will respond without block2 option if no further blocks are required. | ||
49 | + - value of true indicate that the server will response with block2 option event if no further blocks are required. | ||
50 | + */ | ||
51 | + coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_ENTITY_TOO_LARGE_AUTO_FAILOVER, true); | ||
52 | + | ||
53 | + coapConfig.setInt(NetworkConfig.Keys.BLOCKWISE_STATUS_LIFETIME, 300000); | ||
54 | + /* | ||
55 | + !!! REQUEST_ENTITY_TOO_LARGE CODE=4.13 | ||
56 | + The maximum size of a resource body (in bytes) that will be accepted | ||
57 | + as the payload of a POST/PUT or the response to a GET request in a | ||
58 | + transparent> blockwise transfer. | ||
59 | + This option serves as a safeguard against excessive memory | ||
60 | + consumption when many resources contain large bodies that cannot be | ||
61 | + transferred in a single CoAP message. This option has no impact on | ||
62 | + *manually* managed blockwise transfers in which the blocks are handled individually. | ||
63 | + Note that this option does not prevent local clients or resource | ||
64 | + implementations from sending large bodies as part of a request or response to a peer. | ||
65 | + The default value of this property is DEFAULT_MAX_RESOURCE_BODY_SIZE = 8192 | ||
66 | + A value of {@code 0} turns off transparent handling of blockwise transfers altogether. | ||
67 | + */ | ||
68 | + coapConfig.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE, 256 * 1024 * 1024); | ||
69 | + /* | ||
70 | + The default DTLS response matcher. | ||
71 | + Supported values are STRICT, RELAXED, or PRINCIPAL. | ||
72 | + The default value is STRICT. | ||
73 | + Create new instance of udp endpoint context matcher. | ||
74 | + Params: | ||
75 | + checkAddress | ||
76 | + – true with address check, (STRICT, UDP) | ||
77 | + - false, without | ||
78 | + */ | ||
79 | + coapConfig.setString(NetworkConfig.Keys.RESPONSE_MATCHING, "STRICT"); | ||
80 | + /* | ||
81 | + https://tools.ietf.org/html/rfc7959#section-2.9.3 | ||
82 | + The block size (number of bytes) to use when doing a blockwise transfer. \ | ||
83 | + This value serves as the upper limit for block size in blockwise transfers | ||
84 | + */ | ||
85 | + coapConfig.setInt(NetworkConfig.Keys.PREFERRED_BLOCK_SIZE, 1024); | ||
86 | + /* | ||
87 | + The maximum payload size (in bytes) that can be transferred in a | ||
88 | + single message, i.e. without requiring a blockwise transfer. | ||
89 | + NB: this value MUST be adapted to the maximum message size supported by the transport layer. | ||
90 | + In particular, this value cannot exceed the network's MTU if UDP is used as the transport protocol | ||
91 | + DEFAULT_VALUE = 1024 | ||
92 | + */ | ||
93 | + coapConfig.setInt(NetworkConfig.Keys.MAX_MESSAGE_SIZE, 1024); | ||
94 | + | ||
95 | + coapConfig.setInt(NetworkConfig.Keys.MAX_RETRANSMIT, 4); | ||
96 | + | ||
97 | + return coapConfig; | ||
98 | + } | ||
99 | +} |
@@ -26,14 +26,15 @@ import org.eclipse.leshan.server.registration.RegistrationUpdate; | @@ -26,14 +26,15 @@ import org.eclipse.leshan.server.registration.RegistrationUpdate; | ||
26 | 26 | ||
27 | import java.util.Collection; | 27 | import java.util.Collection; |
28 | 28 | ||
29 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromObjectIdToIdVer; | 29 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LOG_LW2M_INFO; |
30 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.convertPathFromObjectIdToIdVer; | ||
30 | 31 | ||
31 | @Slf4j | 32 | @Slf4j |
32 | public class LwM2mServerListener { | 33 | public class LwM2mServerListener { |
33 | 34 | ||
34 | - private final LwM2mTransportServiceImpl service; | 35 | + private final LwM2mTransportMsgHandler service; |
35 | 36 | ||
36 | - public LwM2mServerListener(LwM2mTransportServiceImpl service) { | 37 | + public LwM2mServerListener(LwM2mTransportMsgHandler service) { |
37 | this.service = service; | 38 | this.service = service; |
38 | } | 39 | } |
39 | 40 | ||
@@ -85,17 +86,19 @@ public class LwM2mServerListener { | @@ -85,17 +86,19 @@ public class LwM2mServerListener { | ||
85 | 86 | ||
86 | @Override | 87 | @Override |
87 | public void cancelled(Observation observation) { | 88 | public void cancelled(Observation observation) { |
88 | - log.info("Received notification cancelled from [{}] ", observation.getPath()); | 89 | + String msg = String.format("%s: Cancel Observation %s.", LOG_LW2M_INFO, observation.getPath()); |
90 | + service.sendLogsToThingsboard(msg, observation.getRegistrationId()); | ||
91 | + log.trace(msg); | ||
89 | } | 92 | } |
90 | 93 | ||
91 | @Override | 94 | @Override |
92 | public void onResponse(Observation observation, Registration registration, ObserveResponse response) { | 95 | public void onResponse(Observation observation, Registration registration, ObserveResponse response) { |
93 | if (registration != null) { | 96 | if (registration != null) { |
94 | try { | 97 | try { |
95 | - service.onObservationResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(), | 98 | + service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(), |
96 | registration), response, null); | 99 | registration), response, null); |
97 | } catch (Exception e) { | 100 | } catch (Exception e) { |
98 | - log.error("[{}] onResponse", e.toString()); | 101 | + log.error("Observation/Read onResponse", e); |
99 | 102 | ||
100 | } | 103 | } |
101 | } | 104 | } |
@@ -108,7 +111,10 @@ public class LwM2mServerListener { | @@ -108,7 +111,10 @@ public class LwM2mServerListener { | ||
108 | 111 | ||
109 | @Override | 112 | @Override |
110 | public void newObservation(Observation observation, Registration registration) { | 113 | public void newObservation(Observation observation, Registration registration) { |
111 | - log.info("Received newObservation from [{}] endpoint [{}] ", observation.getPath(), registration.getEndpoint()); | 114 | + String msg = String.format("%s: Successful start newObservation %s.", LOG_LW2M_INFO, |
115 | + observation.getPath()); | ||
116 | + service.sendLogsToThingsboard(msg, registration.getId()); | ||
117 | + log.trace(msg); | ||
112 | } | 118 | } |
113 | }; | 119 | }; |
114 | 120 |
@@ -35,10 +35,10 @@ import java.util.Optional; | @@ -35,10 +35,10 @@ import java.util.Optional; | ||
35 | 35 | ||
36 | @Slf4j | 36 | @Slf4j |
37 | public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? super Void>>, SessionMsgListener { | 37 | public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? super Void>>, SessionMsgListener { |
38 | - private LwM2mTransportServiceImpl service; | 38 | + private DefaultLwM2MTransportMsgHandler service; |
39 | private TransportProtos.SessionInfoProto sessionInfo; | 39 | private TransportProtos.SessionInfoProto sessionInfo; |
40 | 40 | ||
41 | - public LwM2mSessionMsgListener(LwM2mTransportServiceImpl service, TransportProtos.SessionInfoProto sessionInfo) { | 41 | + public LwM2mSessionMsgListener(DefaultLwM2MTransportMsgHandler service, TransportProtos.SessionInfoProto sessionInfo) { |
42 | this.service = service; | 42 | this.service = service; |
43 | this.sessionInfo = sessionInfo; | 43 | this.sessionInfo = sessionInfo; |
44 | } | 44 | } |
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; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | +import lombok.Setter; | ||
20 | +import org.eclipse.leshan.server.californium.LeshanServer; | ||
21 | +import org.springframework.stereotype.Component; | ||
22 | +import org.thingsboard.server.common.transport.TransportContext; | ||
23 | +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | ||
24 | + | ||
25 | +@Component | ||
26 | +@TbLwM2mTransportComponent | ||
27 | +public class LwM2mTransportContext extends TransportContext { | ||
28 | + | ||
29 | + @Getter @Setter | ||
30 | + private LeshanServer server; | ||
31 | + | ||
32 | +} |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandlerUtil.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java
@@ -25,7 +25,6 @@ import com.google.gson.JsonSyntaxException; | @@ -25,7 +25,6 @@ import com.google.gson.JsonSyntaxException; | ||
25 | import com.google.gson.reflect.TypeToken; | 25 | import com.google.gson.reflect.TypeToken; |
26 | import lombok.extern.slf4j.Slf4j; | 26 | import lombok.extern.slf4j.Slf4j; |
27 | import org.apache.commons.lang3.StringUtils; | 27 | import org.apache.commons.lang3.StringUtils; |
28 | -import org.eclipse.californium.core.network.config.NetworkConfig; | ||
29 | import org.eclipse.leshan.core.attributes.Attribute; | 28 | import org.eclipse.leshan.core.attributes.Attribute; |
30 | import org.eclipse.leshan.core.attributes.AttributeSet; | 29 | import org.eclipse.leshan.core.attributes.AttributeSet; |
31 | import org.eclipse.leshan.core.model.ObjectModel; | 30 | import org.eclipse.leshan.core.model.ObjectModel; |
@@ -40,7 +39,6 @@ import org.eclipse.leshan.core.node.codec.CodecException; | @@ -40,7 +39,6 @@ import org.eclipse.leshan.core.node.codec.CodecException; | ||
40 | import org.eclipse.leshan.core.request.DownlinkRequest; | 39 | import org.eclipse.leshan.core.request.DownlinkRequest; |
41 | import org.eclipse.leshan.core.request.WriteAttributesRequest; | 40 | import org.eclipse.leshan.core.request.WriteAttributesRequest; |
42 | import org.eclipse.leshan.core.util.Hex; | 41 | import org.eclipse.leshan.core.util.Hex; |
43 | -import org.eclipse.leshan.server.californium.LeshanServerBuilder; | ||
44 | import org.eclipse.leshan.server.registration.Registration; | 42 | import org.eclipse.leshan.server.registration.Registration; |
45 | import org.nustaq.serialization.FSTConfiguration; | 43 | import org.nustaq.serialization.FSTConfiguration; |
46 | import org.thingsboard.server.common.data.DeviceProfile; | 44 | import org.thingsboard.server.common.data.DeviceProfile; |
@@ -50,7 +48,6 @@ import org.thingsboard.server.common.transport.TransportServiceCallback; | @@ -50,7 +48,6 @@ import org.thingsboard.server.common.transport.TransportServiceCallback; | ||
50 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; | 48 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
51 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; | 49 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; |
52 | 50 | ||
53 | -import java.io.File; | ||
54 | import java.io.IOException; | 51 | import java.io.IOException; |
55 | import java.util.ArrayList; | 52 | import java.util.ArrayList; |
56 | import java.util.Arrays; | 53 | import java.util.Arrays; |
@@ -70,9 +67,8 @@ import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPA | @@ -70,9 +67,8 @@ import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPA | ||
70 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; | 67 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; |
71 | 68 | ||
72 | @Slf4j | 69 | @Slf4j |
73 | -public class LwM2mTransportHandler { | 70 | +public class LwM2mTransportHandlerUtil { |
74 | 71 | ||
75 | - // public static final String BASE_DEVICE_API_TOPIC = "v1/devices/me"; | ||
76 | public static final String TRANSPORT_DEFAULT_LWM2M_VERSION = "1.0"; | 72 | public static final String TRANSPORT_DEFAULT_LWM2M_VERSION = "1.0"; |
77 | public static final String CLIENT_LWM2M_SETTINGS = "clientLwM2mSettings"; | 73 | public static final String CLIENT_LWM2M_SETTINGS = "clientLwM2mSettings"; |
78 | public static final String BOOTSTRAP = "bootstrap"; | 74 | public static final String BOOTSTRAP = "bootstrap"; |
@@ -85,19 +81,12 @@ public class LwM2mTransportHandler { | @@ -85,19 +81,12 @@ public class LwM2mTransportHandler { | ||
85 | public static final String KEY_NAME = "keyName"; | 81 | public static final String KEY_NAME = "keyName"; |
86 | public static final String OBSERVE_LWM2M = "observe"; | 82 | public static final String OBSERVE_LWM2M = "observe"; |
87 | public static final String ATTRIBUTE_LWM2M = "attributeLwm2m"; | 83 | public static final String ATTRIBUTE_LWM2M = "attributeLwm2m"; |
88 | -// public static final String RESOURCE_VALUE = "resValue"; | ||
89 | -// public static final String RESOURCE_TYPE = "resType"; | ||
90 | 84 | ||
91 | private static final String REQUEST = "/request"; | 85 | private static final String REQUEST = "/request"; |
92 | - // private static final String RESPONSE = "/response"; | ||
93 | private static final String ATTRIBUTES = "/" + ATTRIBUTE; | 86 | private static final String ATTRIBUTES = "/" + ATTRIBUTE; |
94 | public static final String TELEMETRIES = "/" + TELEMETRY; | 87 | public static final String TELEMETRIES = "/" + TELEMETRY; |
95 | - // public static final String ATTRIBUTES_RESPONSE = ATTRIBUTES + RESPONSE; | ||
96 | public static final String ATTRIBUTES_REQUEST = ATTRIBUTES + REQUEST; | 88 | public static final String ATTRIBUTES_REQUEST = ATTRIBUTES + REQUEST; |
97 | - // public static final String DEVICE_ATTRIBUTES_RESPONSE = ATTRIBUTES_RESPONSE + "/"; | ||
98 | public static final String DEVICE_ATTRIBUTES_REQUEST = ATTRIBUTES_REQUEST + "/"; | 89 | public static final String DEVICE_ATTRIBUTES_REQUEST = ATTRIBUTES_REQUEST + "/"; |
99 | -// public static final String DEVICE_ATTRIBUTES_TOPIC = BASE_DEVICE_API_TOPIC + ATTRIBUTES; | ||
100 | -// public static final String DEVICE_TELEMETRY_TOPIC = BASE_DEVICE_API_TOPIC + TELEMETRIES; | ||
101 | 90 | ||
102 | public static final long DEFAULT_TIMEOUT = 2 * 60 * 1000L; // 2min in ms | 91 | public static final long DEFAULT_TIMEOUT = 2 * 60 * 1000L; // 2min in ms |
103 | 92 | ||
@@ -112,6 +101,11 @@ public class LwM2mTransportHandler { | @@ -112,6 +101,11 @@ public class LwM2mTransportHandler { | ||
112 | 101 | ||
113 | public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized"; | 102 | public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized"; |
114 | 103 | ||
104 | + public static final Integer FR_OBJECT_ID = 5; | ||
105 | + public static final Integer FR_RESOURCE_VER_ID = 7; | ||
106 | + public static final String FR_PATH_RESOURCE_VER_ID = LWM2M_SEPARATOR_PATH + FR_OBJECT_ID + LWM2M_SEPARATOR_PATH | ||
107 | + + "0" + LWM2M_SEPARATOR_PATH + FR_RESOURCE_VER_ID; | ||
108 | + | ||
115 | public enum LwM2mTypeServer { | 109 | public enum LwM2mTypeServer { |
116 | BOOTSTRAP(0, "bootstrap"), | 110 | BOOTSTRAP(0, "bootstrap"), |
117 | CLIENT(1, "client"); | 111 | CLIENT(1, "client"); |
@@ -168,6 +162,8 @@ public class LwM2mTransportHandler { | @@ -168,6 +162,8 @@ public class LwM2mTransportHandler { | ||
168 | WRITE_ATTRIBUTES(8, "WriteAttributes"), | 162 | WRITE_ATTRIBUTES(8, "WriteAttributes"), |
169 | DELETE(9, "Delete"); | 163 | DELETE(9, "Delete"); |
170 | 164 | ||
165 | +// READ_INFO_FW(10, "ReadInfoFirmware"); | ||
166 | + | ||
171 | public int code; | 167 | public int code; |
172 | public String type; | 168 | public String type; |
173 | 169 | ||
@@ -190,21 +186,6 @@ public class LwM2mTransportHandler { | @@ -190,21 +186,6 @@ public class LwM2mTransportHandler { | ||
190 | public static final String SERVICE_CHANNEL = "SERVICE"; | 186 | public static final String SERVICE_CHANNEL = "SERVICE"; |
191 | public static final String RESPONSE_CHANNEL = "RESP"; | 187 | public static final String RESPONSE_CHANNEL = "RESP"; |
192 | 188 | ||
193 | - public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort) { | ||
194 | - NetworkConfig coapConfig; | ||
195 | - File configFile = new File(NetworkConfig.DEFAULT_FILE_NAME); | ||
196 | - if (configFile.isFile()) { | ||
197 | - coapConfig = new NetworkConfig(); | ||
198 | - coapConfig.load(configFile); | ||
199 | - } else { | ||
200 | - coapConfig = LeshanServerBuilder.createDefaultNetworkConfig(); | ||
201 | - coapConfig.store(configFile); | ||
202 | - } | ||
203 | - coapConfig.setString("COAP_PORT", Integer.toString(serverPortNoSec)); | ||
204 | - coapConfig.setString("COAP_SECURE_PORT", Integer.toString(serverSecurePort)); | ||
205 | - return coapConfig; | ||
206 | - } | ||
207 | - | ||
208 | public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath resourcePath) throws CodecException { | 189 | public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath resourcePath) throws CodecException { |
209 | switch (type) { | 190 | switch (type) { |
210 | case BOOLEAN: | 191 | case BOOLEAN: |
@@ -275,7 +256,7 @@ public class LwM2mTransportHandler { | @@ -275,7 +256,7 @@ public class LwM2mTransportHandler { | ||
275 | ObjectMapper mapper = new ObjectMapper(); | 256 | ObjectMapper mapper = new ObjectMapper(); |
276 | String profileStr = mapper.writeValueAsString(profile); | 257 | String profileStr = mapper.writeValueAsString(profile); |
277 | JsonObject profileJson = (profileStr != null) ? validateJson(profileStr) : null; | 258 | JsonObject profileJson = (profileStr != null) ? validateJson(profileStr) : null; |
278 | - return getValidateCredentialsBodyFromThingsboard(profileJson) ? LwM2mTransportHandler.getNewProfileParameters(profileJson, deviceProfile.getTenantId()) : null; | 259 | + return getValidateCredentialsBodyFromThingsboard(profileJson) ? LwM2mTransportHandlerUtil.getNewProfileParameters(profileJson, deviceProfile.getTenantId()) : null; |
279 | } catch (IOException e) { | 260 | } catch (IOException e) { |
280 | log.error("", e); | 261 | log.error("", e); |
281 | } | 262 | } |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportMsgHandler.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportService.java
@@ -27,7 +27,7 @@ import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcReques | @@ -27,7 +27,7 @@ import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcReques | ||
27 | import java.util.Collection; | 27 | import java.util.Collection; |
28 | import java.util.Optional; | 28 | import java.util.Optional; |
29 | 29 | ||
30 | -public interface LwM2mTransportService extends TbTransportService { | 30 | +public interface LwM2mTransportMsgHandler { |
31 | 31 | ||
32 | void onRegistered(Registration registration, Collection<Observation> previousObsersations); | 32 | void onRegistered(Registration registration, Collection<Observation> previousObsersations); |
33 | 33 | ||
@@ -39,7 +39,7 @@ public interface LwM2mTransportService extends TbTransportService { | @@ -39,7 +39,7 @@ public interface LwM2mTransportService extends TbTransportService { | ||
39 | 39 | ||
40 | void setCancelObservations(Registration registration); | 40 | void setCancelObservations(Registration registration); |
41 | 41 | ||
42 | - void onObservationResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest); | 42 | + void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest); |
43 | 43 | ||
44 | void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo); | 44 | void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo); |
45 | 45 | ||
@@ -61,5 +61,7 @@ public interface LwM2mTransportService extends TbTransportService { | @@ -61,5 +61,7 @@ public interface LwM2mTransportService extends TbTransportService { | ||
61 | 61 | ||
62 | void doDisconnect(TransportProtos.SessionInfoProto sessionInfo); | 62 | void doDisconnect(TransportProtos.SessionInfoProto sessionInfo); |
63 | 63 | ||
64 | + void onAwakeDev(Registration registration); | ||
64 | 65 | ||
66 | + void sendLogsToThingsboard(String msg, String registrationId); | ||
65 | } | 67 | } |
@@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.transport.lwm2m.server; | 16 | package org.thingsboard.server.transport.lwm2m.server; |
17 | 17 | ||
18 | +import lombok.RequiredArgsConstructor; | ||
18 | import lombok.SneakyThrows; | 19 | import lombok.SneakyThrows; |
19 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
20 | import org.eclipse.californium.core.coap.CoAP; | 21 | import org.eclipse.californium.core.coap.CoAP; |
@@ -50,6 +51,7 @@ import org.eclipse.leshan.server.registration.Registration; | @@ -50,6 +51,7 @@ import org.eclipse.leshan.server.registration.Registration; | ||
50 | import org.springframework.stereotype.Service; | 51 | import org.springframework.stereotype.Service; |
51 | import org.thingsboard.server.common.transport.TransportService; | 52 | import org.thingsboard.server.common.transport.TransportService; |
52 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | 53 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
54 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; | ||
53 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; | 55 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
54 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; | 56 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; |
55 | import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest; | 57 | import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest; |
@@ -66,50 +68,38 @@ import java.util.stream.Collectors; | @@ -66,50 +68,38 @@ import java.util.stream.Collectors; | ||
66 | import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT; | 68 | import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT; |
67 | import static org.eclipse.leshan.core.ResponseCode.BAD_REQUEST; | 69 | import static org.eclipse.leshan.core.ResponseCode.BAD_REQUEST; |
68 | import static org.eclipse.leshan.core.ResponseCode.NOT_FOUND; | 70 | import static org.eclipse.leshan.core.ResponseCode.NOT_FOUND; |
69 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEFAULT_TIMEOUT; | ||
70 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR; | ||
71 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO; | ||
72 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_VALUE; | ||
73 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper; | ||
74 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper.OBSERVE_CANCEL; | ||
75 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper.OBSERVE_READ_ALL; | ||
76 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.RESPONSE_CHANNEL; | ||
77 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromIdVerToObjectId; | ||
78 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromObjectIdToIdVer; | ||
79 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.createWriteAttributeRequest; | 71 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.DEFAULT_TIMEOUT; |
72 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.FR_PATH_RESOURCE_VER_ID; | ||
73 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LOG_LW2M_ERROR; | ||
74 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LOG_LW2M_INFO; | ||
75 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LOG_LW2M_VALUE; | ||
76 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper; | ||
77 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.OBSERVE_CANCEL; | ||
78 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.OBSERVE_READ_ALL; | ||
79 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.RESPONSE_CHANNEL; | ||
80 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.convertPathFromIdVerToObjectId; | ||
81 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.convertPathFromObjectIdToIdVer; | ||
82 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.createWriteAttributeRequest; | ||
80 | 83 | ||
81 | @Slf4j | 84 | @Slf4j |
82 | @Service | 85 | @Service |
83 | @TbLwM2mTransportComponent | 86 | @TbLwM2mTransportComponent |
87 | +@RequiredArgsConstructor | ||
84 | public class LwM2mTransportRequest { | 88 | public class LwM2mTransportRequest { |
85 | private ExecutorService executorResponse; | 89 | private ExecutorService executorResponse; |
86 | 90 | ||
87 | public LwM2mValueConverterImpl converter; | 91 | public LwM2mValueConverterImpl converter; |
88 | 92 | ||
89 | - private final LwM2mTransportContextServer lwM2mTransportContextServer; | ||
90 | - | 93 | + private final LwM2mTransportContext context; |
94 | + private final LwM2MTransportServerConfig config; | ||
95 | + private final LwM2mTransportServerHelper lwM2MTransportServerHelper; | ||
91 | private final LwM2mClientContext lwM2mClientContext; | 96 | private final LwM2mClientContext lwM2mClientContext; |
92 | - | ||
93 | - private final LeshanServer leshanServer; | ||
94 | - | ||
95 | - private final LwM2mTransportServiceImpl serviceImpl; | ||
96 | - | ||
97 | - private final TransportService transportService; | ||
98 | - | ||
99 | - public LwM2mTransportRequest(LwM2mTransportContextServer lwM2mTransportContextServer, | ||
100 | - LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer, | ||
101 | - LwM2mTransportServiceImpl serviceImpl, TransportService transportService) { | ||
102 | - this.lwM2mTransportContextServer = lwM2mTransportContextServer; | ||
103 | - this.lwM2mClientContext = lwM2mClientContext; | ||
104 | - this.leshanServer = leshanServer; | ||
105 | - this.serviceImpl = serviceImpl; | ||
106 | - this.transportService = transportService; | ||
107 | - } | 97 | + private final DefaultLwM2MTransportMsgHandler serviceImpl; |
108 | 98 | ||
109 | @PostConstruct | 99 | @PostConstruct |
110 | public void init() { | 100 | public void init() { |
111 | this.converter = LwM2mValueConverterImpl.getInstance(); | 101 | this.converter = LwM2mValueConverterImpl.getInstance(); |
112 | - executorResponse = Executors.newFixedThreadPool(this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResponsePoolSize(), | 102 | + executorResponse = Executors.newFixedThreadPool(this.config.getResponsePoolSize(), |
113 | new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL))); | 103 | new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL))); |
114 | } | 104 | } |
115 | 105 | ||
@@ -125,7 +115,6 @@ public class LwM2mTransportRequest { | @@ -125,7 +115,6 @@ public class LwM2mTransportRequest { | ||
125 | public void sendAllRequest(Registration registration, String targetIdVer, LwM2mTypeOper typeOper, | 115 | public void sendAllRequest(Registration registration, String targetIdVer, LwM2mTypeOper typeOper, |
126 | String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { | 116 | String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { |
127 | try { | 117 | try { |
128 | - | ||
129 | String target = convertPathFromIdVerToObjectId(targetIdVer); | 118 | String target = convertPathFromIdVerToObjectId(targetIdVer); |
130 | DownlinkRequest request = null; | 119 | DownlinkRequest request = null; |
131 | ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT; | 120 | ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT; |
@@ -145,11 +134,11 @@ public class LwM2mTransportRequest { | @@ -145,11 +134,11 @@ public class LwM2mTransportRequest { | ||
145 | break; | 134 | break; |
146 | case OBSERVE: | 135 | case OBSERVE: |
147 | if (resultIds.isResource()) { | 136 | if (resultIds.isResource()) { |
148 | - request = new ObserveRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId()); | 137 | + request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId()); |
149 | } else if (resultIds.isObjectInstance()) { | 138 | } else if (resultIds.isObjectInstance()) { |
150 | - request = new ObserveRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId()); | 139 | + request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId()); |
151 | } else if (resultIds.getObjectId() >= 0) { | 140 | } else if (resultIds.getObjectId() >= 0) { |
152 | - request = new ObserveRequest(resultIds.getObjectId()); | 141 | + request = new ObserveRequest(contentFormat, resultIds.getObjectId()); |
153 | } | 142 | } |
154 | break; | 143 | break; |
155 | case OBSERVE_CANCEL: | 144 | case OBSERVE_CANCEL: |
@@ -158,10 +147,10 @@ public class LwM2mTransportRequest { | @@ -158,10 +147,10 @@ public class LwM2mTransportRequest { | ||
158 | * At server side this will not remove the observation from the observation store, to do it you need to use | 147 | * At server side this will not remove the observation from the observation store, to do it you need to use |
159 | * {@code ObservationService#cancelObservation()} | 148 | * {@code ObservationService#cancelObservation()} |
160 | */ | 149 | */ |
161 | - leshanServer.getObservationService().cancelObservations(registration, target); | 150 | + context.getServer().getObservationService().cancelObservations(registration, target); |
162 | break; | 151 | break; |
163 | case EXECUTE: | 152 | case EXECUTE: |
164 | - resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer() | 153 | + resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config |
165 | .getModelProvider()); | 154 | .getModelProvider()); |
166 | if (params != null && !resourceModel.multiple) { | 155 | if (params != null && !resourceModel.multiple) { |
167 | request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resourceModel.type, ResourceModel.Type.STRING, resultIds)); | 156 | request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resourceModel.type, ResourceModel.Type.STRING, resultIds)); |
@@ -171,9 +160,7 @@ public class LwM2mTransportRequest { | @@ -171,9 +160,7 @@ public class LwM2mTransportRequest { | ||
171 | break; | 160 | break; |
172 | case WRITE_REPLACE: | 161 | case WRITE_REPLACE: |
173 | // Request to write a <b>String Single-Instance Resource</b> using the TLV content format. | 162 | // Request to write a <b>String Single-Instance Resource</b> using the TLV content format. |
174 | -// resource = lwM2MClient.getResourceModel(targetIdVer); | ||
175 | -// if (contentFormat.equals(ContentFormat.TLV) && !resource.multiple) { | ||
176 | - resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer() | 163 | + resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config |
177 | .getModelProvider()); | 164 | .getModelProvider()); |
178 | if (contentFormat.equals(ContentFormat.TLV)) { | 165 | if (contentFormat.equals(ContentFormat.TLV)) { |
179 | request = this.getWriteRequestSingleResource(null, resultIds.getObjectId(), | 166 | request = this.getWriteRequestSingleResource(null, resultIds.getObjectId(), |
@@ -181,7 +168,6 @@ public class LwM2mTransportRequest { | @@ -181,7 +168,6 @@ public class LwM2mTransportRequest { | ||
181 | registration, rpcRequest); | 168 | registration, rpcRequest); |
182 | } | 169 | } |
183 | // Mode.REPLACE && Request to write a <b>String Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON) | 170 | // Mode.REPLACE && Request to write a <b>String Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON) |
184 | -// else if (!contentFormat.equals(ContentFormat.TLV) && !resource.multiple) { | ||
185 | else if (!contentFormat.equals(ContentFormat.TLV)) { | 171 | else if (!contentFormat.equals(ContentFormat.TLV)) { |
186 | request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), | 172 | request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), |
187 | resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModel.type, | 173 | resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModel.type, |
@@ -215,13 +201,16 @@ public class LwM2mTransportRequest { | @@ -215,13 +201,16 @@ public class LwM2mTransportRequest { | ||
215 | long finalTimeoutInMs = timeoutInMs; | 201 | long finalTimeoutInMs = timeoutInMs; |
216 | lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, rpcRequest)); | 202 | lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, rpcRequest)); |
217 | } catch (Exception e) { | 203 | } catch (Exception e) { |
218 | - log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper, e); | 204 | + log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper.name(), e); |
205 | + } | ||
206 | + } else if (OBSERVE_CANCEL == typeOper) { | ||
207 | + log.trace("[{}], [{}] - [{}] SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer); | ||
208 | + if (rpcRequest != null) { | ||
209 | + rpcRequest.setInfoMsg(null); | ||
210 | + serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), null, null); | ||
219 | } | 211 | } |
220 | - } else if (OBSERVE_CANCEL == typeOper && rpcRequest != null) { | ||
221 | - rpcRequest.setInfoMsg(null); | ||
222 | - serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), null, null); | ||
223 | } else { | 212 | } else { |
224 | - log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper, targetIdVer); | 213 | + log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer); |
225 | if (rpcRequest != null) { | 214 | if (rpcRequest != null) { |
226 | String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null"; | 215 | String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null"; |
227 | serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); | 216 | serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); |
@@ -232,12 +221,12 @@ public class LwM2mTransportRequest { | @@ -232,12 +221,12 @@ public class LwM2mTransportRequest { | ||
232 | serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); | 221 | serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); |
233 | } | 222 | } |
234 | } else if (OBSERVE_READ_ALL.name().equals(typeOper.name())) { | 223 | } else if (OBSERVE_READ_ALL.name().equals(typeOper.name())) { |
235 | - Set<Observation> observations = leshanServer.getObservationService().getObservations(registration); | 224 | + Set<Observation> observations = context.getServer().getObservationService().getObservations(registration); |
236 | Set<String> observationPaths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet()); | 225 | Set<String> observationPaths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet()); |
237 | String msg = String.format("%s: type operation %s observation paths - %s", LOG_LW2M_INFO, | 226 | String msg = String.format("%s: type operation %s observation paths - %s", LOG_LW2M_INFO, |
238 | OBSERVE_READ_ALL.type, observationPaths); | 227 | OBSERVE_READ_ALL.type, observationPaths); |
239 | - serviceImpl.sendLogsToThingsboard(msg, registration); | ||
240 | - log.info("[{}], [{}]", registration.getEndpoint(), msg); | 228 | + serviceImpl.sendLogsToThingsboard(msg, registration.getId()); |
229 | + log.trace("[{}] [{}], [{}]", typeOper.name(), registration.getEndpoint(), msg); | ||
241 | if (rpcRequest != null) { | 230 | if (rpcRequest != null) { |
242 | String valueMsg = String.format("Observation paths - %s", observationPaths); | 231 | String valueMsg = String.format("Observation paths - %s", observationPaths); |
243 | serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE); | 232 | serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE); |
@@ -246,7 +235,7 @@ public class LwM2mTransportRequest { | @@ -246,7 +235,7 @@ public class LwM2mTransportRequest { | ||
246 | } catch (Exception e) { | 235 | } catch (Exception e) { |
247 | String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR, | 236 | String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR, |
248 | typeOper.name(), e.getMessage()); | 237 | typeOper.name(), e.getMessage()); |
249 | - serviceImpl.sendLogsToThingsboard(msg, registration); | 238 | + serviceImpl.sendLogsToThingsboard(msg, registration.getId()); |
250 | throw new Exception(e); | 239 | throw new Exception(e); |
251 | } | 240 | } |
252 | } | 241 | } |
@@ -259,47 +248,55 @@ public class LwM2mTransportRequest { | @@ -259,47 +248,55 @@ public class LwM2mTransportRequest { | ||
259 | 248 | ||
260 | @SuppressWarnings("unchecked") | 249 | @SuppressWarnings("unchecked") |
261 | private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { | 250 | private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { |
262 | - leshanServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> { | 251 | + context.getServer().send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> { |
263 | if (!lwM2MClient.isInit()) { | 252 | if (!lwM2MClient.isInit()) { |
264 | - lwM2MClient.initValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); | 253 | + lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); |
265 | } | 254 | } |
266 | if (CoAP.ResponseCode.isSuccess(((Response) response.getCoapResponse()).getCode())) { | 255 | if (CoAP.ResponseCode.isSuccess(((Response) response.getCoapResponse()).getCode())) { |
267 | this.handleResponse(registration, request.getPath().toString(), response, request, rpcRequest); | 256 | this.handleResponse(registration, request.getPath().toString(), response, request, rpcRequest); |
268 | - if (request instanceof WriteRequest && ((WriteRequest) request).isReplaceRequest()) { | ||
269 | - LwM2mNode node = ((WriteRequest) request).getNode(); | ||
270 | - Object value = this.converter.convertValue(((LwM2mSingleResource) node).getValue(), | ||
271 | - ((LwM2mSingleResource) node).getType(), ResourceModel.Type.STRING, request.getPath()); | ||
272 | - String msg = String.format("%s: sendRequest Replace: CoapCde - %s Lwm2m code - %d name - %s Resource path - %s value - %s SendRequest to Client", | ||
273 | - LOG_LW2M_INFO, ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(), | ||
274 | - response.getCode().getName(), request.getPath().toString(), value); | ||
275 | - serviceImpl.sendLogsToThingsboard(msg, registration); | ||
276 | - log.info("[{}] [{}] - [{}] [{}] Update SendRequest[{}]", registration.getEndpoint(), | ||
277 | - ((Response) response.getCoapResponse()).getCode(), response.getCode(), | ||
278 | - request.getPath().toString(), value); | ||
279 | - serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, LOG_LW2M_INFO); | ||
280 | - } | ||
281 | } else { | 257 | } else { |
282 | - String msg = String.format("%s: sendRequest: CoapCode - %s Lwm2m code - %d name - %s Resource path - %s SendRequest to Client", LOG_LW2M_ERROR, | 258 | + 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()); | 259 | ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(), response.getCode().getName(), request.getPath().toString()); |
284 | - serviceImpl.sendLogsToThingsboard(msg, registration); | ||
285 | - log.error("[{}], [{}] - [{}] [{}] error SendRequest", registration.getEndpoint(), ((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString()); | 260 | + serviceImpl.sendLogsToThingsboard(msg, registration.getId()); |
261 | + log.error("[{}] [{}], [{}] - [{}] [{}] error SendRequest", request.getClass().getName().toString(), registration.getEndpoint(), | ||
262 | + ((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString()); | ||
263 | + if (!lwM2MClient.isInit()) { | ||
264 | + lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); | ||
265 | + } | ||
286 | if (rpcRequest != null) { | 266 | if (rpcRequest != null) { |
287 | serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR); | 267 | serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR); |
288 | } | 268 | } |
269 | + /** Not Found | ||
270 | + * set setClient_fw_version = empty | ||
271 | + **/ | ||
272 | + if (FR_PATH_RESOURCE_VER_ID.equals(request.getPath().toString()) && lwM2MClient.isUpdateFw()) { | ||
273 | + lwM2MClient.setUpdateFw(false); | ||
274 | + lwM2MClient.getFrUpdate().setClientFwVersion(""); | ||
275 | + log.warn("updateFirmwareClient1"); | ||
276 | + serviceImpl.updateFirmwareClient(lwM2MClient); | ||
277 | + } | ||
289 | } | 278 | } |
290 | }, e -> { | 279 | }, e -> { |
280 | + /** version == null | ||
281 | + * set setClient_fw_version = empty | ||
282 | + **/ | ||
283 | + if (FR_PATH_RESOURCE_VER_ID.equals(request.getPath().toString()) && lwM2MClient.isUpdateFw()) { | ||
284 | + lwM2MClient.setUpdateFw(false); | ||
285 | + lwM2MClient.getFrUpdate().setClientFwVersion(""); | ||
286 | + log.warn("updateFirmwareClient2"); | ||
287 | + serviceImpl.updateFirmwareClient(lwM2MClient); | ||
288 | + } | ||
291 | if (!lwM2MClient.isInit()) { | 289 | if (!lwM2MClient.isInit()) { |
292 | - lwM2MClient.initValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); | 290 | + lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); |
293 | } | 291 | } |
294 | - String msg = String.format("%s: sendRequest: Resource path - %s msg error - %s SendRequest to Client", | ||
295 | - LOG_LW2M_ERROR, request.getPath().toString(), e.getMessage()); | ||
296 | - serviceImpl.sendLogsToThingsboard(msg, registration); | ||
297 | - log.error("[{}] - [{}] error SendRequest", request.getPath().toString(), e.toString()); | 292 | + String msg = String.format("%s: SendRequest %s: Resource path - %s msg error - %s", |
293 | + LOG_LW2M_ERROR, request.getClass().getName().toString(), request.getPath().toString(), e.getMessage()); | ||
294 | + serviceImpl.sendLogsToThingsboard(msg, registration.getId()); | ||
295 | + log.error("[{}] [{}] - [{}] error SendRequest", request.getClass().getName().toString(), request.getPath().toString(), e.toString()); | ||
298 | if (rpcRequest != null) { | 296 | if (rpcRequest != null) { |
299 | serviceImpl.sentRpcRequest(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR); | 297 | serviceImpl.sentRpcRequest(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR); |
300 | } | 298 | } |
301 | }); | 299 | }); |
302 | - | ||
303 | } | 300 | } |
304 | 301 | ||
305 | private WriteRequest getWriteRequestSingleResource(ContentFormat contentFormat, Integer objectId, Integer instanceId, | 302 | private WriteRequest getWriteRequestSingleResource(ContentFormat contentFormat, Integer objectId, Integer instanceId, |
@@ -323,7 +320,9 @@ public class LwM2mTransportRequest { | @@ -323,7 +320,9 @@ public class LwM2mTransportRequest { | ||
323 | Date date = new Date(Long.decode(value.toString())); | 320 | Date date = new Date(Long.decode(value.toString())); |
324 | return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, date) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, date); | 321 | return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, date) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, date); |
325 | case OPAQUE: // byte[] value, base64 | 322 | case OPAQUE: // byte[] value, base64 |
326 | - return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, Hex.decodeHex(value.toString().toCharArray())) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, Hex.decodeHex(value.toString().toCharArray())); | 323 | + byte[] valueRequest = value instanceof byte[] ? (byte[]) value : Hex.decodeHex(value.toString().toCharArray()); |
324 | + return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, valueRequest) : | ||
325 | + new WriteRequest(contentFormat, objectId, instanceId, resourceId, valueRequest); | ||
327 | default: | 326 | default: |
328 | } | 327 | } |
329 | } | 328 | } |
@@ -337,7 +336,7 @@ public class LwM2mTransportRequest { | @@ -337,7 +336,7 @@ public class LwM2mTransportRequest { | ||
337 | String patn = "/" + objectId + "/" + instanceId + "/" + resourceId; | 336 | String patn = "/" + objectId + "/" + instanceId + "/" + resourceId; |
338 | String msg = String.format(LOG_LW2M_ERROR + ": NumberFormatException: Resource path - %s type - %s value - %s msg error - %s SendRequest to Client", | 337 | String msg = String.format(LOG_LW2M_ERROR + ": NumberFormatException: Resource path - %s type - %s value - %s msg error - %s SendRequest to Client", |
339 | patn, type, value, e.toString()); | 338 | patn, type, value, e.toString()); |
340 | - serviceImpl.sendLogsToThingsboard(msg, registration); | 339 | + serviceImpl.sendLogsToThingsboard(msg, registration.getId()); |
341 | log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString()); | 340 | log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString()); |
342 | if (rpcRequest != null) { | 341 | if (rpcRequest != null) { |
343 | String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value); | 342 | String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value); |
@@ -369,7 +368,7 @@ public class LwM2mTransportRequest { | @@ -369,7 +368,7 @@ public class LwM2mTransportRequest { | ||
369 | DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { | 368 | DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { |
370 | String pathIdVer = convertPathFromObjectIdToIdVer(path, registration); | 369 | String pathIdVer = convertPathFromObjectIdToIdVer(path, registration); |
371 | if (response instanceof ReadResponse) { | 370 | if (response instanceof ReadResponse) { |
372 | - serviceImpl.onObservationResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest); | 371 | + serviceImpl.onUpdateValueAfterReadResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest); |
373 | } else if (response instanceof CancelObservationResponse) { | 372 | } else if (response instanceof CancelObservationResponse) { |
374 | log.info("[{}] Path [{}] CancelObservationResponse 3_Send", pathIdVer, response); | 373 | log.info("[{}] Path [{}] CancelObservationResponse 3_Send", pathIdVer, response); |
375 | 374 | ||
@@ -389,14 +388,56 @@ public class LwM2mTransportRequest { | @@ -389,14 +388,56 @@ public class LwM2mTransportRequest { | ||
389 | } else if (response instanceof WriteAttributesResponse) { | 388 | } else if (response instanceof WriteAttributesResponse) { |
390 | log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response); | 389 | log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response); |
391 | } else if (response instanceof WriteResponse) { | 390 | } else if (response instanceof WriteResponse) { |
392 | - log.info("[{}] Path [{}] WriteAttributesResponse 9_Send", pathIdVer, response); | 391 | + log.info("[{}] Path [{}] WriteResponse 9_Send", pathIdVer, response); |
392 | + this.infoWriteResponse(registration, response, request); | ||
393 | serviceImpl.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request); | 393 | serviceImpl.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request); |
394 | } | 394 | } |
395 | - if (rpcRequest != null && (response instanceof ExecuteResponse | ||
396 | - || response instanceof WriteAttributesResponse | ||
397 | - || response instanceof DeleteResponse)) { | ||
398 | - rpcRequest.setInfoMsg(null); | ||
399 | - serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, null); | 395 | + if (rpcRequest != null) { |
396 | + if (response instanceof ExecuteResponse | ||
397 | + || response instanceof WriteAttributesResponse | ||
398 | + || response instanceof DeleteResponse) { | ||
399 | + rpcRequest.setInfoMsg(null); | ||
400 | + serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, null); | ||
401 | + } else if (response instanceof WriteResponse) { | ||
402 | + serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, LOG_LW2M_INFO); | ||
403 | + } | ||
404 | + } | ||
405 | + } | ||
406 | + | ||
407 | + private void infoWriteResponse(Registration registration, LwM2mResponse response, DownlinkRequest request) { | ||
408 | + try { | ||
409 | + LwM2mNode node = ((WriteRequest) request).getNode(); | ||
410 | + String msg; | ||
411 | + Object value; | ||
412 | + LwM2mSingleResource singleResource = (LwM2mSingleResource) node; | ||
413 | + if (singleResource.getType() == ResourceModel.Type.STRING || singleResource.getType() == ResourceModel.Type.OPAQUE) { | ||
414 | + int valueLength; | ||
415 | + if (singleResource.getType() == ResourceModel.Type.STRING) { | ||
416 | + valueLength = ((String) singleResource.getValue()).length(); | ||
417 | + value = ((String) singleResource.getValue()) | ||
418 | + .substring(Math.min(valueLength, config.getLogMaxLength())); | ||
419 | + | ||
420 | + } else { | ||
421 | + valueLength = ((byte[]) singleResource.getValue()).length; | ||
422 | + value = new String(Arrays.copyOf(((byte[]) singleResource.getValue()), | ||
423 | + Math.min(valueLength, config.getLogMaxLength()))); | ||
424 | + } | ||
425 | + value = valueLength > config.getLogMaxLength() ? value + "..." : value; | ||
426 | + msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path - %s length - %s value - %s", | ||
427 | + LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), valueLength, value); | ||
428 | + } else { | ||
429 | + value = this.converter.convertValue(singleResource.getValue(), | ||
430 | + singleResource.getType(), ResourceModel.Type.STRING, request.getPath()); | ||
431 | + msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path - %s value - %s", | ||
432 | + LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), value); | ||
433 | + } | ||
434 | + if (msg != null) { | ||
435 | + serviceImpl.sendLogsToThingsboard(msg, registration.getId()); | ||
436 | + log.warn("[{}] [{}] [{}] - [{}] [{}] Update finished successfully: [{}]", request.getClass().getName(), registration.getEndpoint(), | ||
437 | + ((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString(), value); | ||
438 | + } | ||
439 | + } catch (Exception e) { | ||
440 | + log.trace("Fail convert value from request to string. ", e); | ||
400 | } | 441 | } |
401 | } | 442 | } |
402 | } | 443 | } |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java
renamed from
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java
@@ -31,6 +31,7 @@ package org.thingsboard.server.transport.lwm2m.server; | @@ -31,6 +31,7 @@ package org.thingsboard.server.transport.lwm2m.server; | ||
31 | */ | 31 | */ |
32 | 32 | ||
33 | import lombok.Getter; | 33 | import lombok.Getter; |
34 | +import lombok.RequiredArgsConstructor; | ||
34 | import lombok.extern.slf4j.Slf4j; | 35 | import lombok.extern.slf4j.Slf4j; |
35 | import org.eclipse.leshan.core.model.DDFFileParser; | 36 | import org.eclipse.leshan.core.model.DDFFileParser; |
36 | import org.eclipse.leshan.core.model.DefaultDDFFileValidator; | 37 | import org.eclipse.leshan.core.model.DefaultDDFFileValidator; |
@@ -39,11 +40,8 @@ import org.eclipse.leshan.core.model.ObjectModel; | @@ -39,11 +40,8 @@ import org.eclipse.leshan.core.model.ObjectModel; | ||
39 | import org.eclipse.leshan.core.model.ResourceModel; | 40 | import org.eclipse.leshan.core.model.ResourceModel; |
40 | import org.eclipse.leshan.core.node.codec.CodecException; | 41 | import org.eclipse.leshan.core.node.codec.CodecException; |
41 | import org.springframework.stereotype.Component; | 42 | import org.springframework.stereotype.Component; |
42 | -import org.thingsboard.server.common.transport.TransportContext; | ||
43 | -import org.thingsboard.server.common.transport.TransportResourceCache; | ||
44 | import org.thingsboard.server.common.transport.TransportService; | 43 | import org.thingsboard.server.common.transport.TransportService; |
45 | import org.thingsboard.server.common.transport.TransportServiceCallback; | 44 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
46 | -import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer; | ||
47 | import org.thingsboard.server.gen.transport.TransportProtos; | 45 | import org.thingsboard.server.gen.transport.TransportProtos; |
48 | import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; | 46 | import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; |
49 | import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; | 47 | import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; |
@@ -57,39 +55,21 @@ import java.util.ArrayList; | @@ -57,39 +55,21 @@ import java.util.ArrayList; | ||
57 | import java.util.List; | 55 | import java.util.List; |
58 | 56 | ||
59 | import static org.thingsboard.server.gen.transport.TransportProtos.KeyValueType.BOOLEAN_V; | 57 | import static org.thingsboard.server.gen.transport.TransportProtos.KeyValueType.BOOLEAN_V; |
60 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY; | 58 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LOG_LW2M_TELEMETRY; |
61 | 59 | ||
62 | @Slf4j | 60 | @Slf4j |
63 | @Component | 61 | @Component |
64 | @TbLwM2mTransportComponent | 62 | @TbLwM2mTransportComponent |
65 | -public class LwM2mTransportContextServer extends TransportContext { | 63 | +@RequiredArgsConstructor |
64 | +public class LwM2mTransportServerHelper { | ||
66 | 65 | ||
67 | - | ||
68 | - private final LwM2MTransportConfigServer lwM2MTransportConfigServer; | 66 | + private final LwM2mTransportContext context; |
69 | 67 | ||
70 | private final TransportService transportService; | 68 | private final TransportService transportService; |
71 | 69 | ||
72 | - private final TransportResourceCache transportResourceCache; | ||
73 | - | ||
74 | - | ||
75 | @Getter | 70 | @Getter |
76 | private final LwM2MJsonAdaptor adaptor; | 71 | private final LwM2MJsonAdaptor adaptor; |
77 | 72 | ||
78 | - public LwM2mTransportContextServer(LwM2MTransportConfigServer lwM2MTransportConfigServer, TransportService transportService, TransportResourceCache transportResourceCache, LwM2MJsonAdaptor adaptor) { | ||
79 | - this.lwM2MTransportConfigServer = lwM2MTransportConfigServer; | ||
80 | - this.transportService = transportService; | ||
81 | - this.transportResourceCache = transportResourceCache; | ||
82 | - this.adaptor = adaptor; | ||
83 | - } | ||
84 | - | ||
85 | - public LwM2MTransportConfigServer getLwM2MTransportConfigServer() { | ||
86 | - return this.lwM2MTransportConfigServer; | ||
87 | - } | ||
88 | - | ||
89 | - public TransportResourceCache getTransportResourceCache() { | ||
90 | - return this.transportResourceCache; | ||
91 | - } | ||
92 | - | ||
93 | /** | 73 | /** |
94 | * send to Thingsboard Attribute || Telemetry | 74 | * send to Thingsboard Attribute || Telemetry |
95 | * | 75 | * |
@@ -134,7 +114,7 @@ public class LwM2mTransportContextServer extends TransportContext { | @@ -134,7 +114,7 @@ public class LwM2mTransportContextServer extends TransportContext { | ||
134 | */ | 114 | */ |
135 | public SessionInfoProto getValidateSessionInfo(TransportProtos.ValidateDeviceCredentialsResponseMsg msg, long mostSignificantBits, long leastSignificantBits) { | 115 | public SessionInfoProto getValidateSessionInfo(TransportProtos.ValidateDeviceCredentialsResponseMsg msg, long mostSignificantBits, long leastSignificantBits) { |
136 | return SessionInfoProto.newBuilder() | 116 | return SessionInfoProto.newBuilder() |
137 | - .setNodeId(this.getNodeId()) | 117 | + .setNodeId(context.getNodeId()) |
138 | .setSessionIdMSB(mostSignificantBits) | 118 | .setSessionIdMSB(mostSignificantBits) |
139 | .setSessionIdLSB(leastSignificantBits) | 119 | .setSessionIdLSB(leastSignificantBits) |
140 | .setDeviceIdMSB(msg.getDeviceInfo().getDeviceIdMSB()) | 120 | .setDeviceIdMSB(msg.getDeviceInfo().getDeviceIdMSB()) |
@@ -165,8 +145,8 @@ public class LwM2mTransportContextServer extends TransportContext { | @@ -165,8 +145,8 @@ public class LwM2mTransportContextServer extends TransportContext { | ||
165 | * @param logMsg - info about Logs | 145 | * @param logMsg - info about Logs |
166 | * @return- KeyValueProto for telemetry (Logs) | 146 | * @return- KeyValueProto for telemetry (Logs) |
167 | */ | 147 | */ |
168 | - public List <TransportProtos.KeyValueProto> getKvLogyToThingsboard(String logMsg) { | ||
169 | - List <TransportProtos.KeyValueProto> result = new ArrayList<>(); | 148 | + public List<TransportProtos.KeyValueProto> getKvLogyToThingsboard(String logMsg) { |
149 | + List<TransportProtos.KeyValueProto> result = new ArrayList<>(); | ||
170 | result.add(TransportProtos.KeyValueProto.newBuilder() | 150 | result.add(TransportProtos.KeyValueProto.newBuilder() |
171 | .setKey(LOG_LW2M_TELEMETRY) | 151 | .setKey(LOG_LW2M_TELEMETRY) |
172 | .setType(TransportProtos.KeyValueType.STRING_V) | 152 | .setType(TransportProtos.KeyValueType.STRING_V) |
@@ -179,32 +159,31 @@ public class LwM2mTransportContextServer extends TransportContext { | @@ -179,32 +159,31 @@ public class LwM2mTransportContextServer extends TransportContext { | ||
179 | * @throws CodecException - | 159 | * @throws CodecException - |
180 | */ | 160 | */ |
181 | 161 | ||
182 | - public TransportProtos.KeyValueProto getKvAttrTelemetryToThingsboard(ResourceModel.Type resourceType, String resourceName, Object value, boolean isMultiInstances) { | ||
183 | - TransportProtos.KeyValueProto.Builder kvProto = TransportProtos.KeyValueProto.newBuilder().setKey(resourceName); | ||
184 | - if (isMultiInstances) { | ||
185 | - kvProto.setType(TransportProtos.KeyValueType.JSON_V) | ||
186 | - .setJsonV((String) value); | 162 | + public TransportProtos.KeyValueProto getKvAttrTelemetryToThingsboard(ResourceModel.Type resourceType, String resourceName, Object value, boolean isMultiInstances) { |
163 | + TransportProtos.KeyValueProto.Builder kvProto = TransportProtos.KeyValueProto.newBuilder().setKey(resourceName); | ||
164 | + if (isMultiInstances) { | ||
165 | + kvProto.setType(TransportProtos.KeyValueType.JSON_V) | ||
166 | + .setJsonV((String) value); | ||
167 | + } else { | ||
168 | + switch (resourceType) { | ||
169 | + case BOOLEAN: | ||
170 | + kvProto.setType(BOOLEAN_V).setBoolV((Boolean) value).build(); | ||
171 | + break; | ||
172 | + case STRING: | ||
173 | + case TIME: | ||
174 | + case OPAQUE: | ||
175 | + case OBJLNK: | ||
176 | + kvProto.setType(TransportProtos.KeyValueType.STRING_V).setStringV((String) value); | ||
177 | + break; | ||
178 | + case INTEGER: | ||
179 | + kvProto.setType(TransportProtos.KeyValueType.LONG_V).setLongV((Long) value); | ||
180 | + break; | ||
181 | + case FLOAT: | ||
182 | + kvProto.setType(TransportProtos.KeyValueType.DOUBLE_V).setDoubleV((Double) value); | ||
187 | } | 183 | } |
188 | - else { | ||
189 | - switch (resourceType) { | ||
190 | - case BOOLEAN: | ||
191 | - kvProto.setType(BOOLEAN_V).setBoolV((Boolean) value).build(); | ||
192 | - break; | ||
193 | - case STRING: | ||
194 | - case TIME: | ||
195 | - case OPAQUE: | ||
196 | - case OBJLNK: | ||
197 | - kvProto.setType(TransportProtos.KeyValueType.STRING_V).setStringV((String) value); | ||
198 | - break; | ||
199 | - case INTEGER: | ||
200 | - kvProto.setType(TransportProtos.KeyValueType.LONG_V).setLongV((Long) value); | ||
201 | - break; | ||
202 | - case FLOAT: | ||
203 | - kvProto.setType(TransportProtos.KeyValueType.DOUBLE_V).setDoubleV((Double) value); | ||
204 | - } | ||
205 | - } | ||
206 | - return kvProto.build(); | ||
207 | } | 184 | } |
185 | + return kvProto.build(); | ||
186 | + } | ||
208 | 187 | ||
209 | /** | 188 | /** |
210 | * | 189 | * |
@@ -230,7 +209,7 @@ public class LwM2mTransportContextServer extends TransportContext { | @@ -230,7 +209,7 @@ public class LwM2mTransportContextServer extends TransportContext { | ||
230 | throw new CodecException("Invalid ResourceModel_Type for resource %s, got %s", resourcePath, currentType); | 209 | throw new CodecException("Invalid ResourceModel_Type for resource %s, got %s", resourcePath, currentType); |
231 | } | 210 | } |
232 | 211 | ||
233 | - public Object getValueFromKvProto (TransportProtos.KeyValueProto kv) { | 212 | + public Object getValueFromKvProto(TransportProtos.KeyValueProto kv) { |
234 | switch (kv.getType()) { | 213 | switch (kv.getType()) { |
235 | case BOOLEAN_V: | 214 | case BOOLEAN_V: |
236 | return kv.getBoolV(); | 215 | return kv.getBoolV(); |
@@ -30,35 +30,4 @@ import javax.annotation.PreDestroy; | @@ -30,35 +30,4 @@ import javax.annotation.PreDestroy; | ||
30 | @TbLwM2mTransportComponent | 30 | @TbLwM2mTransportComponent |
31 | public class LwM2mTransportServerInitializer { | 31 | public class LwM2mTransportServerInitializer { |
32 | 32 | ||
33 | - @Autowired | ||
34 | - private LwM2mTransportServiceImpl service; | ||
35 | - | ||
36 | - @Autowired | ||
37 | - private LeshanServer leshanServer; | ||
38 | - | ||
39 | - @Autowired | ||
40 | - private LwM2mTransportContextServer context; | ||
41 | - | ||
42 | - @PostConstruct | ||
43 | - public void init() { | ||
44 | - if (this.context.getLwM2MTransportConfigServer().getEnableGenNewKeyPskRpk()) { | ||
45 | - new LWM2MGenerationPSkRPkECC(); | ||
46 | - } | ||
47 | - this.startLhServer(); | ||
48 | - } | ||
49 | - | ||
50 | - private void startLhServer() { | ||
51 | - this.leshanServer.start(); | ||
52 | - LwM2mServerListener lhServerCertListener = new LwM2mServerListener(service); | ||
53 | - this.leshanServer.getRegistrationService().addListener(lhServerCertListener.registrationListener); | ||
54 | - this.leshanServer.getPresenceService().addListener(lhServerCertListener.presenceListener); | ||
55 | - this.leshanServer.getObservationService().addListener(lhServerCertListener.observationListener); | ||
56 | - } | ||
57 | - | ||
58 | - @PreDestroy | ||
59 | - public void shutdown() { | ||
60 | - log.info("Stopping LwM2M transport Server!"); | ||
61 | - leshanServer.destroy(); | ||
62 | - log.info("LwM2M transport Server stopped!"); | ||
63 | - } | ||
64 | } | 33 | } |
@@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.transport.lwm2m.server; | 16 | package org.thingsboard.server.transport.lwm2m.server; |
17 | 17 | ||
18 | +import lombok.RequiredArgsConstructor; | ||
18 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
19 | import org.eclipse.leshan.core.model.DefaultDDFFileValidator; | 20 | import org.eclipse.leshan.core.model.DefaultDDFFileValidator; |
20 | import org.eclipse.leshan.core.model.LwM2mModel; | 21 | import org.eclipse.leshan.core.model.LwM2mModel; |
@@ -37,6 +38,7 @@ import static org.thingsboard.server.common.data.ResourceType.LWM2M_MODEL; | @@ -37,6 +38,7 @@ import static org.thingsboard.server.common.data.ResourceType.LWM2M_MODEL; | ||
37 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; | 38 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; |
38 | 39 | ||
39 | @Slf4j | 40 | @Slf4j |
41 | +@RequiredArgsConstructor | ||
40 | public class LwM2mVersionedModelProvider implements LwM2mModelProvider { | 42 | public class LwM2mVersionedModelProvider implements LwM2mModelProvider { |
41 | 43 | ||
42 | /** | 44 | /** |
@@ -46,12 +48,8 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { | @@ -46,12 +48,8 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { | ||
46 | * Value = TenantId | 48 | * Value = TenantId |
47 | */ | 49 | */ |
48 | private final LwM2mClientContext lwM2mClientContext; | 50 | private final LwM2mClientContext lwM2mClientContext; |
49 | - private final LwM2mTransportContextServer lwM2mTransportContextServer; | ||
50 | - | ||
51 | - public LwM2mVersionedModelProvider(LwM2mClientContext lwM2mClientContext, LwM2mTransportContextServer lwM2mTransportContextServer) { | ||
52 | - this.lwM2mClientContext = lwM2mClientContext; | ||
53 | - this.lwM2mTransportContextServer = lwM2mTransportContextServer; | ||
54 | - } | 51 | + private final LwM2mTransportServerHelper helper; |
52 | + private final LwM2mTransportContext context; | ||
55 | 53 | ||
56 | private String getKeyIdVer(Integer objectId, String version) { | 54 | private String getKeyIdVer(Integer objectId, String version) { |
57 | return objectId != null ? objectId + LWM2M_SEPARATOR_KEY + ((version == null || version.isEmpty()) ? ObjectModel.DEFAULT_VERSION : version) : null; | 55 | return objectId != null ? objectId + LWM2M_SEPARATOR_KEY + ((version == null || version.isEmpty()) ? ObjectModel.DEFAULT_VERSION : version) : null; |
@@ -120,11 +118,9 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { | @@ -120,11 +118,9 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { | ||
120 | private ObjectModel getObjectModelDynamic(Integer objectId, String version) { | 118 | private ObjectModel getObjectModelDynamic(Integer objectId, String version) { |
121 | String key = getKeyIdVer(objectId, version); | 119 | String key = getKeyIdVer(objectId, version); |
122 | 120 | ||
123 | - Optional<TbResource> tbResource = lwM2mTransportContextServer | ||
124 | - .getTransportResourceCache() | ||
125 | - .get(this.tenantId, LWM2M_MODEL, key); | 121 | + Optional<TbResource> tbResource = context.getTransportResourceCache().get(this.tenantId, LWM2M_MODEL, key); |
126 | 122 | ||
127 | - return tbResource.map(resource -> lwM2mTransportContextServer.parseFromXmlToObjectModel( | 123 | + return tbResource.map(resource -> helper.parseFromXmlToObjectModel( |
128 | Base64.getDecoder().decode(resource.getData()), | 124 | Base64.getDecoder().decode(resource.getData()), |
129 | key + ".xml", | 125 | key + ".xml", |
130 | new DefaultDDFFileValidator())).orElse(null); | 126 | new DefaultDDFFileValidator())).orElse(null); |
@@ -24,11 +24,8 @@ import org.thingsboard.server.common.transport.adaptor.AdaptorException; | @@ -24,11 +24,8 @@ import org.thingsboard.server.common.transport.adaptor.AdaptorException; | ||
24 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; | 24 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
25 | import org.thingsboard.server.gen.transport.TransportProtos; | 25 | import org.thingsboard.server.gen.transport.TransportProtos; |
26 | 26 | ||
27 | -import java.util.Arrays; | ||
28 | -import java.util.HashSet; | ||
29 | -import java.util.List; | 27 | +import java.util.Collection; |
30 | import java.util.Random; | 28 | import java.util.Random; |
31 | -import java.util.Set; | ||
32 | 29 | ||
33 | @Slf4j | 30 | @Slf4j |
34 | @Component("LwM2MJsonAdaptor") | 31 | @Component("LwM2MJsonAdaptor") |
@@ -54,11 +51,7 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor { | @@ -54,11 +51,7 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor { | ||
54 | } | 51 | } |
55 | 52 | ||
56 | @Override | 53 | @Override |
57 | - public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(List<String> clientKeys, List<String> sharedKeys) throws AdaptorException { | ||
58 | - return processGetAttributeRequestMsg(clientKeys, sharedKeys); | ||
59 | - } | ||
60 | - | ||
61 | - protected TransportProtos.GetAttributeRequestMsg processGetAttributeRequestMsg(List<String> clientKeys, List<String> sharedKeys) throws AdaptorException { | 54 | + public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(Collection<String> clientKeys, Collection<String> sharedKeys) throws AdaptorException { |
62 | try { | 55 | try { |
63 | TransportProtos.GetAttributeRequestMsg.Builder result = TransportProtos.GetAttributeRequestMsg.newBuilder(); | 56 | TransportProtos.GetAttributeRequestMsg.Builder result = TransportProtos.GetAttributeRequestMsg.newBuilder(); |
64 | Random random = new Random(); | 57 | Random random = new Random(); |
@@ -75,14 +68,4 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor { | @@ -75,14 +68,4 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor { | ||
75 | throw new AdaptorException(e); | 68 | throw new AdaptorException(e); |
76 | } | 69 | } |
77 | } | 70 | } |
78 | - | ||
79 | - private Set<String> toStringSet(JsonElement requestBody, String name) { | ||
80 | - JsonElement element = requestBody.getAsJsonObject().get(name); | ||
81 | - if (element != null) { | ||
82 | - return new HashSet<>(Arrays.asList(element.getAsString().split(","))); | ||
83 | - } else { | ||
84 | - return null; | ||
85 | - } | ||
86 | - } | ||
87 | - | ||
88 | } | 71 | } |
@@ -19,7 +19,7 @@ import com.google.gson.JsonElement; | @@ -19,7 +19,7 @@ import com.google.gson.JsonElement; | ||
19 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; | 19 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
20 | import org.thingsboard.server.gen.transport.TransportProtos; | 20 | import org.thingsboard.server.gen.transport.TransportProtos; |
21 | 21 | ||
22 | -import java.util.List; | 22 | +import java.util.Collection; |
23 | 23 | ||
24 | public interface LwM2MTransportAdaptor { | 24 | public interface LwM2MTransportAdaptor { |
25 | 25 | ||
@@ -27,5 +27,5 @@ public interface LwM2MTransportAdaptor { | @@ -27,5 +27,5 @@ public interface LwM2MTransportAdaptor { | ||
27 | 27 | ||
28 | TransportProtos.PostAttributeMsg convertToPostAttributes(JsonElement jsonElement) throws AdaptorException; | 28 | TransportProtos.PostAttributeMsg convertToPostAttributes(JsonElement jsonElement) throws AdaptorException; |
29 | 29 | ||
30 | - TransportProtos.GetAttributeRequestMsg convertToGetAttributes(List<String> clientKeys, List<String> sharedKeys) throws AdaptorException; | 30 | + TransportProtos.GetAttributeRequestMsg convertToGetAttributes(Collection<String> clientKeys, Collection<String> sharedKeys) throws AdaptorException; |
31 | } | 31 | } |
@@ -27,7 +27,7 @@ import org.eclipse.leshan.server.security.SecurityInfo; | @@ -27,7 +27,7 @@ import org.eclipse.leshan.server.security.SecurityInfo; | ||
27 | import org.thingsboard.server.gen.transport.TransportProtos; | 27 | import org.thingsboard.server.gen.transport.TransportProtos; |
28 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; | 28 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; |
29 | import org.thingsboard.server.transport.lwm2m.server.LwM2mQueuedRequest; | 29 | import org.thingsboard.server.transport.lwm2m.server.LwM2mQueuedRequest; |
30 | -import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServiceImpl; | 30 | +import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2MTransportMsgHandler; |
31 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; | 31 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; |
32 | 32 | ||
33 | import java.util.Collection; | 33 | import java.util.Collection; |
@@ -42,9 +42,9 @@ import java.util.concurrent.CopyOnWriteArrayList; | @@ -42,9 +42,9 @@ import java.util.concurrent.CopyOnWriteArrayList; | ||
42 | import java.util.stream.Collectors; | 42 | import java.util.stream.Collectors; |
43 | 43 | ||
44 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; | 44 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; |
45 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.TRANSPORT_DEFAULT_LWM2M_VERSION; | ||
46 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromIdVerToObjectId; | ||
47 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getVerFromPathIdVerOrId; | 45 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.TRANSPORT_DEFAULT_LWM2M_VERSION; |
46 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.convertPathFromIdVerToObjectId; | ||
47 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.getVerFromPathIdVerOrId; | ||
48 | 48 | ||
49 | @Slf4j | 49 | @Slf4j |
50 | @Data | 50 | @Data |
@@ -57,13 +57,15 @@ public class LwM2mClient implements Cloneable { | @@ -57,13 +57,15 @@ public class LwM2mClient implements Cloneable { | ||
57 | private UUID deviceId; | 57 | private UUID deviceId; |
58 | private UUID sessionId; | 58 | private UUID sessionId; |
59 | private UUID profileId; | 59 | private UUID profileId; |
60 | + private volatile LwM2mFirmwareUpdate frUpdate; | ||
60 | private Registration registration; | 61 | private Registration registration; |
61 | private ValidateDeviceCredentialsResponseMsg credentialsResponse; | 62 | private ValidateDeviceCredentialsResponseMsg credentialsResponse; |
62 | private final Map<String, ResourceValue> resources; | 63 | private final Map<String, ResourceValue> resources; |
63 | private final Map<String, TransportProtos.TsKvProto> delayedRequests; | 64 | private final Map<String, TransportProtos.TsKvProto> delayedRequests; |
64 | - private final List<String> pendingRequests; | 65 | + private final List<String> pendingReadRequests; |
65 | private final Queue<LwM2mQueuedRequest> queuedRequests; | 66 | private final Queue<LwM2mQueuedRequest> queuedRequests; |
66 | private boolean init; | 67 | private boolean init; |
68 | + private volatile boolean updateFw; | ||
67 | 69 | ||
68 | public Object clone() throws CloneNotSupportedException { | 70 | public Object clone() throws CloneNotSupportedException { |
69 | return super.clone(); | 71 | return super.clone(); |
@@ -75,12 +77,14 @@ public class LwM2mClient implements Cloneable { | @@ -75,12 +77,14 @@ public class LwM2mClient implements Cloneable { | ||
75 | this.securityInfo = securityInfo; | 77 | this.securityInfo = securityInfo; |
76 | this.credentialsResponse = credentialsResponse; | 78 | this.credentialsResponse = credentialsResponse; |
77 | this.delayedRequests = new ConcurrentHashMap<>(); | 79 | this.delayedRequests = new ConcurrentHashMap<>(); |
78 | - this.pendingRequests = new CopyOnWriteArrayList<>(); | 80 | + this.pendingReadRequests = new CopyOnWriteArrayList<>(); |
79 | this.resources = new ConcurrentHashMap<>(); | 81 | this.resources = new ConcurrentHashMap<>(); |
80 | this.profileId = profileId; | 82 | this.profileId = profileId; |
81 | this.sessionId = sessionId; | 83 | this.sessionId = sessionId; |
82 | this.init = false; | 84 | this.init = false; |
85 | + this.updateFw = false; | ||
83 | this.queuedRequests = new ConcurrentLinkedQueue<>(); | 86 | this.queuedRequests = new ConcurrentLinkedQueue<>(); |
87 | + this.frUpdate = new LwM2mFirmwareUpdate(); | ||
84 | } | 88 | } |
85 | 89 | ||
86 | public boolean saveResourceValue(String pathRez, LwM2mResource rez, LwM2mModelProvider modelProvider) { | 90 | public boolean saveResourceValue(String pathRez, LwM2mResource rez, LwM2mModelProvider modelProvider) { |
@@ -103,15 +107,13 @@ public class LwM2mClient implements Cloneable { | @@ -103,15 +107,13 @@ public class LwM2mClient implements Cloneable { | ||
103 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez)); | 107 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez)); |
104 | String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); | 108 | String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); |
105 | String verRez = getVerFromPathIdVerOrId(pathRez); | 109 | String verRez = getVerFromPathIdVerOrId(pathRez); |
106 | - return (verRez == null || verSupportedObject.equals(verRez)) ? modelProvider.getObjectModel(registration) | 110 | + return verRez == null || verRez.equals(verSupportedObject) ? modelProvider.getObjectModel(registration) |
107 | .getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()) : null; | 111 | .getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()) : null; |
108 | } | 112 | } |
109 | 113 | ||
110 | public Collection<LwM2mResource> getNewResourcesForInstance(String pathRezIdVer, LwM2mModelProvider modelProvider, | 114 | public Collection<LwM2mResource> getNewResourcesForInstance(String pathRezIdVer, LwM2mModelProvider modelProvider, |
111 | LwM2mValueConverterImpl converter) { | 115 | LwM2mValueConverterImpl converter) { |
112 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer)); | 116 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer)); |
113 | - String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); | ||
114 | - String verRez = getVerFromPathIdVerOrId(pathRezIdVer); | ||
115 | Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet(); | 117 | Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet(); |
116 | Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration) | 118 | Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration) |
117 | .getObjectModel(pathIds.getObjectId()).resources; | 119 | .getObjectModel(pathIds.getObjectId()).resources; |
@@ -170,11 +172,11 @@ public class LwM2mClient implements Cloneable { | @@ -170,11 +172,11 @@ public class LwM2mClient implements Cloneable { | ||
170 | .collect(Collectors.toSet()); | 172 | .collect(Collectors.toSet()); |
171 | } | 173 | } |
172 | 174 | ||
173 | - public void initValue(LwM2mTransportServiceImpl serviceImpl, String path) { | 175 | + public void initReadValue(DefaultLwM2MTransportMsgHandler serviceImpl, String path) { |
174 | if (path != null) { | 176 | if (path != null) { |
175 | - this.pendingRequests.remove(path); | 177 | + this.pendingReadRequests.remove(path); |
176 | } | 178 | } |
177 | - if (this.pendingRequests.size() == 0) { | 179 | + if (this.pendingReadRequests.size() == 0) { |
178 | this.init = true; | 180 | this.init = true; |
179 | serviceImpl.putDelayedUpdateResourcesThingsboard(this); | 181 | serviceImpl.putDelayedUpdateResourcesThingsboard(this); |
180 | } | 182 | } |
@@ -25,7 +25,7 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | @@ -25,7 +25,7 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | ||
25 | import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; | 25 | import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; |
26 | import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; | 26 | import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; |
27 | import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore; | 27 | import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore; |
28 | -import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler; | 28 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil; |
29 | 29 | ||
30 | import java.util.Arrays; | 30 | import java.util.Arrays; |
31 | import java.util.Map; | 31 | import java.util.Map; |
@@ -34,7 +34,7 @@ import java.util.UUID; | @@ -34,7 +34,7 @@ import java.util.UUID; | ||
34 | import java.util.concurrent.ConcurrentHashMap; | 34 | import java.util.concurrent.ConcurrentHashMap; |
35 | 35 | ||
36 | import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC; | 36 | import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC; |
37 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromObjectIdToIdVer; | 37 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.convertPathFromObjectIdToIdVer; |
38 | 38 | ||
39 | @Service | 39 | @Service |
40 | @TbLwM2mTransportComponent | 40 | @TbLwM2mTransportComponent |
@@ -82,12 +82,12 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { | @@ -82,12 +82,12 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { | ||
82 | 82 | ||
83 | @Override | 83 | @Override |
84 | public LwM2mClient getLwM2mClientWithReg(Registration registration, String registrationId) { | 84 | public LwM2mClient getLwM2mClientWithReg(Registration registration, String registrationId) { |
85 | - LwM2mClient client = registrationId != null ? | 85 | + LwM2mClient client = registrationId != null && this.lwM2mClients.containsKey(registrationId) ? |
86 | this.lwM2mClients.get(registrationId) : | 86 | this.lwM2mClients.get(registrationId) : |
87 | - this.lwM2mClients.containsKey(registration.getId()) ? | ||
88 | - this.lwM2mClients.get(registration.getId()) : | ||
89 | - this.lwM2mClients.get(registration.getEndpoint()); | ||
90 | - return client != null ? client : updateInSessionsLwM2MClient(registration); | 87 | + registration !=null && this.lwM2mClients.containsKey(registration.getId()) ? |
88 | + this.lwM2mClients.get(registration.getId()) : registration !=null && this.lwM2mClients.containsKey(registration) ? | ||
89 | + this.lwM2mClients.get(registration.getEndpoint()) : null; | ||
90 | + return client != null ? client : registration!= null ? updateInSessionsLwM2MClient(registration) : null; | ||
91 | } | 91 | } |
92 | 92 | ||
93 | @Override | 93 | @Override |
@@ -118,7 +118,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { | @@ -118,7 +118,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { | ||
118 | */ | 118 | */ |
119 | @Override | 119 | @Override |
120 | public LwM2mClient addLwM2mClientToSession(String identity) { | 120 | public LwM2mClient addLwM2mClientToSession(String identity) { |
121 | - ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(identity, LwM2mTransportHandler.LwM2mTypeServer.CLIENT); | 121 | + ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(identity, LwM2mTransportHandlerUtil.LwM2mTypeServer.CLIENT); |
122 | if (store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { | 122 | if (store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { |
123 | UUID profileUuid = (store.getDeviceProfile() != null && addUpdateProfileParameters(store.getDeviceProfile())) ? store.getDeviceProfile().getUuidId() : null; | 123 | UUID profileUuid = (store.getDeviceProfile() != null && addUpdateProfileParameters(store.getDeviceProfile())) ? store.getDeviceProfile().getUuidId() : null; |
124 | LwM2mClient client; | 124 | LwM2mClient client; |
@@ -165,7 +165,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { | @@ -165,7 +165,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { | ||
165 | 165 | ||
166 | @Override | 166 | @Override |
167 | public boolean addUpdateProfileParameters(DeviceProfile deviceProfile) { | 167 | public boolean addUpdateProfileParameters(DeviceProfile deviceProfile) { |
168 | - LwM2mClientProfile lwM2MClientProfile = LwM2mTransportHandler.getLwM2MClientProfileFromThingsboard(deviceProfile); | 168 | + LwM2mClientProfile lwM2MClientProfile = LwM2mTransportHandlerUtil.getLwM2MClientProfileFromThingsboard(deviceProfile); |
169 | if (lwM2MClientProfile != null) { | 169 | if (lwM2MClientProfile != null) { |
170 | profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile); | 170 | profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile); |
171 | return true; | 171 | return true; |
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 | +} |
@@ -21,11 +21,11 @@ import org.eclipse.leshan.core.request.ContentFormat; | @@ -21,11 +21,11 @@ import org.eclipse.leshan.core.request.ContentFormat; | ||
21 | import org.eclipse.leshan.server.registration.Registration; | 21 | import org.eclipse.leshan.server.registration.Registration; |
22 | import org.thingsboard.server.gen.transport.TransportProtos; | 22 | import org.thingsboard.server.gen.transport.TransportProtos; |
23 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; | 23 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
24 | -import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LwM2mTypeOper; | 24 | +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper; |
25 | 25 | ||
26 | import java.util.concurrent.ConcurrentHashMap; | 26 | import java.util.concurrent.ConcurrentHashMap; |
27 | 27 | ||
28 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.validPathIdVer; | 28 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.validPathIdVer; |
29 | 29 | ||
30 | @Data | 30 | @Data |
31 | public class Lwm2mClientRpcRequest { | 31 | public class Lwm2mClientRpcRequest { |
common/transport/lwm2m/src/main/resources/lwm2mserver.jks
renamed from
common/transport/lwm2m/src/main/resources/credentials/serverKeyStore.jks
No preview for this file type
@@ -47,6 +47,7 @@ import org.thingsboard.server.common.data.DeviceProfile; | @@ -47,6 +47,7 @@ import org.thingsboard.server.common.data.DeviceProfile; | ||
47 | import org.thingsboard.server.common.data.DeviceTransportType; | 47 | import org.thingsboard.server.common.data.DeviceTransportType; |
48 | import org.thingsboard.server.common.data.TransportPayloadType; | 48 | import org.thingsboard.server.common.data.TransportPayloadType; |
49 | import org.thingsboard.server.common.data.device.profile.MqttTopics; | 49 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
50 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
50 | import org.thingsboard.server.common.data.id.FirmwareId; | 51 | import org.thingsboard.server.common.data.id.FirmwareId; |
51 | import org.thingsboard.server.common.msg.EncryptionUtil; | 52 | import org.thingsboard.server.common.msg.EncryptionUtil; |
52 | import org.thingsboard.server.common.msg.tools.TbRateLimitsException; | 53 | import org.thingsboard.server.common.msg.tools.TbRateLimitsException; |
@@ -59,6 +60,7 @@ import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; | @@ -59,6 +60,7 @@ import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; | ||
59 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; | 60 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
60 | import org.thingsboard.server.common.transport.service.DefaultTransportService; | 61 | import org.thingsboard.server.common.transport.service.DefaultTransportService; |
61 | import org.thingsboard.server.common.transport.service.SessionMetaData; | 62 | import org.thingsboard.server.common.transport.service.SessionMetaData; |
63 | +import org.thingsboard.server.common.transport.util.SslUtil; | ||
62 | import org.thingsboard.server.gen.transport.TransportProtos; | 64 | import org.thingsboard.server.gen.transport.TransportProtos; |
63 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; | 65 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; |
64 | import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent; | 66 | import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent; |
@@ -68,7 +70,6 @@ import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor; | @@ -68,7 +70,6 @@ import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor; | ||
68 | import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx; | 70 | import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx; |
69 | import org.thingsboard.server.transport.mqtt.session.GatewaySessionHandler; | 71 | import org.thingsboard.server.transport.mqtt.session.GatewaySessionHandler; |
70 | import org.thingsboard.server.transport.mqtt.session.MqttTopicMatcher; | 72 | import org.thingsboard.server.transport.mqtt.session.MqttTopicMatcher; |
71 | -import org.thingsboard.server.common.transport.util.SslUtil; | ||
72 | 73 | ||
73 | import javax.net.ssl.SSLPeerUnverifiedException; | 74 | import javax.net.ssl.SSLPeerUnverifiedException; |
74 | import java.io.IOException; | 75 | import java.io.IOException; |
@@ -97,6 +98,8 @@ import static io.netty.handler.codec.mqtt.MqttMessageType.UNSUBACK; | @@ -97,6 +98,8 @@ import static io.netty.handler.codec.mqtt.MqttMessageType.UNSUBACK; | ||
97 | import static io.netty.handler.codec.mqtt.MqttQoS.AT_LEAST_ONCE; | 98 | import static io.netty.handler.codec.mqtt.MqttQoS.AT_LEAST_ONCE; |
98 | import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE; | 99 | import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE; |
99 | import static io.netty.handler.codec.mqtt.MqttQoS.FAILURE; | 100 | import static io.netty.handler.codec.mqtt.MqttQoS.FAILURE; |
101 | +import static org.thingsboard.server.common.data.device.profile.MqttTopics.DEVICE_FIRMWARE_REQUEST_TOPIC_PATTERN; | ||
102 | +import static org.thingsboard.server.common.data.device.profile.MqttTopics.DEVICE_SOFTWARE_REQUEST_TOPIC_PATTERN; | ||
100 | 103 | ||
101 | /** | 104 | /** |
102 | * @author Andrew Shvayka | 105 | * @author Andrew Shvayka |
@@ -104,7 +107,9 @@ import static io.netty.handler.codec.mqtt.MqttQoS.FAILURE; | @@ -104,7 +107,9 @@ import static io.netty.handler.codec.mqtt.MqttQoS.FAILURE; | ||
104 | @Slf4j | 107 | @Slf4j |
105 | public class MqttTransportHandler extends ChannelInboundHandlerAdapter implements GenericFutureListener<Future<? super Void>>, SessionMsgListener { | 108 | public class MqttTransportHandler extends ChannelInboundHandlerAdapter implements GenericFutureListener<Future<? super Void>>, SessionMsgListener { |
106 | 109 | ||
107 | - private static final Pattern FW_PATTERN = Pattern.compile("v2/fw/request/(?<requestId>\\d+)/chunk/(?<chunk>\\d+)"); | 110 | + private static final Pattern FW_REQUEST_PATTERN = Pattern.compile(DEVICE_FIRMWARE_REQUEST_TOPIC_PATTERN); |
111 | + private static final Pattern SW_REQUEST_PATTERN = Pattern.compile(DEVICE_SOFTWARE_REQUEST_TOPIC_PATTERN); | ||
112 | + | ||
108 | 113 | ||
109 | private static final String PAYLOAD_TOO_LARGE = "PAYLOAD_TOO_LARGE"; | 114 | private static final String PAYLOAD_TOO_LARGE = "PAYLOAD_TOO_LARGE"; |
110 | 115 | ||
@@ -314,38 +319,10 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -314,38 +319,10 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
314 | } else if (topicName.equals(MqttTopics.DEVICE_CLAIM_TOPIC)) { | 319 | } else if (topicName.equals(MqttTopics.DEVICE_CLAIM_TOPIC)) { |
315 | TransportProtos.ClaimDeviceMsg claimDeviceMsg = payloadAdaptor.convertToClaimDevice(deviceSessionCtx, mqttMsg); | 320 | TransportProtos.ClaimDeviceMsg claimDeviceMsg = payloadAdaptor.convertToClaimDevice(deviceSessionCtx, mqttMsg); |
316 | transportService.process(deviceSessionCtx.getSessionInfo(), claimDeviceMsg, getPubAckCallback(ctx, msgId, claimDeviceMsg)); | 321 | transportService.process(deviceSessionCtx.getSessionInfo(), claimDeviceMsg, getPubAckCallback(ctx, msgId, claimDeviceMsg)); |
317 | - } else if ((fwMatcher = FW_PATTERN.matcher(topicName)).find()) { | ||
318 | - String payload = mqttMsg.content().toString(UTF8); | ||
319 | - int chunkSize = StringUtils.isNotEmpty(payload) ? Integer.parseInt(payload) : 0; | ||
320 | - String requestId = fwMatcher.group("requestId"); | ||
321 | - int chunk = Integer.parseInt(fwMatcher.group("chunk")); | ||
322 | - | ||
323 | - if (chunkSize > 0) { | ||
324 | - this.fwChunkSizes.put(requestId, chunkSize); | ||
325 | - } else { | ||
326 | - chunkSize = fwChunkSizes.getOrDefault(requestId, 0); | ||
327 | - } | ||
328 | - | ||
329 | - if (chunkSize > context.getMaxPayloadSize()) { | ||
330 | - sendFirmwareError(ctx, PAYLOAD_TOO_LARGE); | ||
331 | - return; | ||
332 | - } | ||
333 | - | ||
334 | - String firmwareId = fwSessions.get(requestId); | ||
335 | - | ||
336 | - if (firmwareId != null) { | ||
337 | - sendFirmware(ctx, mqttMsg.variableHeader().packetId(), firmwareId, requestId, chunkSize, chunk); | ||
338 | - } else { | ||
339 | - TransportProtos.SessionInfoProto sessionInfo = deviceSessionCtx.getSessionInfo(); | ||
340 | - TransportProtos.GetFirmwareRequestMsg getFirmwareRequestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder() | ||
341 | - .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) | ||
342 | - .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) | ||
343 | - .setTenantIdMSB(sessionInfo.getTenantIdMSB()) | ||
344 | - .setTenantIdLSB(sessionInfo.getTenantIdLSB()) | ||
345 | - .build(); | ||
346 | - transportService.process(deviceSessionCtx.getSessionInfo(), getFirmwareRequestMsg, | ||
347 | - new FirmwareCallback(ctx, mqttMsg.variableHeader().packetId(), getFirmwareRequestMsg, requestId, chunkSize, chunk)); | ||
348 | - } | 322 | + } else if ((fwMatcher = FW_REQUEST_PATTERN.matcher(topicName)).find()) { |
323 | + getFirmwareCallback(ctx, mqttMsg, msgId, fwMatcher, FirmwareType.FIRMWARE); | ||
324 | + } else if ((fwMatcher = SW_REQUEST_PATTERN.matcher(topicName)).find()) { | ||
325 | + getFirmwareCallback(ctx, mqttMsg, msgId, fwMatcher, FirmwareType.SOFTWARE); | ||
349 | } else { | 326 | } else { |
350 | transportService.reportActivity(deviceSessionCtx.getSessionInfo()); | 327 | transportService.reportActivity(deviceSessionCtx.getSessionInfo()); |
351 | ack(ctx, msgId); | 328 | ack(ctx, msgId); |
@@ -357,6 +334,41 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -357,6 +334,41 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
357 | } | 334 | } |
358 | } | 335 | } |
359 | 336 | ||
337 | + private void getFirmwareCallback(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg, int msgId, Matcher fwMatcher, FirmwareType type) { | ||
338 | + String payload = mqttMsg.content().toString(UTF8); | ||
339 | + int chunkSize = StringUtils.isNotEmpty(payload) ? Integer.parseInt(payload) : 0; | ||
340 | + String requestId = fwMatcher.group("requestId"); | ||
341 | + int chunk = Integer.parseInt(fwMatcher.group("chunk")); | ||
342 | + | ||
343 | + if (chunkSize > 0) { | ||
344 | + this.fwChunkSizes.put(requestId, chunkSize); | ||
345 | + } else { | ||
346 | + chunkSize = fwChunkSizes.getOrDefault(requestId, 0); | ||
347 | + } | ||
348 | + | ||
349 | + if (chunkSize > context.getMaxPayloadSize()) { | ||
350 | + sendFirmwareError(ctx, PAYLOAD_TOO_LARGE); | ||
351 | + return; | ||
352 | + } | ||
353 | + | ||
354 | + String firmwareId = fwSessions.get(requestId); | ||
355 | + | ||
356 | + if (firmwareId != null) { | ||
357 | + sendFirmware(ctx, mqttMsg.variableHeader().packetId(), firmwareId, requestId, chunkSize, chunk, type); | ||
358 | + } else { | ||
359 | + TransportProtos.SessionInfoProto sessionInfo = deviceSessionCtx.getSessionInfo(); | ||
360 | + TransportProtos.GetFirmwareRequestMsg getFirmwareRequestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder() | ||
361 | + .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) | ||
362 | + .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) | ||
363 | + .setTenantIdMSB(sessionInfo.getTenantIdMSB()) | ||
364 | + .setTenantIdLSB(sessionInfo.getTenantIdLSB()) | ||
365 | + .setType(type.name()) | ||
366 | + .build(); | ||
367 | + transportService.process(deviceSessionCtx.getSessionInfo(), getFirmwareRequestMsg, | ||
368 | + new FirmwareCallback(ctx, msgId, getFirmwareRequestMsg, requestId, chunkSize, chunk)); | ||
369 | + } | ||
370 | + } | ||
371 | + | ||
360 | private void ack(ChannelHandlerContext ctx, int msgId) { | 372 | private void ack(ChannelHandlerContext ctx, int msgId) { |
361 | if (msgId > 0) { | 373 | if (msgId > 0) { |
362 | ctx.writeAndFlush(createMqttPubAckMsg(msgId)); | 374 | ctx.writeAndFlush(createMqttPubAckMsg(msgId)); |
@@ -435,7 +447,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -435,7 +447,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
435 | if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())) { | 447 | if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())) { |
436 | FirmwareId firmwareId = new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())); | 448 | FirmwareId firmwareId = new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())); |
437 | fwSessions.put(requestId, firmwareId.toString()); | 449 | fwSessions.put(requestId, firmwareId.toString()); |
438 | - sendFirmware(ctx, msgId, firmwareId.toString(), requestId, chunkSize, chunk); | 450 | + sendFirmware(ctx, msgId, firmwareId.toString(), requestId, chunkSize, chunk, FirmwareType.valueOf(response.getType())); |
439 | } else { | 451 | } else { |
440 | sendFirmwareError(ctx, response.getResponseStatus().toString()); | 452 | sendFirmwareError(ctx, response.getResponseStatus().toString()); |
441 | } | 453 | } |
@@ -448,13 +460,13 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -448,13 +460,13 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
448 | } | 460 | } |
449 | } | 461 | } |
450 | 462 | ||
451 | - private void sendFirmware(ChannelHandlerContext ctx, int msgId, String firmwareId, String requestId, int chunkSize, int chunk) { | 463 | + private void sendFirmware(ChannelHandlerContext ctx, int msgId, String firmwareId, String requestId, int chunkSize, int chunk, FirmwareType type) { |
452 | log.trace("[{}] Send firmware [{}] to device!", sessionId, firmwareId); | 464 | log.trace("[{}] Send firmware [{}] to device!", sessionId, firmwareId); |
453 | ack(ctx, msgId); | 465 | ack(ctx, msgId); |
454 | try { | 466 | try { |
455 | byte[] firmwareChunk = context.getFirmwareDataCache().get(firmwareId, chunkSize, chunk); | 467 | byte[] firmwareChunk = context.getFirmwareDataCache().get(firmwareId, chunkSize, chunk); |
456 | deviceSessionCtx.getPayloadAdaptor() | 468 | deviceSessionCtx.getPayloadAdaptor() |
457 | - .convertToPublish(deviceSessionCtx, firmwareChunk, requestId, chunk) | 469 | + .convertToPublish(deviceSessionCtx, firmwareChunk, requestId, chunk, type) |
458 | .ifPresent(deviceSessionCtx.getChannel()::writeAndFlush); | 470 | .ifPresent(deviceSessionCtx.getChannel()::writeAndFlush); |
459 | if (firmwareChunk != null && chunkSize != firmwareChunk.length) { | 471 | if (firmwareChunk != null && chunkSize != firmwareChunk.length) { |
460 | scheduler.schedule(() -> processDisconnect(ctx), 60, TimeUnit.SECONDS); | 472 | scheduler.schedule(() -> processDisconnect(ctx), 60, TimeUnit.SECONDS); |
@@ -504,6 +516,8 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -504,6 +516,8 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
504 | case MqttTopics.DEVICE_PROVISION_RESPONSE_TOPIC: | 516 | case MqttTopics.DEVICE_PROVISION_RESPONSE_TOPIC: |
505 | case MqttTopics.DEVICE_FIRMWARE_RESPONSES_TOPIC: | 517 | case MqttTopics.DEVICE_FIRMWARE_RESPONSES_TOPIC: |
506 | case MqttTopics.DEVICE_FIRMWARE_ERROR_TOPIC: | 518 | case MqttTopics.DEVICE_FIRMWARE_ERROR_TOPIC: |
519 | + case MqttTopics.DEVICE_SOFTWARE_RESPONSES_TOPIC: | ||
520 | + case MqttTopics.DEVICE_SOFTWARE_ERROR_TOPIC: | ||
507 | registerSubQoS(topic, grantedQoSList, reqQoS); | 521 | registerSubQoS(topic, grantedQoSList, reqQoS); |
508 | break; | 522 | break; |
509 | default: | 523 | default: |
@@ -30,6 +30,7 @@ import lombok.extern.slf4j.Slf4j; | @@ -30,6 +30,7 @@ import lombok.extern.slf4j.Slf4j; | ||
30 | import org.springframework.stereotype.Component; | 30 | import org.springframework.stereotype.Component; |
31 | import org.springframework.util.StringUtils; | 31 | import org.springframework.util.StringUtils; |
32 | import org.thingsboard.server.common.data.device.profile.MqttTopics; | 32 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
33 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
33 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; | 34 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
34 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; | 35 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
35 | import org.thingsboard.server.gen.transport.TransportProtos; | 36 | import org.thingsboard.server.gen.transport.TransportProtos; |
@@ -43,6 +44,9 @@ import java.util.Optional; | @@ -43,6 +44,9 @@ import java.util.Optional; | ||
43 | import java.util.Set; | 44 | import java.util.Set; |
44 | import java.util.UUID; | 45 | import java.util.UUID; |
45 | 46 | ||
47 | +import static org.thingsboard.server.common.data.device.profile.MqttTopics.DEVICE_FIRMWARE_RESPONSES_TOPIC_FORMAT; | ||
48 | + | ||
49 | + | ||
46 | /** | 50 | /** |
47 | * @author Andrew Shvayka | 51 | * @author Andrew Shvayka |
48 | */ | 52 | */ |
@@ -151,8 +155,8 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { | @@ -151,8 +155,8 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { | ||
151 | } | 155 | } |
152 | 156 | ||
153 | @Override | 157 | @Override |
154 | - public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk) { | ||
155 | - return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_FIRMWARE_RESPONSE_TOPIC_PREFIX + requestId + "/chunk/" + chunk, firmwareChunk)); | 158 | + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, FirmwareType firmwareType) { |
159 | + return Optional.of(createMqttPublishMsg(ctx, String.format(DEVICE_FIRMWARE_RESPONSES_TOPIC_FORMAT, firmwareType.getKeyPrefix(), requestId, chunk), firmwareChunk)); | ||
156 | } | 160 | } |
157 | 161 | ||
158 | public static JsonElement validateJsonPayload(UUID sessionId, ByteBuf payloadData) throws AdaptorException { | 162 | public static JsonElement validateJsonPayload(UUID sessionId, ByteBuf payloadData) throws AdaptorException { |
@@ -23,6 +23,7 @@ import io.netty.handler.codec.mqtt.MqttMessage; | @@ -23,6 +23,7 @@ import io.netty.handler.codec.mqtt.MqttMessage; | ||
23 | import io.netty.handler.codec.mqtt.MqttMessageType; | 23 | import io.netty.handler.codec.mqtt.MqttMessageType; |
24 | import io.netty.handler.codec.mqtt.MqttPublishMessage; | 24 | import io.netty.handler.codec.mqtt.MqttPublishMessage; |
25 | import io.netty.handler.codec.mqtt.MqttPublishVariableHeader; | 25 | import io.netty.handler.codec.mqtt.MqttPublishVariableHeader; |
26 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
26 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; | 27 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
27 | import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; | 28 | import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; |
28 | import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg; | 29 | import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg; |
@@ -77,7 +78,7 @@ public interface MqttTransportAdaptor { | @@ -77,7 +78,7 @@ public interface MqttTransportAdaptor { | ||
77 | 78 | ||
78 | Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, ProvisionDeviceResponseMsg provisionResponse) throws AdaptorException; | 79 | Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, ProvisionDeviceResponseMsg provisionResponse) throws AdaptorException; |
79 | 80 | ||
80 | - Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk) throws AdaptorException; | 81 | + Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, FirmwareType firmwareType) throws AdaptorException; |
81 | 82 | ||
82 | default MqttPublishMessage createMqttPublishMsg(MqttDeviceAwareSessionContext ctx, String topic, byte[] payloadInBytes) { | 83 | default MqttPublishMessage createMqttPublishMsg(MqttDeviceAwareSessionContext ctx, String topic, byte[] payloadInBytes) { |
83 | MqttFixedHeader mqttFixedHeader = | 84 | MqttFixedHeader mqttFixedHeader = |
@@ -28,6 +28,7 @@ import lombok.extern.slf4j.Slf4j; | @@ -28,6 +28,7 @@ import lombok.extern.slf4j.Slf4j; | ||
28 | import org.springframework.stereotype.Component; | 28 | import org.springframework.stereotype.Component; |
29 | import org.springframework.util.StringUtils; | 29 | import org.springframework.util.StringUtils; |
30 | import org.thingsboard.server.common.data.device.profile.MqttTopics; | 30 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
31 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
31 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; | 32 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
32 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; | 33 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
33 | import org.thingsboard.server.common.transport.adaptor.ProtoConverter; | 34 | import org.thingsboard.server.common.transport.adaptor.ProtoConverter; |
@@ -38,6 +39,8 @@ import org.thingsboard.server.transport.mqtt.session.MqttDeviceAwareSessionConte | @@ -38,6 +39,8 @@ import org.thingsboard.server.transport.mqtt.session.MqttDeviceAwareSessionConte | ||
38 | 39 | ||
39 | import java.util.Optional; | 40 | import java.util.Optional; |
40 | 41 | ||
42 | +import static org.thingsboard.server.common.data.device.profile.MqttTopics.DEVICE_FIRMWARE_RESPONSES_TOPIC_FORMAT; | ||
43 | + | ||
41 | @Component | 44 | @Component |
42 | @Slf4j | 45 | @Slf4j |
43 | public class ProtoMqttAdaptor implements MqttTransportAdaptor { | 46 | public class ProtoMqttAdaptor implements MqttTransportAdaptor { |
@@ -165,8 +168,8 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | @@ -165,8 +168,8 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { | ||
165 | } | 168 | } |
166 | 169 | ||
167 | @Override | 170 | @Override |
168 | - public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk) throws AdaptorException { | ||
169 | - return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_FIRMWARE_RESPONSE_TOPIC_PREFIX + requestId + "/" + chunk, firmwareChunk)); | 171 | + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, FirmwareType firmwareType) throws AdaptorException { |
172 | + return Optional.of(createMqttPublishMsg(ctx, String.format(DEVICE_FIRMWARE_RESPONSES_TOPIC_FORMAT, firmwareType.getKeyPrefix(), requestId, chunk), firmwareChunk)); | ||
170 | } | 173 | } |
171 | 174 | ||
172 | @Override | 175 | @Override |
@@ -51,11 +51,13 @@ public abstract class TransportContext { | @@ -51,11 +51,13 @@ public abstract class TransportContext { | ||
51 | @Getter | 51 | @Getter |
52 | private ExecutorService executor; | 52 | private ExecutorService executor; |
53 | 53 | ||
54 | - | ||
55 | @Getter | 54 | @Getter |
56 | @Autowired | 55 | @Autowired |
57 | private FirmwareDataCache firmwareDataCache; | 56 | private FirmwareDataCache firmwareDataCache; |
58 | 57 | ||
58 | + @Autowired | ||
59 | + private TransportResourceCache transportResourceCache; | ||
60 | + | ||
59 | @PostConstruct | 61 | @PostConstruct |
60 | public void init() { | 62 | public void init() { |
61 | executor = ThingsBoardExecutors.newWorkStealingPool(50, getClass()); | 63 | executor = ThingsBoardExecutors.newWorkStealingPool(50, getClass()); |
@@ -83,6 +83,8 @@ public interface DeviceDao extends Dao<Device>, TenantEntityDao { | @@ -83,6 +83,8 @@ public interface DeviceDao extends Dao<Device>, TenantEntityDao { | ||
83 | 83 | ||
84 | PageData<Device> findDevicesByTenantIdAndTypeAndEmptyFirmware(UUID tenantId, String type, PageLink pageLink); | 84 | PageData<Device> findDevicesByTenantIdAndTypeAndEmptyFirmware(UUID tenantId, String type, PageLink pageLink); |
85 | 85 | ||
86 | + PageData<Device> findDevicesByTenantIdAndTypeAndEmptySoftware(UUID tenantId, String type, PageLink pageLink); | ||
87 | + | ||
86 | /** | 88 | /** |
87 | * Find device infos by tenantId, type and page link. | 89 | * Find device infos by tenantId, type and page link. |
88 | * | 90 | * |
@@ -56,6 +56,7 @@ import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfilePr | @@ -56,6 +56,7 @@ import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfilePr | ||
56 | import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; | 56 | import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; |
57 | import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; | 57 | import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; |
58 | import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; | 58 | import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; |
59 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
59 | import org.thingsboard.server.common.data.id.DeviceProfileId; | 60 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
60 | import org.thingsboard.server.common.data.id.TenantId; | 61 | import org.thingsboard.server.common.data.id.TenantId; |
61 | import org.thingsboard.server.common.data.page.PageData; | 62 | import org.thingsboard.server.common.data.page.PageData; |
@@ -406,9 +407,31 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | @@ -406,9 +407,31 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D | ||
406 | if (firmware == null) { | 407 | if (firmware == null) { |
407 | throw new DataValidationException("Can't assign non-existent firmware!"); | 408 | throw new DataValidationException("Can't assign non-existent firmware!"); |
408 | } | 409 | } |
410 | + if (!firmware.getType().equals(FirmwareType.FIRMWARE)) { | ||
411 | + throw new DataValidationException("Can't assign firmware with type: " + firmware.getType()); | ||
412 | + } | ||
409 | if (firmware.getData() == null) { | 413 | if (firmware.getData() == null) { |
410 | throw new DataValidationException("Can't assign firmware with empty data!"); | 414 | throw new DataValidationException("Can't assign firmware with empty data!"); |
411 | } | 415 | } |
416 | + if (!firmware.getDeviceProfileId().equals(deviceProfile.getId())) { | ||
417 | + throw new DataValidationException("Can't assign firmware with different deviceProfile!"); | ||
418 | + } | ||
419 | + } | ||
420 | + | ||
421 | + if (deviceProfile.getSoftwareId() != null) { | ||
422 | + Firmware software = firmwareService.findFirmwareById(tenantId, deviceProfile.getSoftwareId()); | ||
423 | + if (software == null) { | ||
424 | + throw new DataValidationException("Can't assign non-existent software!"); | ||
425 | + } | ||
426 | + if (!software.getType().equals(FirmwareType.SOFTWARE)) { | ||
427 | + throw new DataValidationException("Can't assign software with type: " + software.getType()); | ||
428 | + } | ||
429 | + if (software.getData() == null) { | ||
430 | + throw new DataValidationException("Can't assign software with empty data!"); | ||
431 | + } | ||
432 | + if (!software.getDeviceProfileId().equals(deviceProfile.getId())) { | ||
433 | + throw new DataValidationException("Can't assign firmware with different deviceProfile!"); | ||
434 | + } | ||
412 | } | 435 | } |
413 | } | 436 | } |
414 | 437 |
@@ -53,6 +53,7 @@ import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfig | @@ -53,6 +53,7 @@ import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfig | ||
53 | import org.thingsboard.server.common.data.device.data.MqttDeviceTransportConfiguration; | 53 | import org.thingsboard.server.common.data.device.data.MqttDeviceTransportConfiguration; |
54 | import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration; | 54 | import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration; |
55 | import org.thingsboard.server.common.data.edge.Edge; | 55 | import org.thingsboard.server.common.data.edge.Edge; |
56 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | ||
56 | import org.thingsboard.server.common.data.id.CustomerId; | 57 | import org.thingsboard.server.common.data.id.CustomerId; |
57 | import org.thingsboard.server.common.data.id.DeviceId; | 58 | import org.thingsboard.server.common.data.id.DeviceId; |
58 | import org.thingsboard.server.common.data.id.DeviceProfileId; | 59 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
@@ -361,7 +362,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -361,7 +362,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
361 | 362 | ||
362 | @Override | 363 | @Override |
363 | public PageData<Device> findDevicesByTenantIdAndTypeAndEmptyFirmware(TenantId tenantId, String type, PageLink pageLink) { | 364 | public PageData<Device> findDevicesByTenantIdAndTypeAndEmptyFirmware(TenantId tenantId, String type, PageLink pageLink) { |
364 | - log.trace("Executing findDevicesByTenantIdAndType, tenantId [{}], type [{}], pageLink [{}]", tenantId, type, pageLink); | 365 | + log.trace("Executing findDevicesByTenantIdAndTypeAndEmptyFirmware, tenantId [{}], type [{}], pageLink [{}]", tenantId, type, pageLink); |
365 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | 366 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
366 | validateString(type, "Incorrect type " + type); | 367 | validateString(type, "Incorrect type " + type); |
367 | validatePageLink(pageLink); | 368 | validatePageLink(pageLink); |
@@ -369,6 +370,15 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -369,6 +370,15 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
369 | } | 370 | } |
370 | 371 | ||
371 | @Override | 372 | @Override |
373 | + public PageData<Device> findDevicesByTenantIdAndTypeAndEmptySoftware(TenantId tenantId, String type, PageLink pageLink) { | ||
374 | + log.trace("Executing findDevicesByTenantIdAndTypeAndEmptySoftware, tenantId [{}], type [{}], pageLink [{}]", tenantId, type, pageLink); | ||
375 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | ||
376 | + validateString(type, "Incorrect type " + type); | ||
377 | + validatePageLink(pageLink); | ||
378 | + return deviceDao.findDevicesByTenantIdAndTypeAndEmptySoftware(tenantId.getId(), type, pageLink); | ||
379 | + } | ||
380 | + | ||
381 | + @Override | ||
372 | public PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink) { | 382 | public PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink) { |
373 | log.trace("Executing findDeviceInfosByTenantIdAndType, tenantId [{}], type [{}], pageLink [{}]", tenantId, type, pageLink); | 383 | log.trace("Executing findDeviceInfosByTenantIdAndType, tenantId [{}], type [{}], pageLink [{}]", tenantId, type, pageLink); |
374 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | 384 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
@@ -696,9 +706,31 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -696,9 +706,31 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
696 | if (firmware == null) { | 706 | if (firmware == null) { |
697 | throw new DataValidationException("Can't assign non-existent firmware!"); | 707 | throw new DataValidationException("Can't assign non-existent firmware!"); |
698 | } | 708 | } |
709 | + if (!firmware.getType().equals(FirmwareType.FIRMWARE)) { | ||
710 | + throw new DataValidationException("Can't assign firmware with type: " + firmware.getType()); | ||
711 | + } | ||
699 | if (firmware.getData() == null) { | 712 | if (firmware.getData() == null) { |
700 | throw new DataValidationException("Can't assign firmware with empty data!"); | 713 | throw new DataValidationException("Can't assign firmware with empty data!"); |
701 | } | 714 | } |
715 | + if (!firmware.getDeviceProfileId().equals(device.getDeviceProfileId())) { | ||
716 | + throw new DataValidationException("Can't assign firmware with different deviceProfile!"); | ||
717 | + } | ||
718 | + } | ||
719 | + | ||
720 | + if (device.getSoftwareId() != null) { | ||
721 | + Firmware software = firmwareService.findFirmwareById(tenantId, device.getSoftwareId()); | ||
722 | + if (software == null) { | ||
723 | + throw new DataValidationException("Can't assign non-existent software!"); | ||
724 | + } | ||
725 | + if (!software.getType().equals(FirmwareType.SOFTWARE)) { | ||
726 | + throw new DataValidationException("Can't assign software with type: " + software.getType()); | ||
727 | + } | ||
728 | + if (software.getData() == null) { | ||
729 | + throw new DataValidationException("Can't assign software with empty data!"); | ||
730 | + } | ||
731 | + if (!software.getDeviceProfileId().equals(device.getDeviceProfileId())) { | ||
732 | + throw new DataValidationException("Can't assign firmware with different deviceProfile!"); | ||
733 | + } | ||
702 | } | 734 | } |
703 | } | 735 | } |
704 | }; | 736 | }; |