Commit cf405be4f3a350e9fada398d5c775fea41354398

Authored by Igor Kulikov
2 parents 59606f83 8a4c0a71

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 }
@@ -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 };