Commit cf405be4f3a350e9fada398d5c775fea41354398
Merge branch 'master' of github.com:thingsboard/thingsboard
Showing
66 changed files
with
1599 additions
and
938 deletions
Too many changes to show.
To preserve performance only 66 of 140 files are displayed.
... | ... | @@ -63,6 +63,8 @@ CREATE TABLE IF NOT EXISTS firmware ( |
63 | 63 | id uuid NOT NULL CONSTRAINT firmware_pkey PRIMARY KEY, |
64 | 64 | created_time bigint NOT NULL, |
65 | 65 | tenant_id uuid NOT NULL, |
66 | + device_profile_id uuid, | |
67 | + type varchar(32) NOT NULL, | |
66 | 68 | title varchar(255) NOT NULL, |
67 | 69 | version varchar(255) NOT NULL, |
68 | 70 | file_name varchar(255), |
... | ... | @@ -77,10 +79,12 @@ CREATE TABLE IF NOT EXISTS firmware ( |
77 | 79 | ); |
78 | 80 | |
79 | 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 | 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 | 89 | DO $$ |
86 | 90 | BEGIN |
... | ... | @@ -90,11 +94,23 @@ DO $$ |
90 | 94 | FOREIGN KEY (firmware_id) REFERENCES firmware(id); |
91 | 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 | 103 | IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device') THEN |
94 | 104 | ALTER TABLE device |
95 | 105 | ADD CONSTRAINT fk_firmware_device |
96 | 106 | FOREIGN KEY (firmware_id) REFERENCES firmware(id); |
97 | 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 | 114 | END; |
99 | 115 | $$; |
100 | 116 | ... | ... |
... | ... | @@ -132,7 +132,7 @@ import org.thingsboard.server.service.firmware.FirmwareStateService; |
132 | 132 | import org.thingsboard.server.service.edge.EdgeNotificationService; |
133 | 133 | import org.thingsboard.server.service.edge.rpc.EdgeGrpcService; |
134 | 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 | 136 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
137 | 137 | import org.thingsboard.server.service.queue.TbClusterService; |
138 | 138 | import org.thingsboard.server.service.resource.TbResourceService; |
... | ... | @@ -267,7 +267,7 @@ public abstract class BaseController { |
267 | 267 | protected TbDeviceProfileCache deviceProfileCache; |
268 | 268 | |
269 | 269 | @Autowired |
270 | - protected LwM2MModelsRepository lwM2MModelsRepository; | |
270 | + protected LwM2MServerSecurityInfoRepository lwM2MServerSecurityInfoRepository; | |
271 | 271 | |
272 | 272 | @Autowired(required = false) |
273 | 273 | protected EdgeService edgeService; | ... | ... |
... | ... | @@ -146,12 +146,16 @@ public class DeviceProfileController extends BaseController { |
146 | 146 | checkEntity(deviceProfile.getId(), deviceProfile, Resource.DEVICE_PROFILE); |
147 | 147 | |
148 | 148 | boolean isFirmwareChanged = false; |
149 | + boolean isSoftwareChanged = false; | |
149 | 150 | |
150 | 151 | if (!created) { |
151 | 152 | DeviceProfile oldDeviceProfile = deviceProfileService.findDeviceProfileById(getTenantId(), deviceProfile.getId()); |
152 | 153 | if (!Objects.equals(deviceProfile.getFirmwareId(), oldDeviceProfile.getFirmwareId())) { |
153 | 154 | isFirmwareChanged = true; |
154 | 155 | } |
156 | + if (!Objects.equals(deviceProfile.getSoftwareId(), oldDeviceProfile.getSoftwareId())) { | |
157 | + isSoftwareChanged = true; | |
158 | + } | |
155 | 159 | } |
156 | 160 | |
157 | 161 | DeviceProfile savedDeviceProfile = checkNotNull(deviceProfileService.saveDeviceProfile(deviceProfile)); |
... | ... | @@ -164,9 +168,8 @@ public class DeviceProfileController extends BaseController { |
164 | 168 | null, |
165 | 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 | 173 | sendEntityNotificationMsg(getTenantId(), savedDeviceProfile.getId(), |
171 | 174 | deviceProfile.getId() == null ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED); |
172 | 175 | return savedDeviceProfile; | ... | ... |
... | ... | @@ -35,6 +35,8 @@ import org.thingsboard.server.common.data.Firmware; |
35 | 35 | import org.thingsboard.server.common.data.FirmwareInfo; |
36 | 36 | import org.thingsboard.server.common.data.audit.ActionType; |
37 | 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 | 40 | import org.thingsboard.server.common.data.id.FirmwareId; |
39 | 41 | import org.thingsboard.server.common.data.page.PageData; |
40 | 42 | import org.thingsboard.server.common.data.page.PageLink; |
... | ... | @@ -133,6 +135,8 @@ public class FirmwareController extends BaseController { |
133 | 135 | Firmware firmware = new Firmware(firmwareId); |
134 | 136 | firmware.setCreatedTime(info.getCreatedTime()); |
135 | 137 | firmware.setTenantId(getTenantId()); |
138 | + firmware.setDeviceProfileId(info.getDeviceProfileId()); | |
139 | + firmware.setType(info.getType()); | |
136 | 140 | firmware.setTitle(info.getTitle()); |
137 | 141 | firmware.setVersion(info.getVersion()); |
138 | 142 | firmware.setAdditionalInfo(info.getAdditionalInfo()); |
... | ... | @@ -175,17 +179,22 @@ public class FirmwareController extends BaseController { |
175 | 179 | } |
176 | 180 | |
177 | 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 | 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 | 187 | @RequestParam int pageSize, |
182 | 188 | @RequestParam int page, |
183 | 189 | @RequestParam(required = false) String textSearch, |
184 | 190 | @RequestParam(required = false) String sortProperty, |
185 | 191 | @RequestParam(required = false) String sortOrder) throws ThingsboardException { |
192 | + checkParameter("deviceProfileId", strDeviceProfileId); | |
193 | + checkParameter("type", strType); | |
186 | 194 | try { |
187 | 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 | 198 | } catch (Exception e) { |
190 | 199 | throw handleException(e); |
191 | 200 | } | ... | ... |
... | ... | @@ -47,9 +47,9 @@ public class Lwm2mController extends BaseController { |
47 | 47 | @RequestMapping(value = "/lwm2m/deviceProfile/bootstrap/{securityMode}/{bootstrapServerIs}", method = RequestMethod.GET) |
48 | 48 | @ResponseBody |
49 | 49 | public ServerSecurityConfig getLwm2mBootstrapSecurityInfo(@PathVariable("securityMode") String securityMode, |
50 | - @PathVariable("bootstrapServerIs") boolean bootstrapServerIs) throws ThingsboardException { | |
50 | + @PathVariable("bootstrapServerIs") boolean bootstrapServer) throws ThingsboardException { | |
51 | 51 | try { |
52 | - return lwM2MModelsRepository.getBootstrapSecurityInfo(securityMode, bootstrapServerIs); | |
52 | + return lwM2MServerSecurityInfoRepository.getServerSecurityInfo(securityMode, bootstrapServer); | |
53 | 53 | } catch (Exception e) { |
54 | 54 | throw handleException(e); |
55 | 55 | } | ... | ... |
... | ... | @@ -32,6 +32,7 @@ import org.springframework.web.bind.annotation.RequestParam; |
32 | 32 | import org.springframework.web.bind.annotation.ResponseBody; |
33 | 33 | import org.springframework.web.bind.annotation.ResponseStatus; |
34 | 34 | import org.springframework.web.bind.annotation.RestController; |
35 | +import org.thingsboard.common.util.JacksonUtil; | |
35 | 36 | import org.thingsboard.rule.engine.api.MailService; |
36 | 37 | import org.thingsboard.server.common.data.EntityType; |
37 | 38 | import org.thingsboard.server.common.data.User; |
... | ... | @@ -89,13 +90,14 @@ public class UserController extends BaseController { |
89 | 90 | try { |
90 | 91 | UserId userId = new UserId(toUUID(strUserId)); |
91 | 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 | 102 | return user; |
101 | 103 | } catch (Exception e) { |
... | ... | @@ -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 | 108 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
115 | 109 | @RequestMapping(value = "/user/tokenAccessEnabled", method = RequestMethod.GET) |
116 | 110 | @ResponseBody | ... | ... |
... | ... | @@ -19,13 +19,17 @@ import com.google.common.util.concurrent.FutureCallback; |
19 | 19 | import lombok.extern.slf4j.Slf4j; |
20 | 20 | import org.springframework.stereotype.Service; |
21 | 21 | import org.thingsboard.rule.engine.api.RuleEngineTelemetryService; |
22 | +import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; | |
22 | 23 | import org.thingsboard.server.common.data.DataConstants; |
23 | 24 | import org.thingsboard.server.common.data.Device; |
24 | 25 | import org.thingsboard.server.common.data.DeviceProfile; |
25 | 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 | 29 | import org.thingsboard.server.common.data.id.DeviceId; |
27 | 30 | import org.thingsboard.server.common.data.id.FirmwareId; |
28 | 31 | import org.thingsboard.server.common.data.id.TenantId; |
32 | +import org.thingsboard.server.common.data.kv.AttributeKey; | |
29 | 33 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
30 | 34 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
31 | 35 | import org.thingsboard.server.common.data.kv.BasicTsKvEntry; |
... | ... | @@ -43,37 +47,49 @@ import org.thingsboard.server.queue.TbQueueProducer; |
43 | 47 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
44 | 48 | import org.thingsboard.server.queue.provider.TbCoreQueueFactory; |
45 | 49 | import org.thingsboard.server.queue.util.TbCoreComponent; |
50 | +import org.thingsboard.server.service.queue.TbClusterService; | |
46 | 51 | |
47 | 52 | import javax.annotation.Nullable; |
48 | 53 | import java.util.ArrayList; |
49 | -import java.util.Arrays; | |
50 | 54 | import java.util.Collections; |
55 | +import java.util.HashSet; | |
51 | 56 | import java.util.List; |
57 | +import java.util.Set; | |
52 | 58 | import java.util.UUID; |
53 | 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 | 75 | @Slf4j |
62 | 76 | @Service |
63 | 77 | @TbCoreComponent |
64 | 78 | public class DefaultFirmwareStateService implements FirmwareStateService { |
65 | 79 | |
80 | + private final TbClusterService tbClusterService; | |
66 | 81 | private final FirmwareService firmwareService; |
67 | 82 | private final DeviceService deviceService; |
68 | 83 | private final DeviceProfileService deviceProfileService; |
69 | 84 | private final RuleEngineTelemetryService telemetryService; |
70 | 85 | private final TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> fwStateMsgProducer; |
71 | 86 | |
72 | - public DefaultFirmwareStateService(FirmwareService firmwareService, | |
87 | + public DefaultFirmwareStateService(TbClusterService tbClusterService, FirmwareService firmwareService, | |
73 | 88 | DeviceService deviceService, |
74 | 89 | DeviceProfileService deviceProfileService, |
75 | 90 | RuleEngineTelemetryService telemetryService, |
76 | 91 | TbCoreQueueFactory coreQueueFactory) { |
92 | + this.tbClusterService = tbClusterService; | |
77 | 93 | this.firmwareService = firmwareService; |
78 | 94 | this.deviceService = deviceService; |
79 | 95 | this.deviceProfileService = deviceProfileService; |
... | ... | @@ -83,6 +99,11 @@ public class DefaultFirmwareStateService implements FirmwareStateService { |
83 | 99 | |
84 | 100 | @Override |
85 | 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 | 107 | FirmwareId newFirmwareId = device.getFirmwareId(); |
87 | 108 | if (newFirmwareId == null) { |
88 | 109 | DeviceProfile newDeviceProfile = deviceProfileService.findDeviceProfileById(device.getTenantId(), device.getDeviceProfileId()); |
... | ... | @@ -97,35 +118,84 @@ public class DefaultFirmwareStateService implements FirmwareStateService { |
97 | 118 | } |
98 | 119 | if (!newFirmwareId.equals(oldFirmwareId)) { |
99 | 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 | 123 | } else { |
103 | 124 | // Device was updated and new firmware is not set. |
104 | - remove(device); | |
125 | + remove(device, FIRMWARE); | |
105 | 126 | } |
106 | 127 | } else if (newFirmwareId != null) { |
107 | 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 | 160 | @Override |
113 | - public void update(DeviceProfile deviceProfile) { | |
161 | + public void update(DeviceProfile deviceProfile, boolean isFirmwareChanged, boolean isSoftwareChanged) { | |
114 | 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 | 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 | 188 | if (deviceProfile.getFirmwareId() != null) { |
118 | 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 | 191 | } else { |
121 | - updateConsumer = this::remove; | |
192 | + updateConsumer = d -> remove(d, firmwareType); | |
122 | 193 | } |
123 | 194 | |
124 | 195 | PageLink pageLink = new PageLink(100); |
125 | 196 | PageData<Device> pageData; |
126 | 197 | do { |
127 | - pageData = deviceService.findDevicesByTenantIdAndTypeAndEmptyFirmware(tenantId, deviceProfile.getName(), pageLink); | |
128 | - | |
198 | + pageData = getDevicesFunction.apply(pageLink); | |
129 | 199 | pageData.getData().forEach(updateConsumer); |
130 | 200 | |
131 | 201 | if (pageData.hasNext()) { |
... | ... | @@ -140,16 +210,17 @@ public class DefaultFirmwareStateService implements FirmwareStateService { |
140 | 210 | FirmwareId targetFirmwareId = new FirmwareId(new UUID(msg.getFirmwareIdMSB(), msg.getFirmwareIdLSB())); |
141 | 211 | DeviceId deviceId = new DeviceId(new UUID(msg.getDeviceIdMSB(), msg.getDeviceIdLSB())); |
142 | 212 | TenantId tenantId = new TenantId(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB())); |
213 | + FirmwareType firmwareType = FirmwareType.valueOf(msg.getType()); | |
143 | 214 | long ts = msg.getTs(); |
144 | 215 | |
145 | 216 | Device device = deviceService.findDeviceById(tenantId, deviceId); |
146 | 217 | if (device == null) { |
147 | 218 | log.warn("[{}] [{}] Device was removed during firmware update msg was queued!", tenantId, deviceId); |
148 | 219 | } else { |
149 | - FirmwareId currentFirmwareId = device.getFirmwareId(); | |
150 | - | |
220 | + FirmwareId currentFirmwareId = FirmwareUtil.getFirmwareId(device, firmwareType); | |
151 | 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 | 226 | if (targetFirmwareId.equals(currentFirmwareId)) { |
... | ... | @@ -162,7 +233,7 @@ public class DefaultFirmwareStateService implements FirmwareStateService { |
162 | 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 | 237 | ToFirmwareStateServiceMsg msg = ToFirmwareStateServiceMsg.newBuilder() |
167 | 238 | .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) |
168 | 239 | .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) |
... | ... | @@ -170,6 +241,7 @@ public class DefaultFirmwareStateService implements FirmwareStateService { |
170 | 241 | .setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()) |
171 | 242 | .setFirmwareIdMSB(firmwareId.getId().getMostSignificantBits()) |
172 | 243 | .setFirmwareIdLSB(firmwareId.getId().getLeastSignificantBits()) |
244 | + .setType(firmwareType.name()) | |
173 | 245 | .setTs(ts) |
174 | 246 | .build(); |
175 | 247 | |
... | ... | @@ -183,10 +255,10 @@ public class DefaultFirmwareStateService implements FirmwareStateService { |
183 | 255 | fwStateMsgProducer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), null); |
184 | 256 | |
185 | 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 | 263 | telemetryService.saveAndNotify(tenantId, deviceId, telemetry, new FutureCallback<>() { |
192 | 264 | @Override |
... | ... | @@ -206,7 +278,7 @@ public class DefaultFirmwareStateService implements FirmwareStateService { |
206 | 278 | TenantId tenantId = device.getTenantId(); |
207 | 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 | 283 | telemetryService.saveAndNotify(tenantId, deviceId, Collections.singletonList(status), new FutureCallback<>() { |
212 | 284 | @Override |
... | ... | @@ -221,13 +293,12 @@ public class DefaultFirmwareStateService implements FirmwareStateService { |
221 | 293 | }); |
222 | 294 | |
223 | 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 | 302 | telemetryService.saveAndNotify(tenantId, deviceId, DataConstants.SHARED_SCOPE, attributes, new FutureCallback<>() { |
232 | 303 | @Override |
233 | 304 | public void onSuccess(@Nullable Void tmp) { |
... | ... | @@ -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 | 317 | new FutureCallback<>() { |
248 | 318 | @Override |
249 | 319 | public void onSuccess(@Nullable Void tmp) { |
250 | 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 | 326 | @Override | ... | ... |
... | ... | @@ -23,7 +23,7 @@ public interface FirmwareStateService { |
23 | 23 | |
24 | 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 | 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 | 16 | package org.thingsboard.server.service.lwm2m; |
17 | 17 | |
18 | 18 | |
19 | +import lombok.RequiredArgsConstructor; | |
19 | 20 | import lombok.extern.slf4j.Slf4j; |
20 | 21 | import org.eclipse.leshan.core.util.Hex; |
21 | -import org.springframework.beans.factory.annotation.Autowired; | |
22 | 22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
23 | 23 | import org.springframework.stereotype.Service; |
24 | 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 | 28 | import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; |
28 | 29 | |
29 | 30 | import java.math.BigInteger; |
... | ... | @@ -42,96 +43,59 @@ import java.security.spec.KeySpec; |
42 | 43 | |
43 | 44 | @Slf4j |
44 | 45 | @Service |
46 | +@RequiredArgsConstructor | |
45 | 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 | 54 | * @param securityMode |
59 | - * @param bootstrapServerIs | |
55 | + * @param bootstrapServer | |
60 | 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 | 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 | 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 | 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 | 92 | String publicKey = getServerPublicKeyX509(alias); |
125 | 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 | 96 | private String getServerPublicKeyX509(String alias) { |
133 | 97 | try { |
134 | - X509Certificate serverCertificate = (X509Certificate) contextServer.getKeyStoreValue().getCertificate(alias); | |
98 | + X509Certificate serverCertificate = (X509Certificate) serverConfig.getKeyStoreValue().getCertificate(alias); | |
135 | 99 | return Hex.encodeHexString(serverCertificate.getEncoded()); |
136 | 100 | } catch (CertificateEncodingException | KeyStoreException e) { |
137 | 101 | e.printStackTrace(); |
... | ... | @@ -139,11 +103,6 @@ public class LwM2MModelsRepository { |
139 | 103 | return null; |
140 | 104 | } |
141 | 105 | |
142 | - /** | |
143 | - * @param publicServerX | |
144 | - * @param publicServerY | |
145 | - * @return PublicKey format HexString or null | |
146 | - */ | |
147 | 106 | private String getRPKPublicKey(String publicServerX, String publicServerY) { |
148 | 107 | try { |
149 | 108 | /** Get Elliptic Curve Parameter spec for secp256r1 */ | ... | ... |
... | ... | @@ -185,7 +185,7 @@ public class DefaultTbResourceService implements TbResourceService { |
185 | 185 | instance.setId(0); |
186 | 186 | List<LwM2mResourceObserve> resources = new ArrayList<>(); |
187 | 187 | obj.resources.forEach((k, v) -> { |
188 | - if (!v.operations.isExecutable()) { | |
188 | + if (v.operations.isReadable()) { | |
189 | 189 | LwM2mResourceObserve lwM2MResourceObserve = new LwM2mResourceObserve(k, v.name, false, false, false); |
190 | 190 | resources.add(lwM2MResourceObserve); |
191 | 191 | } | ... | ... |
... | ... | @@ -41,6 +41,8 @@ import org.thingsboard.server.common.data.TenantProfile; |
41 | 41 | import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials; |
42 | 42 | import org.thingsboard.server.common.data.device.credentials.ProvisionDeviceCredentialsData; |
43 | 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 | 46 | import org.thingsboard.server.common.data.id.CustomerId; |
45 | 47 | import org.thingsboard.server.common.data.id.DeviceId; |
46 | 48 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
... | ... | @@ -512,16 +514,17 @@ public class DefaultTransportApiService implements TransportApiService { |
512 | 514 | private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.GetFirmwareRequestMsg requestMsg) { |
513 | 515 | TenantId tenantId = new TenantId(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB())); |
514 | 516 | DeviceId deviceId = new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB())); |
517 | + FirmwareType firmwareType = FirmwareType.valueOf(requestMsg.getType()); | |
515 | 518 | Device device = deviceService.findDeviceById(tenantId, deviceId); |
516 | 519 | |
517 | 520 | if (device == null) { |
518 | 521 | return getEmptyTransportApiResponseFuture(); |
519 | 522 | } |
520 | 523 | |
521 | - FirmwareId firmwareId = device.getFirmwareId(); | |
522 | - | |
524 | + FirmwareId firmwareId = FirmwareUtil.getFirmwareId(device, firmwareType); | |
523 | 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 | 530 | TransportProtos.GetFirmwareResponseMsg.Builder builder = TransportProtos.GetFirmwareResponseMsg.newBuilder(); |
... | ... | @@ -537,6 +540,7 @@ public class DefaultTransportApiService implements TransportApiService { |
537 | 540 | builder.setResponseStatus(TransportProtos.ResponseStatus.SUCCESS); |
538 | 541 | builder.setFirmwareIdMSB(firmwareId.getId().getMostSignificantBits()); |
539 | 542 | builder.setFirmwareIdLSB(firmwareId.getId().getLeastSignificantBits()); |
543 | + builder.setType(firmwareInfo.getType().name()); | |
540 | 544 | builder.setTitle(firmwareInfo.getTitle()); |
541 | 545 | builder.setVersion(firmwareInfo.getVersion()); |
542 | 546 | builder.setFileName(firmwareInfo.getFileName()); | ... | ... |
... | ... | @@ -630,38 +630,14 @@ transport: |
630 | 630 | lwm2m: |
631 | 631 | # Enable/disable lvm2m transport protocol. |
632 | 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 | 633 | server: |
654 | 634 | id: "${LWM2M_SERVER_ID:123}" |
655 | 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 | 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 | 641 | public_x: "${LWM2M_SERVER_PUBLIC_X:05064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f358}" |
666 | 642 | public_y: "${LWM2M_SERVER_PUBLIC_Y:5eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}" |
667 | 643 | private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}" |
... | ... | @@ -671,19 +647,34 @@ transport: |
671 | 647 | enable: "${LWM2M_ENABLED_BS:true}" |
672 | 648 | id: "${LWM2M_SERVER_ID_BS:111}" |
673 | 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 | 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 | 655 | public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}" |
683 | 656 | public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:3fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" |
684 | 657 | private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" |
685 | 658 | # Only Certificate_x509: |
686 | 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 | 678 | # Use redis for Security and Registration stores |
688 | 679 | redis.enabled: "${LWM2M_REDIS_ENABLED:false}" |
689 | 680 | snmp: | ... | ... |
... | ... | @@ -24,10 +24,13 @@ import org.springframework.mock.web.MockMultipartFile; |
24 | 24 | import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; |
25 | 25 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; |
26 | 26 | import org.thingsboard.common.util.JacksonUtil; |
27 | +import org.thingsboard.server.common.data.DeviceProfile; | |
27 | 28 | import org.thingsboard.server.common.data.Firmware; |
28 | 29 | import org.thingsboard.server.common.data.FirmwareInfo; |
29 | 30 | import org.thingsboard.server.common.data.Tenant; |
30 | 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 | 34 | import org.thingsboard.server.common.data.page.PageData; |
32 | 35 | import org.thingsboard.server.common.data.page.PageLink; |
33 | 36 | import org.thingsboard.server.common.data.security.Authority; |
... | ... | @@ -38,6 +41,7 @@ import java.util.Collections; |
38 | 41 | import java.util.List; |
39 | 42 | |
40 | 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 | 46 | public abstract class BaseFirmwareControllerTest extends AbstractControllerTest { |
43 | 47 | |
... | ... | @@ -53,6 +57,7 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest |
53 | 57 | |
54 | 58 | private Tenant savedTenant; |
55 | 59 | private User tenantAdmin; |
60 | + private DeviceProfileId deviceProfileId; | |
56 | 61 | |
57 | 62 | @Before |
58 | 63 | public void beforeTest() throws Exception { |
... | ... | @@ -71,6 +76,11 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest |
71 | 76 | tenantAdmin.setLastName("Downs"); |
72 | 77 | |
73 | 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 | 86 | @After |
... | ... | @@ -84,6 +94,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest |
84 | 94 | @Test |
85 | 95 | public void testSaveFirmware() throws Exception { |
86 | 96 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
97 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | |
98 | + firmwareInfo.setType(FIRMWARE); | |
87 | 99 | firmwareInfo.setTitle(TITLE); |
88 | 100 | firmwareInfo.setVersion(VERSION); |
89 | 101 | |
... | ... | @@ -107,6 +119,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest |
107 | 119 | @Test |
108 | 120 | public void testSaveFirmwareData() throws Exception { |
109 | 121 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
122 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | |
123 | + firmwareInfo.setType(FIRMWARE); | |
110 | 124 | firmwareInfo.setTitle(TITLE); |
111 | 125 | firmwareInfo.setVersion(VERSION); |
112 | 126 | |
... | ... | @@ -137,6 +151,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest |
137 | 151 | @Test |
138 | 152 | public void testUpdateFirmwareFromDifferentTenant() throws Exception { |
139 | 153 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
154 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | |
155 | + firmwareInfo.setType(FIRMWARE); | |
140 | 156 | firmwareInfo.setTitle(TITLE); |
141 | 157 | firmwareInfo.setVersion(VERSION); |
142 | 158 | |
... | ... | @@ -150,6 +166,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest |
150 | 166 | @Test |
151 | 167 | public void testFindFirmwareInfoById() throws Exception { |
152 | 168 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
169 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | |
170 | + firmwareInfo.setType(FIRMWARE); | |
153 | 171 | firmwareInfo.setTitle(TITLE); |
154 | 172 | firmwareInfo.setVersion(VERSION); |
155 | 173 | |
... | ... | @@ -163,6 +181,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest |
163 | 181 | @Test |
164 | 182 | public void testFindFirmwareById() throws Exception { |
165 | 183 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
184 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | |
185 | + firmwareInfo.setType(FIRMWARE); | |
166 | 186 | firmwareInfo.setTitle(TITLE); |
167 | 187 | firmwareInfo.setVersion(VERSION); |
168 | 188 | |
... | ... | @@ -180,6 +200,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest |
180 | 200 | @Test |
181 | 201 | public void testDeleteFirmware() throws Exception { |
182 | 202 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
203 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | |
204 | + firmwareInfo.setType(FIRMWARE); | |
183 | 205 | firmwareInfo.setTitle(TITLE); |
184 | 206 | firmwareInfo.setVersion(VERSION); |
185 | 207 | |
... | ... | @@ -197,6 +219,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest |
197 | 219 | List<FirmwareInfo> firmwares = new ArrayList<>(); |
198 | 220 | for (int i = 0; i < 165; i++) { |
199 | 221 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
222 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | |
223 | + firmwareInfo.setType(FIRMWARE); | |
200 | 224 | firmwareInfo.setTitle(TITLE); |
201 | 225 | firmwareInfo.setVersion(VERSION + i); |
202 | 226 | |
... | ... | @@ -238,6 +262,8 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest |
238 | 262 | |
239 | 263 | for (int i = 0; i < 165; i++) { |
240 | 264 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
265 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | |
266 | + firmwareInfo.setType(FIRMWARE); | |
241 | 267 | firmwareInfo.setTitle(TITLE); |
242 | 268 | firmwareInfo.setVersion(VERSION + i); |
243 | 269 | |
... | ... | @@ -257,7 +283,7 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest |
257 | 283 | PageLink pageLink = new PageLink(24); |
258 | 284 | PageData<FirmwareInfo> pageData; |
259 | 285 | do { |
260 | - pageData = doGetTypedWithPageLink("/api/firmwares/true?", | |
286 | + pageData = doGetTypedWithPageLink("/api/firmwares/" + deviceProfileId.toString() + "/FIRMWARE/true?", | |
261 | 287 | new TypeReference<>() { |
262 | 288 | }, pageLink); |
263 | 289 | loadedFirmwaresWithData.addAll(pageData.getData()); |
... | ... | @@ -269,7 +295,7 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest |
269 | 295 | List<FirmwareInfo> loadedFirmwaresWithoutData = new ArrayList<>(); |
270 | 296 | pageLink = new PageLink(24); |
271 | 297 | do { |
272 | - pageData = doGetTypedWithPageLink("/api/firmwares/false?", | |
298 | + pageData = doGetTypedWithPageLink("/api/firmwares/" + deviceProfileId.toString() + "/FIRMWARE/false?", | |
273 | 299 | new TypeReference<>() { |
274 | 300 | }, pageLink); |
275 | 301 | loadedFirmwaresWithoutData.addAll(pageData.getData()); | ... | ... |
... | ... | @@ -65,6 +65,8 @@ public interface DeviceService { |
65 | 65 | |
66 | 66 | PageData<Device> findDevicesByTenantIdAndTypeAndEmptyFirmware(TenantId tenantId, String type, PageLink pageLink); |
67 | 67 | |
68 | + PageData<Device> findDevicesByTenantIdAndTypeAndEmptySoftware(TenantId tenantId, String type, PageLink pageLink); | |
69 | + | |
68 | 70 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink); |
69 | 71 | |
70 | 72 | PageData<DeviceInfo> findDeviceInfosByTenantIdAndDeviceProfileId(TenantId tenantId, DeviceProfileId deviceProfileId, PageLink pageLink); | ... | ... |
... | ... | @@ -18,6 +18,8 @@ package org.thingsboard.server.dao.firmware; |
18 | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | 19 | import org.thingsboard.server.common.data.Firmware; |
20 | 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 | 23 | import org.thingsboard.server.common.data.id.FirmwareId; |
22 | 24 | import org.thingsboard.server.common.data.id.TenantId; |
23 | 25 | import org.thingsboard.server.common.data.page.PageData; |
... | ... | @@ -37,7 +39,7 @@ public interface FirmwareService { |
37 | 39 | |
38 | 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 | 44 | void deleteFirmware(TenantId tenantId, FirmwareId firmwareId); |
43 | 45 | ... | ... |
... | ... | @@ -93,22 +93,26 @@ public class DataConstants { |
93 | 93 | public static final String USERNAME = "username"; |
94 | 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 | 115 | public static final String EDGE_MSG_SOURCE = "edge"; |
113 | 116 | public static final String MSG_SOURCE_KEY = "source"; |
117 | + | |
114 | 118 | } | ... | ... |
... | ... | @@ -32,7 +32,7 @@ import java.io.IOException; |
32 | 32 | |
33 | 33 | @EqualsAndHashCode(callSuper = true) |
34 | 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 | 37 | private static final long serialVersionUID = 2807343040519543363L; |
38 | 38 | |
... | ... | @@ -50,6 +50,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen |
50 | 50 | private byte[] deviceDataBytes; |
51 | 51 | |
52 | 52 | private FirmwareId firmwareId; |
53 | + private FirmwareId softwareId; | |
53 | 54 | |
54 | 55 | public Device() { |
55 | 56 | super(); |
... | ... | @@ -69,6 +70,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen |
69 | 70 | this.deviceProfileId = device.getDeviceProfileId(); |
70 | 71 | this.setDeviceData(device.getDeviceData()); |
71 | 72 | this.firmwareId = device.getFirmwareId(); |
73 | + this.softwareId = device.getSoftwareId(); | |
72 | 74 | } |
73 | 75 | |
74 | 76 | public Device updateDevice(Device device) { |
... | ... | @@ -79,6 +81,8 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen |
79 | 81 | this.label = device.getLabel(); |
80 | 82 | this.deviceProfileId = device.getDeviceProfileId(); |
81 | 83 | this.setDeviceData(device.getDeviceData()); |
84 | + this.setFirmwareId(device.getFirmwareId()); | |
85 | + this.setSoftwareId(device.getSoftwareId()); | |
82 | 86 | return this; |
83 | 87 | } |
84 | 88 | |
... | ... | @@ -171,6 +175,14 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen |
171 | 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 | 186 | @Override |
175 | 187 | public String toString() { |
176 | 188 | StringBuilder builder = new StringBuilder(); | ... | ... |
... | ... | @@ -36,7 +36,7 @@ import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalIn |
36 | 36 | @Data |
37 | 37 | @EqualsAndHashCode(callSuper = true) |
38 | 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 | 41 | private TenantId tenantId; |
42 | 42 | @NoXss |
... | ... | @@ -59,6 +59,8 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H |
59 | 59 | |
60 | 60 | private FirmwareId firmwareId; |
61 | 61 | |
62 | + private FirmwareId softwareId; | |
63 | + | |
62 | 64 | public DeviceProfile() { |
63 | 65 | super(); |
64 | 66 | } |
... | ... | @@ -77,6 +79,8 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H |
77 | 79 | this.defaultQueueName = deviceProfile.getDefaultQueueName(); |
78 | 80 | this.setProfileData(deviceProfile.getProfileData()); |
79 | 81 | this.provisionDeviceKey = deviceProfile.getProvisionDeviceKey(); |
82 | + this.firmwareId = deviceProfile.getFirmwareId(); | |
83 | + this.softwareId = deviceProfile.getSoftwareId(); | |
80 | 84 | } |
81 | 85 | |
82 | 86 | @Override | ... | ... |
... | ... | @@ -19,6 +19,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore; |
19 | 19 | import lombok.Data; |
20 | 20 | import lombok.EqualsAndHashCode; |
21 | 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 | 24 | import org.thingsboard.server.common.data.id.FirmwareId; |
23 | 25 | import org.thingsboard.server.common.data.id.TenantId; |
24 | 26 | |
... | ... | @@ -30,6 +32,8 @@ public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId> |
30 | 32 | private static final long serialVersionUID = 3168391583570815419L; |
31 | 33 | |
32 | 34 | private TenantId tenantId; |
35 | + private DeviceProfileId deviceProfileId; | |
36 | + private FirmwareType type; | |
33 | 37 | private String title; |
34 | 38 | private String version; |
35 | 39 | private boolean hasData; |
... | ... | @@ -51,6 +55,8 @@ public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId> |
51 | 55 | public FirmwareInfo(FirmwareInfo firmwareInfo) { |
52 | 56 | super(firmwareInfo); |
53 | 57 | this.tenantId = firmwareInfo.getTenantId(); |
58 | + this.deviceProfileId = firmwareInfo.getDeviceProfileId(); | |
59 | + this.type = firmwareInfo.getType(); | |
54 | 60 | this.title = firmwareInfo.getTitle(); |
55 | 61 | this.version = firmwareInfo.getVersion(); |
56 | 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 | 31 | private static final String SUB_TOPIC = "+"; |
32 | 32 | private static final String PROVISION = "/provision"; |
33 | 33 | private static final String FIRMWARE = "/fw"; |
34 | + private static final String SOFTWARE = "/sw"; | |
34 | 35 | private static final String CHUNK = "/chunk/"; |
35 | 36 | private static final String ERROR = "/error"; |
36 | 37 | |
... | ... | @@ -75,9 +76,17 @@ public class MqttTopics { |
75 | 76 | // v2 topics |
76 | 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 | 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 | 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 | +} | ... | ... |
... | ... | @@ -388,16 +388,18 @@ message GetFirmwareRequestMsg { |
388 | 388 | int64 deviceIdLSB = 2; |
389 | 389 | int64 tenantIdMSB = 3; |
390 | 390 | int64 tenantIdLSB = 4; |
391 | + string type = 5; | |
391 | 392 | } |
392 | 393 | |
393 | 394 | message GetFirmwareResponseMsg { |
394 | 395 | ResponseStatus responseStatus = 1; |
395 | 396 | int64 firmwareIdMSB = 2; |
396 | 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 | 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 | 713 | int64 deviceIdLSB = 5; |
712 | 714 | int64 firmwareIdMSB = 6; |
713 | 715 | int64 firmwareIdLSB = 7; |
716 | + string type = 8; | |
714 | 717 | } | ... | ... |
common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java
... | ... | @@ -43,6 +43,7 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportC |
43 | 43 | import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration; |
44 | 44 | import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; |
45 | 45 | import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; |
46 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
46 | 47 | import org.thingsboard.server.common.data.security.DeviceTokenCredentials; |
47 | 48 | import org.thingsboard.server.common.msg.session.FeatureType; |
48 | 49 | import org.thingsboard.server.common.msg.session.SessionMsgType; |
... | ... | @@ -122,6 +123,8 @@ public class CoapTransportResource extends AbstractCoapTransportResource { |
122 | 123 | processRequest(exchange, SessionMsgType.GET_ATTRIBUTES_REQUEST); |
123 | 124 | } else if (featureType.get() == FeatureType.FIRMWARE) { |
124 | 125 | processRequest(exchange, SessionMsgType.GET_FIRMWARE_REQUEST); |
126 | + } else if (featureType.get() == FeatureType.SOFTWARE) { | |
127 | + processRequest(exchange, SessionMsgType.GET_SOFTWARE_REQUEST); | |
125 | 128 | } else { |
126 | 129 | log.trace("Invalid feature type parameter"); |
127 | 130 | exchange.respond(CoAP.ResponseCode.BAD_REQUEST); |
... | ... | @@ -326,12 +329,10 @@ public class CoapTransportResource extends AbstractCoapTransportResource { |
326 | 329 | new CoapNoOpCallback(exchange)); |
327 | 330 | break; |
328 | 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 | 336 | break; |
336 | 337 | } |
337 | 338 | } catch (AdaptorException e) { |
... | ... | @@ -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 | 354 | private TransportProtos.SessionInfoProto lookupAsyncSessionInfo(String token) { |
344 | 355 | tokenToNotificationCounterMap.remove(token); |
345 | 356 | return tokenToSessionIdMap.remove(token); | ... | ... |
... | ... | @@ -34,6 +34,7 @@ import org.springframework.web.bind.annotation.RequestParam; |
34 | 34 | import org.springframework.web.bind.annotation.RestController; |
35 | 35 | import org.springframework.web.context.request.async.DeferredResult; |
36 | 36 | import org.thingsboard.server.common.data.DeviceTransportType; |
37 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
37 | 38 | import org.thingsboard.server.common.data.TbTransportService; |
38 | 39 | import org.thingsboard.server.common.data.id.DeviceId; |
39 | 40 | import org.thingsboard.server.common.transport.SessionMsgListener; |
... | ... | @@ -210,8 +211,29 @@ public class DeviceApiController implements TbTransportService { |
210 | 211 | public DeferredResult<ResponseEntity> getFirmware(@PathVariable("deviceToken") String deviceToken, |
211 | 212 | @RequestParam(value = "title") String title, |
212 | 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 | 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 | 237 | DeferredResult<ResponseEntity> responseWriter = new DeferredResult<>(); |
216 | 238 | transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), |
217 | 239 | new DeviceAuthCallback(transportContext, responseWriter, sessionInfo -> { |
... | ... | @@ -219,20 +241,13 @@ public class DeviceApiController implements TbTransportService { |
219 | 241 | .setTenantIdMSB(sessionInfo.getTenantIdMSB()) |
220 | 242 | .setTenantIdLSB(sessionInfo.getTenantIdLSB()) |
221 | 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 | 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 | 251 | private static class DeviceAuthCallback implements TransportServiceCallback<ValidateDeviceCredentialsResponse> { |
237 | 252 | private final TransportContext transportContext; |
238 | 253 | private final DeferredResult<ResponseEntity> responseWriter; | ... | ... |
... | ... | @@ -25,10 +25,13 @@ import org.springframework.beans.factory.annotation.Autowired; |
25 | 25 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
26 | 26 | import org.springframework.context.annotation.Bean; |
27 | 27 | import org.springframework.stereotype.Component; |
28 | +import org.thingsboard.server.common.data.StringUtils; | |
28 | 29 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapSecurityStore; |
29 | 30 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MInMemoryBootstrapConfigStore; |
30 | 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 | 36 | import java.math.BigInteger; |
34 | 37 | import java.security.AlgorithmParameters; |
... | ... | @@ -55,7 +58,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE |
55 | 58 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; |
56 | 59 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; |
57 | 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 | 63 | @Slf4j |
61 | 64 | @Component |
... | ... | @@ -66,10 +69,10 @@ public class LwM2MTransportBootstrapServerConfiguration { |
66 | 69 | private boolean pskMode = false; |
67 | 70 | |
68 | 71 | @Autowired |
69 | - private LwM2MTransportContextBootstrap contextBs; | |
72 | + private LwM2MTransportServerConfig serverConfig; | |
70 | 73 | |
71 | 74 | @Autowired |
72 | - private LwM2mTransportContextServer contextS; | |
75 | + private LwM2MTransportContextBootstrap contextBs; | |
73 | 76 | |
74 | 77 | @Autowired |
75 | 78 | private LwM2MBootstrapSecurityStore lwM2MBootstrapSecurityStore; |
... | ... | @@ -81,19 +84,18 @@ public class LwM2MTransportBootstrapServerConfiguration { |
81 | 84 | @Bean |
82 | 85 | public LeshanBootstrapServer getLeshanBootstrapServer() { |
83 | 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 | 90 | public LeshanBootstrapServer getLhBootstrapServer(Integer bootstrapPortNoSec, Integer bootstrapSecurePort) { |
88 | 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 | 95 | /** Create CoAP Config */ |
93 | 96 | builder.setCoapConfig(getCoapConfig(bootstrapPortNoSec, bootstrapSecurePort)); |
94 | 97 | |
95 | 98 | /** Define model provider (Create Models )*/ |
96 | -// builder.setModel(new StaticModel(contextS.getLwM2MTransportConfigServer().getModelsValueCommon())); | |
97 | 99 | |
98 | 100 | /** Create credentials */ |
99 | 101 | this.setServerWithCredentials(builder); |
... | ... | @@ -107,14 +109,13 @@ public class LwM2MTransportBootstrapServerConfiguration { |
107 | 109 | |
108 | 110 | /** Create and Set DTLS Config */ |
109 | 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 | 114 | if (this.pskMode) { |
113 | 115 | dtlsConfig.setSupportedCipherSuites( |
114 | 116 | TLS_PSK_WITH_AES_128_CCM_8, |
115 | 117 | TLS_PSK_WITH_AES_128_CBC_SHA256); |
116 | - } | |
117 | - else { | |
118 | + } else { | |
118 | 119 | dtlsConfig.setSupportedCipherSuites( |
119 | 120 | TLS_PSK_WITH_AES_128_CCM_8, |
120 | 121 | TLS_PSK_WITH_AES_128_CBC_SHA256, |
... | ... | @@ -134,10 +135,10 @@ public class LwM2MTransportBootstrapServerConfiguration { |
134 | 135 | |
135 | 136 | private void setServerWithCredentials(LeshanBootstrapServerBuilder builder) { |
136 | 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 | 140 | if (this.setBuilderX509(builder)) { |
140 | - X509Certificate rootCAX509Cert = (X509Certificate) keyStoreServer.getCertificate(this.contextS.getLwM2MTransportConfigServer().getRootAlias()); | |
141 | + X509Certificate rootCAX509Cert = (X509Certificate) keyStoreServer.getCertificate(serverConfig.getRootCertificateAlias()); | |
141 | 142 | if (rootCAX509Cert != null) { |
142 | 143 | X509Certificate[] trustedCertificates = new X509Certificate[1]; |
143 | 144 | trustedCertificates[0] = rootCAX509Cert; |
... | ... | @@ -168,12 +169,10 @@ public class LwM2MTransportBootstrapServerConfiguration { |
168 | 169 | * For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks |
169 | 170 | */ |
170 | 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 | 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 | 176 | builder.setPublicKey(serverCertificate.getPublicKey()); |
178 | 177 | builder.setPrivateKey(privateKey); |
179 | 178 | builder.setCertificateChain(new X509Certificate[]{serverCertificate}); |
... | ... | @@ -200,10 +199,12 @@ public class LwM2MTransportBootstrapServerConfiguration { |
200 | 199 | } |
201 | 200 | |
202 | 201 | private void infoPramsUri(String mode) { |
203 | - log.info("Bootstrap Server uses [{}]: serverNoSecureURI : [{}], serverSecureURI : [{}]", | |
202 | + log.info("Bootstrap Server uses [{}]: serverNoSecureURI : [{}:{}], serverSecureURI : [{}:{}]", | |
204 | 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 | 238 | AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); |
238 | 239 | algoParameters.init(new ECGenParameterSpec("secp256r1")); |
239 | 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 | 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 | 246 | /** Create key specs */ |
245 | 247 | KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), |
246 | 248 | parameterSpec); |
247 | 249 | /** Get public key */ |
248 | 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 | 254 | /** Get private key */ |
252 | - byte[] privateS = Hex.decodeHex(this.contextBs.getCtxBootStrap().getBootstrapPrivateEncoded().toCharArray()); | |
255 | + byte[] privateS = Hex.decodeHex(privateEncodedKey.toCharArray()); | |
253 | 256 | try { |
254 | 257 | this.privateKey = KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(privateS)); |
255 | 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 | 34 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
35 | 35 | import org.springframework.stereotype.Component; |
36 | 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 | 40 | @Slf4j |
... | ... | @@ -42,13 +42,13 @@ import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstr |
42 | 42 | @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith'") |
43 | 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 | 34 | import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; |
35 | 35 | import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore; |
36 | 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 | 41 | import java.io.IOException; |
41 | 42 | import java.security.GeneralSecurityException; |
... | ... | @@ -43,12 +44,12 @@ import java.util.Collections; |
43 | 44 | import java.util.List; |
44 | 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 | 54 | @Slf4j |
54 | 55 | @Service("LwM2MBootstrapSecurityStore") |
... | ... | @@ -59,17 +60,19 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { |
59 | 60 | |
60 | 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 | 67 | this.bootstrapConfigStore = bootstrapConfigStore; |
66 | 68 | this.lwM2MCredentialsSecurityInfoValidator = lwM2MCredentialsSecurityInfoValidator; |
67 | 69 | this.context = context; |
70 | + this.helper = helper; | |
68 | 71 | } |
69 | 72 | |
70 | 73 | @Override |
71 | 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 | 76 | if (store.getBootstrapJsonCredential() != null && store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { |
74 | 77 | /** add value to store from BootstrapJson */ |
75 | 78 | this.setBootstrapConfigScurityInfo(store); |
... | ... | @@ -93,7 +96,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { |
93 | 96 | |
94 | 97 | @Override |
95 | 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 | 100 | if (store.getBootstrapJsonCredential() != null && store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { |
98 | 101 | /** add value to store from BootstrapJson */ |
99 | 102 | this.setBootstrapConfigScurityInfo(store); |
... | ... | @@ -158,19 +161,19 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { |
158 | 161 | LwM2MServerBootstrap profileServerBootstrap = mapper.readValue(bootstrapObject.get(BOOTSTRAP_SERVER).toString(), LwM2MServerBootstrap.class); |
159 | 162 | LwM2MServerBootstrap profileLwm2mServer = mapper.readValue(bootstrapObject.get(LWM2M_SERVER).toString(), LwM2MServerBootstrap.class); |
160 | 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 | 165 | context.getTransportService().registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(null, sessionInfo)); |
163 | 166 | if (this.getValidatedSecurityMode(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap, lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer)) { |
164 | 167 | lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap); |
165 | 168 | lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer); |
166 | 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 | 171 | return lwM2MBootstrapConfig; |
169 | 172 | } else { |
170 | 173 | log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndPoint()); |
171 | 174 | log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint()); |
172 | 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 | 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 | +} | |
\ No newline at end of file | ... | ... |
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 | 13 | * See the License for the specific language governing permissions and |
14 | 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 | 18 | import lombok.Getter; |
19 | 19 | import lombok.Setter; |
... | ... | @@ -29,53 +29,42 @@ import java.util.Map; |
29 | 29 | @Slf4j |
30 | 30 | @Component |
31 | 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 | 34 | @Getter |
39 | 35 | @Value("${transport.lwm2m.bootstrap.id:}") |
40 | - private Integer bootstrapServerId; | |
36 | + private Integer id; | |
41 | 37 | |
42 | 38 | @Getter |
43 | 39 | @Value("${transport.lwm2m.bootstrap.bind_address:}") |
44 | - private String bootstrapHost; | |
40 | + private String host; | |
45 | 41 | |
46 | 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 | 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 | 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 | 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 | 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 | 62 | @Getter |
67 | - @Setter | |
68 | - private PublicKey bootstrapPublicKey; | |
63 | + @Value("${transport.lwm2m.bootstrap.security.private_encoded:}") | |
64 | + private String privateEncoded; | |
69 | 65 | |
70 | 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 | 13 | * See the License for the specific language governing permissions and |
14 | 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 | 19 | import lombok.Getter; |
19 | 20 | import lombok.Setter; |
20 | 21 | import lombok.extern.slf4j.Slf4j; |
... | ... | @@ -28,6 +29,7 @@ import java.io.File; |
28 | 29 | import java.io.FileInputStream; |
29 | 30 | import java.io.IOException; |
30 | 31 | import java.io.InputStream; |
32 | +import java.net.URI; | |
31 | 33 | import java.nio.file.Path; |
32 | 34 | import java.nio.file.Paths; |
33 | 35 | import java.security.KeyStore; |
... | ... | @@ -38,38 +40,7 @@ import java.security.cert.CertificateException; |
38 | 40 | @Slf4j |
39 | 41 | @Component |
40 | 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 | 45 | @Getter |
75 | 46 | @Setter |
... | ... | @@ -108,11 +79,11 @@ public class LwM2MTransportConfigServer { |
108 | 79 | private int unRegisteredPoolSize; |
109 | 80 | |
110 | 81 | @Getter |
111 | - @Value("${transport.lwm2m.secure.key_store_type:}") | |
82 | + @Value("${transport.lwm2m.security.key_store_type:}") | |
112 | 83 | private String keyStoreType; |
113 | 84 | |
114 | 85 | @Getter |
115 | - @Value("${transport.lwm2m.secure.key_store_path_file:}") | |
86 | + @Value("${transport.lwm2m.security.key_store:}") | |
116 | 87 | private String keyStorePathFile; |
117 | 88 | |
118 | 89 | @Getter |
... | ... | @@ -120,98 +91,72 @@ public class LwM2MTransportConfigServer { |
120 | 91 | private KeyStore keyStoreValue; |
121 | 92 | |
122 | 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 | 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 | 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 | 103 | private Boolean enableGenNewKeyPskRpk; |
133 | 104 | |
134 | 105 | @Getter |
135 | 106 | @Value("${transport.lwm2m.server.id:}") |
136 | - private Integer serverId; | |
107 | + private Integer id; | |
137 | 108 | |
138 | 109 | @Getter |
139 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 146 | @PostConstruct |
171 | 147 | public void init() { |
172 | - this.getInKeyStore(); | |
173 | - } | |
174 | - | |
175 | - private KeyStore getInKeyStore() { | |
148 | + URI uri = null; | |
176 | 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 | 16 | package org.thingsboard.server.transport.lwm2m.secure; |
17 | 17 | |
18 | 18 | import com.google.gson.JsonObject; |
19 | +import lombok.RequiredArgsConstructor; | |
19 | 20 | import lombok.extern.slf4j.Slf4j; |
20 | 21 | import org.eclipse.leshan.core.util.Hex; |
21 | 22 | import org.eclipse.leshan.core.util.SecurityUtil; |
... | ... | @@ -26,8 +27,10 @@ import org.thingsboard.server.common.transport.TransportServiceCallback; |
26 | 27 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; |
27 | 28 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; |
28 | 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 | 35 | import java.io.IOException; |
33 | 36 | import java.security.GeneralSecurityException; |
... | ... | @@ -44,13 +47,11 @@ import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.X5 |
44 | 47 | @Slf4j |
45 | 48 | @Component |
46 | 49 | @TbLwM2mTransportComponent |
50 | +@RequiredArgsConstructor | |
47 | 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 | 57 | * Request to thingsboard Response from thingsboard ValidateDeviceLwM2MCredentials |
... | ... | @@ -58,17 +59,17 @@ public class LwM2mCredentialsSecurityInfoValidator { |
58 | 59 | * @param keyValue - |
59 | 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 | 63 | CountDownLatch latch = new CountDownLatch(1); |
63 | 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 | 66 | new TransportServiceCallback<>() { |
66 | 67 | @Override |
67 | 68 | public void onSuccess(ValidateDeviceCredentialsResponseMsg msg) { |
68 | 69 | String credentialsBody = msg.getCredentialsBody(); |
69 | 70 | resultSecurityStore[0] = createSecurityInfo(endpoint, credentialsBody, keyValue); |
70 | 71 | resultSecurityStore[0].setMsg(msg); |
71 | - Optional<DeviceProfile> deviceProfileOpt = LwM2mTransportHandler.decode(msg.getProfileBody().toByteArray()); | |
72 | + Optional<DeviceProfile> deviceProfileOpt = LwM2mTransportHandlerUtil.decode(msg.getProfileBody().toByteArray()); | |
72 | 73 | deviceProfileOpt.ifPresent(profile -> resultSecurityStore[0].setDeviceProfile(profile)); |
73 | 74 | latch.countDown(); |
74 | 75 | } |
... | ... | @@ -81,7 +82,7 @@ public class LwM2mCredentialsSecurityInfoValidator { |
81 | 82 | } |
82 | 83 | }); |
83 | 84 | try { |
84 | - latch.await(contextS.getLwM2MTransportConfigServer().getTimeout(), TimeUnit.MILLISECONDS); | |
85 | + latch.await(config.getTimeout(), TimeUnit.MILLISECONDS); | |
85 | 86 | } catch (InterruptedException e) { |
86 | 87 | log.error("Failed to await credentials!", e); |
87 | 88 | } |
... | ... | @@ -95,9 +96,9 @@ public class LwM2mCredentialsSecurityInfoValidator { |
95 | 96 | * @param keyValue - |
96 | 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 | 100 | ReadResultSecurityStore result = new ReadResultSecurityStore(); |
100 | - JsonObject objectMsg = LwM2mTransportHandler.validateJson(jsonStr); | |
101 | + JsonObject objectMsg = LwM2mTransportHandlerUtil.validateJson(jsonStr); | |
101 | 102 | if (objectMsg != null && !objectMsg.isJsonNull()) { |
102 | 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 | 109 | && objectMsg.get("client").getAsJsonObject().get("endpoint").isJsonPrimitive()) ? objectMsg.get("client").getAsJsonObject().get("endpoint").getAsString() : null; |
109 | 110 | endPoint = (endPointPsk == null || endPointPsk.isEmpty()) ? endPoint : endPointPsk; |
110 | 111 | if (object != null && !object.isJsonNull()) { |
111 | - if (keyValue.equals(LwM2mTransportHandler.LwM2mTypeServer.BOOTSTRAP)) { | |
112 | + if (keyValue.equals(LwM2mTransportHandlerUtil.LwM2mTypeServer.BOOTSTRAP)) { | |
112 | 113 | result.setBootstrapJsonCredential(object); |
113 | 114 | result.setEndPoint(endPoint); |
114 | 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 | 38 | import org.springframework.context.annotation.Lazy; |
39 | 39 | import org.springframework.stereotype.Service; |
40 | 40 | import org.thingsboard.common.util.JacksonUtil; |
41 | +import org.thingsboard.server.cache.firmware.FirmwareDataCache; | |
41 | 42 | import org.thingsboard.server.common.data.Device; |
42 | 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 | 48 | import org.thingsboard.server.common.transport.TransportService; |
49 | +import org.thingsboard.server.common.transport.TransportServiceCallback; | |
45 | 50 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
46 | 51 | import org.thingsboard.server.common.transport.service.DefaultTransportService; |
47 | 52 | import org.thingsboard.server.gen.transport.TransportProtos; |
... | ... | @@ -49,6 +54,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotif |
49 | 54 | import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent; |
50 | 55 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
51 | 56 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
57 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; | |
52 | 58 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
53 | 59 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; |
54 | 60 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; |
... | ... | @@ -77,34 +83,37 @@ import java.util.stream.Collectors; |
77 | 83 | |
78 | 84 | import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST; |
79 | 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 | 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 | 113 | @Slf4j |
105 | 114 | @Service |
106 | 115 | @TbLwM2mTransportComponent |
107 | -public class LwM2mTransportServiceImpl implements LwM2mTransportService { | |
116 | +public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler { | |
108 | 117 | |
109 | 118 | private ExecutorService executorRegistered; |
110 | 119 | private ExecutorService executorUpdateRegistered; |
... | ... | @@ -112,31 +121,35 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
112 | 121 | private LwM2mValueConverterImpl converter; |
113 | 122 | |
114 | 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 | 128 | private final LwM2mClientContext lwM2mClientContext; |
119 | - | |
120 | - private final LeshanServer leshanServer; | |
121 | - | |
122 | 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 | 136 | this.transportService = transportService; |
126 | - this.lwM2mTransportContextServer = lwM2mTransportContextServer; | |
137 | + this.config = config; | |
138 | + this.helper = helper; | |
127 | 139 | this.lwM2mClientContext = lwM2mClientContext; |
128 | - this.leshanServer = leshanServer; | |
129 | 140 | this.lwM2mTransportRequest = lwM2mTransportRequest; |
141 | + this.firmwareDataCache = firmwareDataCache; | |
142 | + this.context = context; | |
130 | 143 | } |
131 | 144 | |
132 | 145 | @PostConstruct |
133 | 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 | 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 | 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 | 153 | new NamedThreadFactory(String.format("LwM2M %s channel un registered", SERVICE_CHANNEL))); |
141 | 154 | this.converter = LwM2mValueConverterImpl.getInstance(); |
142 | 155 | } |
... | ... | @@ -168,8 +181,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
168 | 181 | transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null); |
169 | 182 | transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null); |
170 | 183 | transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null); |
184 | + this.getInfoFirmwareUpdate(lwM2MClient); | |
171 | 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 | 187 | } else { |
174 | 188 | log.error("Client: [{}] onRegistered [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null); |
175 | 189 | } |
... | ... | @@ -224,7 +238,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
224 | 238 | executorUnRegistered.submit(() -> { |
225 | 239 | try { |
226 | 240 | this.setCancelObservations(registration); |
227 | - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration); | |
241 | + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId()); | |
228 | 242 | this.closeClientSession(registration); |
229 | 243 | } catch (Throwable t) { |
230 | 244 | log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t); |
... | ... | @@ -257,7 +271,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
257 | 271 | @Override |
258 | 272 | public void onSleepingDev(Registration registration) { |
259 | 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 | 276 | //TODO: associate endpointId with device information. |
263 | 277 | } |
... | ... | @@ -265,10 +279,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
265 | 279 | @Override |
266 | 280 | public void setCancelObservations(Registration registration) { |
267 | 281 | if (registration != null) { |
268 | - Set<Observation> observations = leshanServer.getObservationService().getObservations(registration); | |
282 | + Set<Observation> observations = context.getServer().getObservationService().getObservations(registration); | |
269 | 283 | observations.forEach(observation -> lwM2mTransportRequest.sendAllRequest(registration, |
270 | 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 | 294 | * @param response - observe |
281 | 295 | */ |
282 | 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 | 298 | if (response.getContent() != null) { |
285 | 299 | if (response.getContent() instanceof LwM2mObject) { |
286 | 300 | LwM2mObject lwM2mObject = (LwM2mObject) response.getContent(); |
... | ... | @@ -304,22 +318,29 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
304 | 318 | |
305 | 319 | /** |
306 | 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 | 328 | * @param msg - |
312 | 329 | */ |
313 | 330 | @Override |
314 | 331 | public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) { |
332 | + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); | |
315 | 333 | if (msg.getSharedUpdatedCount() > 0) { |
316 | 334 | msg.getSharedUpdatedList().forEach(tsKvProto -> { |
317 | 335 | String pathName = tsKvProto.getKv().getKey(); |
318 | 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 | 342 | if (pathIdVer != null) { |
322 | - ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer() | |
343 | + ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.config | |
323 | 344 | .getModelProvider()); |
324 | 345 | if (resourceModel != null && resourceModel.operations.isWritable()) { |
325 | 346 | this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer), valueNew, pathIdVer); |
... | ... | @@ -327,19 +348,26 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
327 | 348 | log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, valueNew); |
328 | 349 | String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated", |
329 | 350 | LOG_LW2M_ERROR, pathIdVer, valueNew); |
330 | - this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration()); | |
351 | + this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId()); | |
331 | 352 | } |
332 | 353 | } else { |
333 | 354 | log.error("Resource name name - [{}] value - [{}] is not present as attribute/telemetry in profile and cannot be updated", pathName, valueNew); |
334 | 355 | String logMsg = String.format("%s: attributeUpdate: attribute name - %s value - %s is not present as attribute in profile and cannot be updated", |
335 | 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 | 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 | 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 | 405 | @Override |
378 | 406 | public void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) { |
379 | 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 | 414 | @Override |
387 | 415 | public void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) { |
388 | 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 | 420 | @Override |
... | ... | @@ -402,7 +430,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
402 | 430 | } else { |
403 | 431 | lwM2mTransportRequest.sendAllRequest(registration, lwm2mClientRpcRequest.getTargetIdVer(), lwm2mClientRpcRequest.getTypeOper(), lwm2mClientRpcRequest.getContentFormatName(), |
404 | 432 | lwm2mClientRpcRequest.getValue() == null ? lwm2mClientRpcRequest.getParams() : lwm2mClientRpcRequest.getValue(), |
405 | - this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), lwm2mClientRpcRequest); | |
433 | + this.config.getTimeout(), lwm2mClientRpcRequest); | |
406 | 434 | } |
407 | 435 | } catch (Exception e) { |
408 | 436 | if (lwm2mClientRpcRequest == null) { |
... | ... | @@ -430,7 +458,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
430 | 458 | lwm2mClientRpcRequest.setRequestId(toDeviceRequest.getRequestId()); |
431 | 459 | lwm2mClientRpcRequest.setSessionInfo(sessionInfo); |
432 | 460 | lwm2mClientRpcRequest.setValidTypeOper(toDeviceRequest.getMethodName()); |
433 | - JsonObject rpcRequest = LwM2mTransportHandler.validateJson(toDeviceRequest.getParams()); | |
461 | + JsonObject rpcRequest = LwM2mTransportHandlerUtil.validateJson(toDeviceRequest.getParams()); | |
434 | 462 | if (rpcRequest != null) { |
435 | 463 | if (rpcRequest.has(lwm2mClientRpcRequest.keyNameKey)) { |
436 | 464 | String targetIdVer = this.getPresentPathIntoProfile(sessionInfo, |
... | ... | @@ -455,23 +483,21 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
455 | 483 | } |
456 | 484 | if (rpcRequest.has(lwm2mClientRpcRequest.paramsKey) && rpcRequest.get(lwm2mClientRpcRequest.paramsKey).isJsonObject()) { |
457 | 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 | 489 | lwm2mClientRpcRequest.setSessionInfo(sessionInfo); |
462 | 490 | if (OBSERVE_READ_ALL != lwm2mClientRpcRequest.getTypeOper() && lwm2mClientRpcRequest.getTargetIdVer() == null) { |
463 | 491 | lwm2mClientRpcRequest.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " + |
464 | 492 | lwm2mClientRpcRequest.keyNameKey + " is null or bad format"); |
465 | - } | |
466 | - else if ((EXECUTE == lwm2mClientRpcRequest.getTypeOper() | |
493 | + } else if ((EXECUTE == lwm2mClientRpcRequest.getTypeOper() | |
467 | 494 | || WRITE_REPLACE == lwm2mClientRpcRequest.getTypeOper()) |
468 | - && lwm2mClientRpcRequest.getTargetIdVer() !=null | |
495 | + && lwm2mClientRpcRequest.getTargetIdVer() != null | |
469 | 496 | && !(new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResource() |
470 | 497 | || new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResourceInstance())) { |
471 | - lwm2mClientRpcRequest.setErrorMsg("Invalid parameter " + lwm2mClientRpcRequest.targetIdVerKey | |
498 | + lwm2mClientRpcRequest.setErrorMsg("Invalid parameter " + lwm2mClientRpcRequest.targetIdVerKey | |
472 | 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 | 501 | lwm2mClientRpcRequest.setErrorMsg("Procedures In Development..."); |
476 | 502 | } |
477 | 503 | } else { |
... | ... | @@ -483,23 +509,23 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
483 | 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 | 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 | 530 | this.onToDeviceRpcResponse(rpcRequest.getDeviceRpcResponseResultMsg(), rpcRequest.getSessionInfo()); |
505 | 531 | } |
... | ... | @@ -521,7 +547,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
521 | 547 | @Override |
522 | 548 | public void doTrigger(Registration registration, String path) { |
523 | 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 | 580 | * |
555 | 581 | * @param registration - |
556 | 582 | */ |
557 | - protected void onAwakeDev(Registration registration) { | |
583 | + @Override | |
584 | + public void onAwakeDev(Registration registration) { | |
558 | 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 | 587 | //TODO: associate endpointId with device information. |
561 | 588 | } |
562 | 589 | |
... | ... | @@ -583,12 +610,16 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
583 | 610 | |
584 | 611 | /** |
585 | 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 | 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 | 639 | LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration); |
609 | 640 | Set<String> clientObjects = lwM2mClientContext.getSupportedIdVerInClient(registration); |
610 | 641 | if (clientObjects != null && clientObjects.size() > 0) { |
611 | - if (LWM2M_STRATEGY_2 == LwM2mTransportHandler.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) { | |
642 | + if (LWM2M_STRATEGY_2 == LwM2mTransportHandlerUtil.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) { | |
612 | 643 | // #2 |
613 | - lwM2MClient.getPendingRequests().addAll(clientObjects); | |
644 | + lwM2MClient.getPendingReadRequests().addAll(clientObjects); | |
614 | 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 | 648 | // #1 |
618 | 649 | this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, READ, clientObjects); |
... | ... | @@ -652,6 +683,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
652 | 683 | * Sending observe value of resources to thingsboard |
653 | 684 | * #1 Return old Value Resource from LwM2MClient |
654 | 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 | 689 | * @param registration - Registration LwM2M Client |
657 | 690 | * @param lwM2mResource - LwM2mSingleResource response.getContent() |
... | ... | @@ -659,8 +692,21 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
659 | 692 | */ |
660 | 693 | private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) { |
661 | 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 | 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 | 710 | Set<String> paths = new HashSet<>(); |
665 | 711 | paths.add(path); |
666 | 712 | this.updateAttrTelemetry(registration, paths); |
... | ... | @@ -669,6 +715,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
669 | 715 | } |
670 | 716 | } |
671 | 717 | |
718 | + | |
672 | 719 | /** |
673 | 720 | * send Attribute and Telemetry to Thingsboard |
674 | 721 | * #1 - get AttrName/TelemetryName with value from LwM2MClient: |
... | ... | @@ -684,10 +731,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
684 | 731 | SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration); |
685 | 732 | if (results != null && sessionInfo != null) { |
686 | 733 | if (results.getResultAttributes().size() > 0) { |
687 | - this.lwM2mTransportContextServer.sendParametersOnThingsboardAttribute(results.getResultAttributes(), sessionInfo); | |
734 | + this.helper.sendParametersOnThingsboardAttribute(results.getResultAttributes(), sessionInfo); | |
688 | 735 | } |
689 | 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 | 740 | } catch (Exception e) { |
... | ... | @@ -723,22 +770,23 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
723 | 770 | params = this.getPathForWriteAttributes(lwM2MClientProfile.getPostAttributeLwm2mProfile()); |
724 | 771 | result = params.keySet(); |
725 | 772 | } |
726 | - if (!result.isEmpty()) { | |
773 | + if (result != null && !result.isEmpty()) { | |
727 | 774 | // #1 |
728 | 775 | Set<String> pathSend = result.stream().filter(target -> { |
729 | 776 | return target.split(LWM2M_SEPARATOR_PATH).length < 3 ? |
730 | 777 | clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]) : |
731 | 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 | 781 | if (!pathSend.isEmpty()) { |
736 | - lwM2MClient.getPendingRequests().addAll(pathSend); | |
782 | + lwM2MClient.getPendingReadRequests().addAll(pathSend); | |
737 | 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 | 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 | 868 | LwM2mResource resourceValue = lwM2MClient != null ? getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) : null; |
821 | 869 | if (resourceValue != null) { |
822 | 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 | 872 | Object valueKvProto = null; |
825 | 873 | if (resourceValue.isMultiInstances()) { |
826 | 874 | valueKvProto = new JsonObject(); |
... | ... | @@ -837,7 +885,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
837 | 885 | valueKvProto = this.converter.convertValue(resourceValue.getValue(), currentType, expectedType, |
838 | 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 | 890 | } catch (Exception e) { |
843 | 891 | log.error("Failed to add parameters.", e); |
... | ... | @@ -856,7 +904,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
856 | 904 | private Object getResourceValueFormatKv(LwM2mClient lwM2MClient, String pathIdVer) { |
857 | 905 | LwM2mResource resourceValue = this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer); |
858 | 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 | 908 | return this.converter.convertValue(resourceValue.getValue(), currentType, expectedType, |
861 | 909 | new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); |
862 | 910 | } |
... | ... | @@ -969,7 +1017,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
969 | 1017 | // update value in Resources |
970 | 1018 | registrationIds.forEach(registrationId -> { |
971 | 1019 | Registration registration = lwM2mClientContext.getRegistration(registrationId); |
972 | - this.readResourceValueObserve(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ); | |
1020 | + this.readObserveFromProfile(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ); | |
973 | 1021 | // send attr/telemetry to tingsboard for new path |
974 | 1022 | this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd()); |
975 | 1023 | }); |
... | ... | @@ -998,12 +1046,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
998 | 1046 | registrationIds.forEach(registrationId -> { |
999 | 1047 | Registration registration = lwM2mClientContext.getRegistration(registrationId); |
1000 | 1048 | if (postObserveAnalyzer.getPathPostParametersAdd().size() > 0) { |
1001 | - this.readResourceValueObserve(registration, postObserveAnalyzer.getPathPostParametersAdd(), OBSERVE); | |
1049 | + this.readObserveFromProfile(registration, postObserveAnalyzer.getPathPostParametersAdd(), OBSERVE); | |
1002 | 1050 | } |
1003 | 1051 | // 5.3 del |
1004 | 1052 | // send Request cancel observe to Client |
1005 | 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 | 1091 | * @param registration - Registration LwM2M Client |
1044 | 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 | 1095 | targets.forEach(target -> { |
1048 | 1096 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(target)); |
1049 | 1097 | if (pathIds.isResource()) { |
1050 | 1098 | if (READ.equals(typeOper)) { |
1051 | 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 | 1101 | } else if (OBSERVE.equals(typeOper)) { |
1054 | 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 | 1156 | if (!pathSend.isEmpty()) { |
1109 | 1157 | ConcurrentHashMap<String, Object> finalParams = lwm2mAttributesNew; |
1110 | 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 | 1173 | params.clear(); |
1126 | 1174 | params.put(OBJECT_VERSION, ""); |
1127 | 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 | 1181 | |
1134 | 1182 | } |
1135 | 1183 | |
1136 | - private void cancelObserveIsValue(Registration registration, Set<String> paramAnallyzer) { | |
1184 | + private void cancelObserveFromProfile(Registration registration, Set<String> paramAnallyzer) { | |
1137 | 1185 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); |
1138 | 1186 | paramAnallyzer.forEach(pathIdVer -> { |
1139 | 1187 | if (this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) != null) { |
1140 | 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 | 1196 | if (valueNew != null && (valueOld == null || !valueNew.toString().equals(valueOld.toString()))) { |
1149 | 1197 | lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), path, WRITE_REPLACE, |
1150 | 1198 | ContentFormat.TLV.getName(), valueNew, |
1151 | - this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null); | |
1199 | + this.config.getTimeout(), null); | |
1152 | 1200 | } else { |
1153 | 1201 | log.error("Failed update resource [{}] [{}]", path, valueNew); |
1154 | 1202 | String logMsg = String.format("%s: Failed update resource path - %s value - %s. Value is not changed or bad", |
1155 | 1203 | LOG_LW2M_ERROR, path, valueNew); |
1156 | - this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration()); | |
1204 | + this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId()); | |
1157 | 1205 | log.info("Failed update resource [{}] [{}]", path, valueNew); |
1158 | 1206 | } |
1159 | 1207 | } |
... | ... | @@ -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 | 1238 | * @param attributesResponse - |
1189 | 1239 | * @param sessionInfo - |
... | ... | @@ -1191,6 +1241,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
1191 | 1241 | public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg attributesResponse, TransportProtos.SessionInfoProto sessionInfo) { |
1192 | 1242 | try { |
1193 | 1243 | List<TransportProtos.TsKvProto> tsKvProtos = attributesResponse.getSharedAttributeListList(); |
1244 | + | |
1194 | 1245 | this.updateAttriuteFromThingsboard(tsKvProtos, sessionInfo); |
1195 | 1246 | } catch (Exception e) { |
1196 | 1247 | log.error(String.valueOf(e)); |
... | ... | @@ -1223,7 +1274,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
1223 | 1274 | // #2.1 |
1224 | 1275 | lwM2MClient.getDelayedRequests().forEach((pathIdVer, tsKvProto) -> { |
1225 | 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 | 1291 | return null; |
1241 | 1292 | } else { |
1242 | 1293 | return SessionInfoProto.newBuilder() |
1243 | - .setNodeId(this.lwM2mTransportContextServer.getNodeId()) | |
1294 | + .setNodeId(this.context.getNodeId()) | |
1244 | 1295 | .setSessionIdMSB(lwM2MClient.getSessionId().getMostSignificantBits()) |
1245 | 1296 | .setSessionIdLSB(lwM2MClient.getSessionId().getLeastSignificantBits()) |
1246 | 1297 | .setDeviceIdMSB(msg.getDeviceInfo().getDeviceIdMSB()) |
... | ... | @@ -1274,7 +1325,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
1274 | 1325 | */ |
1275 | 1326 | private SessionInfoProto getValidateSessionInfo(String registrationId) { |
1276 | 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 | 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 | 1354 | * @param lwM2MClient - LwM2M Client |
1303 | 1355 | */ |
1304 | 1356 | public void putDelayedUpdateResourcesThingsboard(LwM2mClient lwM2MClient) { |
1305 | 1357 | SessionInfoProto sessionInfo = this.getValidateSessionInfo(lwM2MClient.getRegistration()); |
1306 | 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 | 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 | 1365 | transportService.process(sessionInfo, getAttributeMsg, getAckCallback(lwM2MClient, getAttributeMsg.getRequestId(), DEVICE_ATTRIBUTES_REQUEST)); |
1314 | 1366 | } catch (AdaptorException e) { |
1315 | 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 | 1437 | * @param lwM2MClient - |
1327 | 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 | 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 | 1444 | new TypeToken<ConcurrentHashMap<String, String>>() { |
1336 | 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 | 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 | 1450 | .getModelProvider()); |
1351 | 1451 | Integer objectId = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)).getObjectId(); |
1352 | 1452 | String objectVer = validateObjectVerFromKey(pathIdVer); |
... | ... | @@ -1355,9 +1455,4 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
1355 | 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 | 15 | */ |
16 | 16 | package org.thingsboard.server.transport.lwm2m.server; |
17 | 17 | |
18 | +import lombok.RequiredArgsConstructor; | |
18 | 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 | 22 | import org.eclipse.californium.scandium.config.DtlsConnectorConfig; |
20 | 23 | import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeDecoder; |
21 | 24 | import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder; |
... | ... | @@ -27,12 +30,16 @@ import org.eclipse.leshan.server.model.LwM2mModelProvider; |
27 | 30 | import org.eclipse.leshan.server.security.DefaultAuthorizer; |
28 | 31 | import org.eclipse.leshan.server.security.EditableSecurityStore; |
29 | 32 | import org.eclipse.leshan.server.security.SecurityChecker; |
30 | -import org.springframework.context.annotation.Bean; | |
31 | 33 | import org.springframework.stereotype.Component; |
34 | +import org.thingsboard.server.common.data.StringUtils; | |
32 | 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 | 38 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; |
34 | 39 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; |
35 | 40 | |
41 | +import javax.annotation.PostConstruct; | |
42 | +import javax.annotation.PreDestroy; | |
36 | 43 | import java.math.BigInteger; |
37 | 44 | import java.security.AlgorithmParameters; |
38 | 45 | import java.security.KeyFactory; |
... | ... | @@ -57,61 +64,86 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE |
57 | 64 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; |
58 | 65 | import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; |
59 | 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 | 69 | @Slf4j |
63 | 70 | @Component |
64 | 71 | @TbLwM2mTransportComponent |
65 | -public class LwM2mTransportServerConfiguration { | |
72 | +@RequiredArgsConstructor | |
73 | +public class DefaultLwM2mTransportService implements LwM2MTransportService { | |
74 | + | |
66 | 75 | private PublicKey publicKey; |
67 | 76 | private PrivateKey privateKey; |
68 | 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 | 83 | private final CaliforniumRegistrationStore registrationStore; |
71 | 84 | private final EditableSecurityStore securityStore; |
72 | 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 | 115 | private LeshanServer getLhServer(Integer serverPortNoSec, Integer serverSecurePort) { |
88 | 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 | 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 | 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 | 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 | 132 | builder.setObjectModelProvider(modelProvider); |
102 | 133 | |
103 | - /** Create credentials */ | |
134 | + /* Create credentials */ | |
104 | 135 | this.setServerWithCredentials(builder); |
105 | 136 | |
106 | - /** Set securityStore with new registrationStore */ | |
137 | + /* Set securityStore with new registrationStore */ | |
107 | 138 | builder.setSecurityStore(securityStore); |
108 | 139 | builder.setRegistrationStore(registrationStore); |
109 | 140 | |
110 | 141 | |
111 | - /** Create DTLS Config */ | |
142 | + /* Create DTLS Config */ | |
112 | 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 | 147 | if (this.pskMode) { |
116 | 148 | dtlsConfig.setSupportedCipherSuites( |
117 | 149 | TLS_PSK_WITH_AES_128_CCM_8, |
... | ... | @@ -124,27 +156,27 @@ public class LwM2mTransportServerConfiguration { |
124 | 156 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256); |
125 | 157 | } |
126 | 158 | |
127 | - /** Set DTLS Config */ | |
159 | + /* Set DTLS Config */ | |
128 | 160 | builder.setDtlsConfig(dtlsConfig); |
129 | 161 | |
130 | - /** Create LWM2M server */ | |
162 | + /* Create LWM2M server */ | |
131 | 163 | return builder.build(); |
132 | 164 | } |
133 | 165 | |
134 | 166 | private void setServerWithCredentials(LeshanServerBuilder builder) { |
135 | 167 | try { |
136 | - if (this.context.getLwM2MTransportConfigServer().getKeyStoreValue() != null) { | |
168 | + if (config.getKeyStoreValue() != null) { | |
137 | 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 | 171 | if (rootCAX509Cert != null) { |
140 | 172 | X509Certificate[] trustedCertificates = new X509Certificate[1]; |
141 | 173 | trustedCertificates[0] = rootCAX509Cert; |
142 | 174 | builder.setTrustedCertificates(trustedCertificates); |
143 | 175 | } else { |
144 | - /** by default trust all */ | |
176 | + /* by default trust all */ | |
145 | 177 | builder.setTrustedCertificates(new X509Certificate[0]); |
146 | 178 | } |
147 | - /** Set securityStore with registrationStore*/ | |
179 | + /* Set securityStore with registrationStore*/ | |
148 | 180 | builder.setAuthorizer(new DefaultAuthorizer(securityStore, new SecurityChecker() { |
149 | 181 | @Override |
150 | 182 | protected boolean matchX509Identity(String endpoint, String receivedX509CommonName, |
... | ... | @@ -157,7 +189,7 @@ public class LwM2mTransportServerConfiguration { |
157 | 189 | this.infoPramsUri("RPK"); |
158 | 190 | this.infoParamsServerKey(this.publicKey, this.privateKey); |
159 | 191 | } else { |
160 | - /** by default trust all */ | |
192 | + /* by default trust all */ | |
161 | 193 | builder.setTrustedCertificates(new X509Certificate[0]); |
162 | 194 | log.info("Unable to load X509 files for LWM2MServer"); |
163 | 195 | this.pskMode = true; |
... | ... | @@ -169,17 +201,11 @@ public class LwM2mTransportServerConfiguration { |
169 | 201 | } |
170 | 202 | |
171 | 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 | 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 | 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 | 209 | builder.setPublicKey(serverCertificate.getPublicKey()); |
184 | 210 | builder.setPrivateKey(privateKey); |
185 | 211 | builder.setCertificateChain(new X509Certificate[]{serverCertificate}); |
... | ... | @@ -206,10 +232,12 @@ public class LwM2mTransportServerConfiguration { |
206 | 232 | } |
207 | 233 | |
208 | 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 | 243 | private boolean setServerRPK(LeshanServerBuilder builder) { |
... | ... | @@ -227,55 +255,42 @@ public class LwM2mTransportServerConfiguration { |
227 | 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 | 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 | 260 | AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); |
240 | 261 | algoParameters.init(new ECGenParameterSpec("secp256r1")); |
241 | 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 | 267 | KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), |
251 | 268 | parameterSpec); |
252 | - /** Get keys */ | |
253 | 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 | 274 | try { |
260 | 275 | this.privateKey = KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(privateS)); |
261 | 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 | 282 | private void infoParamsServerKey(PublicKey publicKey, PrivateKey privateKey) { |
268 | - /** Get x coordinate */ | |
283 | + /* Get x coordinate */ | |
269 | 284 | byte[] x = ((ECPublicKey) publicKey).getW().getAffineX().toByteArray(); |
270 | 285 | if (x[0] == 0) |
271 | 286 | x = Arrays.copyOfRange(x, 1, x.length); |
272 | 287 | |
273 | - /** Get Y coordinate */ | |
288 | + /* Get Y coordinate */ | |
274 | 289 | byte[] y = ((ECPublicKey) publicKey).getW().getAffineY().toByteArray(); |
275 | 290 | if (y[0] == 0) |
276 | 291 | y = Arrays.copyOfRange(y, 1, y.length); |
277 | 292 | |
278 | - /** Get Curves params */ | |
293 | + /* Get Curves params */ | |
279 | 294 | String params = ((ECPublicKey) publicKey).getParams().toString(); |
280 | 295 | String privHex = Hex.encodeHexString(privateKey.getEncoded()); |
281 | 296 | log.info(" \n- Public Key (Hex): [{}] \n" + |
... | ... | @@ -292,4 +307,9 @@ public class LwM2mTransportServerConfiguration { |
292 | 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 | 26 | |
27 | 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 | 32 | @Slf4j |
32 | 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 | 38 | this.service = service; |
38 | 39 | } |
39 | 40 | |
... | ... | @@ -85,17 +86,19 @@ public class LwM2mServerListener { |
85 | 86 | |
86 | 87 | @Override |
87 | 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 | 94 | @Override |
92 | 95 | public void onResponse(Observation observation, Registration registration, ObserveResponse response) { |
93 | 96 | if (registration != null) { |
94 | 97 | try { |
95 | - service.onObservationResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(), | |
98 | + service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(), | |
96 | 99 | registration), response, null); |
97 | 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 | 111 | |
109 | 112 | @Override |
110 | 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 | 35 | |
36 | 36 | @Slf4j |
37 | 37 | public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? super Void>>, SessionMsgListener { |
38 | - private LwM2mTransportServiceImpl service; | |
38 | + private DefaultLwM2MTransportMsgHandler service; | |
39 | 39 | private TransportProtos.SessionInfoProto sessionInfo; |
40 | 40 | |
41 | - public LwM2mSessionMsgListener(LwM2mTransportServiceImpl service, TransportProtos.SessionInfoProto sessionInfo) { | |
41 | + public LwM2mSessionMsgListener(DefaultLwM2MTransportMsgHandler service, TransportProtos.SessionInfoProto sessionInfo) { | |
42 | 42 | this.service = service; |
43 | 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 | 25 | import com.google.gson.reflect.TypeToken; |
26 | 26 | import lombok.extern.slf4j.Slf4j; |
27 | 27 | import org.apache.commons.lang3.StringUtils; |
28 | -import org.eclipse.californium.core.network.config.NetworkConfig; | |
29 | 28 | import org.eclipse.leshan.core.attributes.Attribute; |
30 | 29 | import org.eclipse.leshan.core.attributes.AttributeSet; |
31 | 30 | import org.eclipse.leshan.core.model.ObjectModel; |
... | ... | @@ -40,7 +39,6 @@ import org.eclipse.leshan.core.node.codec.CodecException; |
40 | 39 | import org.eclipse.leshan.core.request.DownlinkRequest; |
41 | 40 | import org.eclipse.leshan.core.request.WriteAttributesRequest; |
42 | 41 | import org.eclipse.leshan.core.util.Hex; |
43 | -import org.eclipse.leshan.server.californium.LeshanServerBuilder; | |
44 | 42 | import org.eclipse.leshan.server.registration.Registration; |
45 | 43 | import org.nustaq.serialization.FSTConfiguration; |
46 | 44 | import org.thingsboard.server.common.data.DeviceProfile; |
... | ... | @@ -50,7 +48,6 @@ import org.thingsboard.server.common.transport.TransportServiceCallback; |
50 | 48 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
51 | 49 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; |
52 | 50 | |
53 | -import java.io.File; | |
54 | 51 | import java.io.IOException; |
55 | 52 | import java.util.ArrayList; |
56 | 53 | import java.util.Arrays; |
... | ... | @@ -70,9 +67,8 @@ import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPA |
70 | 67 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; |
71 | 68 | |
72 | 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 | 72 | public static final String TRANSPORT_DEFAULT_LWM2M_VERSION = "1.0"; |
77 | 73 | public static final String CLIENT_LWM2M_SETTINGS = "clientLwM2mSettings"; |
78 | 74 | public static final String BOOTSTRAP = "bootstrap"; |
... | ... | @@ -85,19 +81,12 @@ public class LwM2mTransportHandler { |
85 | 81 | public static final String KEY_NAME = "keyName"; |
86 | 82 | public static final String OBSERVE_LWM2M = "observe"; |
87 | 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 | 85 | private static final String REQUEST = "/request"; |
92 | - // private static final String RESPONSE = "/response"; | |
93 | 86 | private static final String ATTRIBUTES = "/" + ATTRIBUTE; |
94 | 87 | public static final String TELEMETRIES = "/" + TELEMETRY; |
95 | - // public static final String ATTRIBUTES_RESPONSE = ATTRIBUTES + RESPONSE; | |
96 | 88 | public static final String ATTRIBUTES_REQUEST = ATTRIBUTES + REQUEST; |
97 | - // public static final String DEVICE_ATTRIBUTES_RESPONSE = ATTRIBUTES_RESPONSE + "/"; | |
98 | 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 | 91 | public static final long DEFAULT_TIMEOUT = 2 * 60 * 1000L; // 2min in ms |
103 | 92 | |
... | ... | @@ -112,6 +101,11 @@ public class LwM2mTransportHandler { |
112 | 101 | |
113 | 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 | 109 | public enum LwM2mTypeServer { |
116 | 110 | BOOTSTRAP(0, "bootstrap"), |
117 | 111 | CLIENT(1, "client"); |
... | ... | @@ -168,6 +162,8 @@ public class LwM2mTransportHandler { |
168 | 162 | WRITE_ATTRIBUTES(8, "WriteAttributes"), |
169 | 163 | DELETE(9, "Delete"); |
170 | 164 | |
165 | +// READ_INFO_FW(10, "ReadInfoFirmware"); | |
166 | + | |
171 | 167 | public int code; |
172 | 168 | public String type; |
173 | 169 | |
... | ... | @@ -190,21 +186,6 @@ public class LwM2mTransportHandler { |
190 | 186 | public static final String SERVICE_CHANNEL = "SERVICE"; |
191 | 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 | 189 | public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath resourcePath) throws CodecException { |
209 | 190 | switch (type) { |
210 | 191 | case BOOLEAN: |
... | ... | @@ -275,7 +256,7 @@ public class LwM2mTransportHandler { |
275 | 256 | ObjectMapper mapper = new ObjectMapper(); |
276 | 257 | String profileStr = mapper.writeValueAsString(profile); |
277 | 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 | 260 | } catch (IOException e) { |
280 | 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 | 27 | import java.util.Collection; |
28 | 28 | import java.util.Optional; |
29 | 29 | |
30 | -public interface LwM2mTransportService extends TbTransportService { | |
30 | +public interface LwM2mTransportMsgHandler { | |
31 | 31 | |
32 | 32 | void onRegistered(Registration registration, Collection<Observation> previousObsersations); |
33 | 33 | |
... | ... | @@ -39,7 +39,7 @@ public interface LwM2mTransportService extends TbTransportService { |
39 | 39 | |
40 | 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 | 44 | void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo); |
45 | 45 | |
... | ... | @@ -61,5 +61,7 @@ public interface LwM2mTransportService extends TbTransportService { |
61 | 61 | |
62 | 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 | 15 | */ |
16 | 16 | package org.thingsboard.server.transport.lwm2m.server; |
17 | 17 | |
18 | +import lombok.RequiredArgsConstructor; | |
18 | 19 | import lombok.SneakyThrows; |
19 | 20 | import lombok.extern.slf4j.Slf4j; |
20 | 21 | import org.eclipse.californium.core.coap.CoAP; |
... | ... | @@ -50,6 +51,7 @@ import org.eclipse.leshan.server.registration.Registration; |
50 | 51 | import org.springframework.stereotype.Service; |
51 | 52 | import org.thingsboard.server.common.transport.TransportService; |
52 | 53 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
54 | +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; | |
53 | 55 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
54 | 56 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; |
55 | 57 | import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest; |
... | ... | @@ -66,50 +68,38 @@ import java.util.stream.Collectors; |
66 | 68 | import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT; |
67 | 69 | import static org.eclipse.leshan.core.ResponseCode.BAD_REQUEST; |
68 | 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 | 84 | @Slf4j |
82 | 85 | @Service |
83 | 86 | @TbLwM2mTransportComponent |
87 | +@RequiredArgsConstructor | |
84 | 88 | public class LwM2mTransportRequest { |
85 | 89 | private ExecutorService executorResponse; |
86 | 90 | |
87 | 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 | 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 | 99 | @PostConstruct |
110 | 100 | public void init() { |
111 | 101 | this.converter = LwM2mValueConverterImpl.getInstance(); |
112 | - executorResponse = Executors.newFixedThreadPool(this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResponsePoolSize(), | |
102 | + executorResponse = Executors.newFixedThreadPool(this.config.getResponsePoolSize(), | |
113 | 103 | new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL))); |
114 | 104 | } |
115 | 105 | |
... | ... | @@ -125,7 +115,6 @@ public class LwM2mTransportRequest { |
125 | 115 | public void sendAllRequest(Registration registration, String targetIdVer, LwM2mTypeOper typeOper, |
126 | 116 | String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { |
127 | 117 | try { |
128 | - | |
129 | 118 | String target = convertPathFromIdVerToObjectId(targetIdVer); |
130 | 119 | DownlinkRequest request = null; |
131 | 120 | ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT; |
... | ... | @@ -145,11 +134,11 @@ public class LwM2mTransportRequest { |
145 | 134 | break; |
146 | 135 | case OBSERVE: |
147 | 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 | 138 | } else if (resultIds.isObjectInstance()) { |
150 | - request = new ObserveRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId()); | |
139 | + request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId()); | |
151 | 140 | } else if (resultIds.getObjectId() >= 0) { |
152 | - request = new ObserveRequest(resultIds.getObjectId()); | |
141 | + request = new ObserveRequest(contentFormat, resultIds.getObjectId()); | |
153 | 142 | } |
154 | 143 | break; |
155 | 144 | case OBSERVE_CANCEL: |
... | ... | @@ -158,10 +147,10 @@ public class LwM2mTransportRequest { |
158 | 147 | * At server side this will not remove the observation from the observation store, to do it you need to use |
159 | 148 | * {@code ObservationService#cancelObservation()} |
160 | 149 | */ |
161 | - leshanServer.getObservationService().cancelObservations(registration, target); | |
150 | + context.getServer().getObservationService().cancelObservations(registration, target); | |
162 | 151 | break; |
163 | 152 | case EXECUTE: |
164 | - resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer() | |
153 | + resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config | |
165 | 154 | .getModelProvider()); |
166 | 155 | if (params != null && !resourceModel.multiple) { |
167 | 156 | request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resourceModel.type, ResourceModel.Type.STRING, resultIds)); |
... | ... | @@ -171,9 +160,7 @@ public class LwM2mTransportRequest { |
171 | 160 | break; |
172 | 161 | case WRITE_REPLACE: |
173 | 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 | 164 | .getModelProvider()); |
178 | 165 | if (contentFormat.equals(ContentFormat.TLV)) { |
179 | 166 | request = this.getWriteRequestSingleResource(null, resultIds.getObjectId(), |
... | ... | @@ -181,7 +168,6 @@ public class LwM2mTransportRequest { |
181 | 168 | registration, rpcRequest); |
182 | 169 | } |
183 | 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 | 171 | else if (!contentFormat.equals(ContentFormat.TLV)) { |
186 | 172 | request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), |
187 | 173 | resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModel.type, |
... | ... | @@ -215,13 +201,16 @@ public class LwM2mTransportRequest { |
215 | 201 | long finalTimeoutInMs = timeoutInMs; |
216 | 202 | lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, rpcRequest)); |
217 | 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 | 212 | } else { |
224 | - log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper, targetIdVer); | |
213 | + log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer); | |
225 | 214 | if (rpcRequest != null) { |
226 | 215 | String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null"; |
227 | 216 | serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); |
... | ... | @@ -232,12 +221,12 @@ public class LwM2mTransportRequest { |
232 | 221 | serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); |
233 | 222 | } |
234 | 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 | 225 | Set<String> observationPaths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet()); |
237 | 226 | String msg = String.format("%s: type operation %s observation paths - %s", LOG_LW2M_INFO, |
238 | 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 | 230 | if (rpcRequest != null) { |
242 | 231 | String valueMsg = String.format("Observation paths - %s", observationPaths); |
243 | 232 | serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE); |
... | ... | @@ -246,7 +235,7 @@ public class LwM2mTransportRequest { |
246 | 235 | } catch (Exception e) { |
247 | 236 | String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR, |
248 | 237 | typeOper.name(), e.getMessage()); |
249 | - serviceImpl.sendLogsToThingsboard(msg, registration); | |
238 | + serviceImpl.sendLogsToThingsboard(msg, registration.getId()); | |
250 | 239 | throw new Exception(e); |
251 | 240 | } |
252 | 241 | } |
... | ... | @@ -259,47 +248,55 @@ public class LwM2mTransportRequest { |
259 | 248 | |
260 | 249 | @SuppressWarnings("unchecked") |
261 | 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 | 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 | 255 | if (CoAP.ResponseCode.isSuccess(((Response) response.getCoapResponse()).getCode())) { |
267 | 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 | 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 | 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 | 266 | if (rpcRequest != null) { |
287 | 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 | 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 | 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 | 296 | if (rpcRequest != null) { |
299 | 297 | serviceImpl.sentRpcRequest(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR); |
300 | 298 | } |
301 | 299 | }); |
302 | - | |
303 | 300 | } |
304 | 301 | |
305 | 302 | private WriteRequest getWriteRequestSingleResource(ContentFormat contentFormat, Integer objectId, Integer instanceId, |
... | ... | @@ -323,7 +320,9 @@ public class LwM2mTransportRequest { |
323 | 320 | Date date = new Date(Long.decode(value.toString())); |
324 | 321 | return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, date) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, date); |
325 | 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 | 326 | default: |
328 | 327 | } |
329 | 328 | } |
... | ... | @@ -337,7 +336,7 @@ public class LwM2mTransportRequest { |
337 | 336 | String patn = "/" + objectId + "/" + instanceId + "/" + resourceId; |
338 | 337 | String msg = String.format(LOG_LW2M_ERROR + ": NumberFormatException: Resource path - %s type - %s value - %s msg error - %s SendRequest to Client", |
339 | 338 | patn, type, value, e.toString()); |
340 | - serviceImpl.sendLogsToThingsboard(msg, registration); | |
339 | + serviceImpl.sendLogsToThingsboard(msg, registration.getId()); | |
341 | 340 | log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString()); |
342 | 341 | if (rpcRequest != null) { |
343 | 342 | String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value); |
... | ... | @@ -369,7 +368,7 @@ public class LwM2mTransportRequest { |
369 | 368 | DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { |
370 | 369 | String pathIdVer = convertPathFromObjectIdToIdVer(path, registration); |
371 | 370 | if (response instanceof ReadResponse) { |
372 | - serviceImpl.onObservationResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest); | |
371 | + serviceImpl.onUpdateValueAfterReadResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest); | |
373 | 372 | } else if (response instanceof CancelObservationResponse) { |
374 | 373 | log.info("[{}] Path [{}] CancelObservationResponse 3_Send", pathIdVer, response); |
375 | 374 | |
... | ... | @@ -389,14 +388,56 @@ public class LwM2mTransportRequest { |
389 | 388 | } else if (response instanceof WriteAttributesResponse) { |
390 | 389 | log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response); |
391 | 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 | 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 | 31 | */ |
32 | 32 | |
33 | 33 | import lombok.Getter; |
34 | +import lombok.RequiredArgsConstructor; | |
34 | 35 | import lombok.extern.slf4j.Slf4j; |
35 | 36 | import org.eclipse.leshan.core.model.DDFFileParser; |
36 | 37 | import org.eclipse.leshan.core.model.DefaultDDFFileValidator; |
... | ... | @@ -39,11 +40,8 @@ import org.eclipse.leshan.core.model.ObjectModel; |
39 | 40 | import org.eclipse.leshan.core.model.ResourceModel; |
40 | 41 | import org.eclipse.leshan.core.node.codec.CodecException; |
41 | 42 | import org.springframework.stereotype.Component; |
42 | -import org.thingsboard.server.common.transport.TransportContext; | |
43 | -import org.thingsboard.server.common.transport.TransportResourceCache; | |
44 | 43 | import org.thingsboard.server.common.transport.TransportService; |
45 | 44 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
46 | -import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer; | |
47 | 45 | import org.thingsboard.server.gen.transport.TransportProtos; |
48 | 46 | import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; |
49 | 47 | import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; |
... | ... | @@ -57,39 +55,21 @@ import java.util.ArrayList; |
57 | 55 | import java.util.List; |
58 | 56 | |
59 | 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 | 60 | @Slf4j |
63 | 61 | @Component |
64 | 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 | 68 | private final TransportService transportService; |
71 | 69 | |
72 | - private final TransportResourceCache transportResourceCache; | |
73 | - | |
74 | - | |
75 | 70 | @Getter |
76 | 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 | 74 | * send to Thingsboard Attribute || Telemetry |
95 | 75 | * |
... | ... | @@ -134,7 +114,7 @@ public class LwM2mTransportContextServer extends TransportContext { |
134 | 114 | */ |
135 | 115 | public SessionInfoProto getValidateSessionInfo(TransportProtos.ValidateDeviceCredentialsResponseMsg msg, long mostSignificantBits, long leastSignificantBits) { |
136 | 116 | return SessionInfoProto.newBuilder() |
137 | - .setNodeId(this.getNodeId()) | |
117 | + .setNodeId(context.getNodeId()) | |
138 | 118 | .setSessionIdMSB(mostSignificantBits) |
139 | 119 | .setSessionIdLSB(leastSignificantBits) |
140 | 120 | .setDeviceIdMSB(msg.getDeviceInfo().getDeviceIdMSB()) |
... | ... | @@ -165,8 +145,8 @@ public class LwM2mTransportContextServer extends TransportContext { |
165 | 145 | * @param logMsg - info about Logs |
166 | 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 | 150 | result.add(TransportProtos.KeyValueProto.newBuilder() |
171 | 151 | .setKey(LOG_LW2M_TELEMETRY) |
172 | 152 | .setType(TransportProtos.KeyValueType.STRING_V) |
... | ... | @@ -179,32 +159,31 @@ public class LwM2mTransportContextServer extends TransportContext { |
179 | 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 | 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 | 213 | switch (kv.getType()) { |
235 | 214 | case BOOLEAN_V: |
236 | 215 | return kv.getBoolV(); | ... | ... |
... | ... | @@ -30,35 +30,4 @@ import javax.annotation.PreDestroy; |
30 | 30 | @TbLwM2mTransportComponent |
31 | 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 | 15 | */ |
16 | 16 | package org.thingsboard.server.transport.lwm2m.server; |
17 | 17 | |
18 | +import lombok.RequiredArgsConstructor; | |
18 | 19 | import lombok.extern.slf4j.Slf4j; |
19 | 20 | import org.eclipse.leshan.core.model.DefaultDDFFileValidator; |
20 | 21 | import org.eclipse.leshan.core.model.LwM2mModel; |
... | ... | @@ -37,6 +38,7 @@ import static org.thingsboard.server.common.data.ResourceType.LWM2M_MODEL; |
37 | 38 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; |
38 | 39 | |
39 | 40 | @Slf4j |
41 | +@RequiredArgsConstructor | |
40 | 42 | public class LwM2mVersionedModelProvider implements LwM2mModelProvider { |
41 | 43 | |
42 | 44 | /** |
... | ... | @@ -46,12 +48,8 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { |
46 | 48 | * Value = TenantId |
47 | 49 | */ |
48 | 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 | 54 | private String getKeyIdVer(Integer objectId, String version) { |
57 | 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 | 118 | private ObjectModel getObjectModelDynamic(Integer objectId, String version) { |
121 | 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 | 124 | Base64.getDecoder().decode(resource.getData()), |
129 | 125 | key + ".xml", |
130 | 126 | new DefaultDDFFileValidator())).orElse(null); | ... | ... |
... | ... | @@ -24,11 +24,8 @@ import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
24 | 24 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
25 | 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 | 28 | import java.util.Random; |
31 | -import java.util.Set; | |
32 | 29 | |
33 | 30 | @Slf4j |
34 | 31 | @Component("LwM2MJsonAdaptor") |
... | ... | @@ -54,11 +51,7 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor { |
54 | 51 | } |
55 | 52 | |
56 | 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 | 55 | try { |
63 | 56 | TransportProtos.GetAttributeRequestMsg.Builder result = TransportProtos.GetAttributeRequestMsg.newBuilder(); |
64 | 57 | Random random = new Random(); |
... | ... | @@ -75,14 +68,4 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor { |
75 | 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 | 19 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
20 | 20 | import org.thingsboard.server.gen.transport.TransportProtos; |
21 | 21 | |
22 | -import java.util.List; | |
22 | +import java.util.Collection; | |
23 | 23 | |
24 | 24 | public interface LwM2MTransportAdaptor { |
25 | 25 | |
... | ... | @@ -27,5 +27,5 @@ public interface LwM2MTransportAdaptor { |
27 | 27 | |
28 | 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 | 27 | import org.thingsboard.server.gen.transport.TransportProtos; |
28 | 28 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; |
29 | 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 | 31 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; |
32 | 32 | |
33 | 33 | import java.util.Collection; |
... | ... | @@ -42,9 +42,9 @@ import java.util.concurrent.CopyOnWriteArrayList; |
42 | 42 | import java.util.stream.Collectors; |
43 | 43 | |
44 | 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 | 49 | @Slf4j |
50 | 50 | @Data |
... | ... | @@ -57,13 +57,15 @@ public class LwM2mClient implements Cloneable { |
57 | 57 | private UUID deviceId; |
58 | 58 | private UUID sessionId; |
59 | 59 | private UUID profileId; |
60 | + private volatile LwM2mFirmwareUpdate frUpdate; | |
60 | 61 | private Registration registration; |
61 | 62 | private ValidateDeviceCredentialsResponseMsg credentialsResponse; |
62 | 63 | private final Map<String, ResourceValue> resources; |
63 | 64 | private final Map<String, TransportProtos.TsKvProto> delayedRequests; |
64 | - private final List<String> pendingRequests; | |
65 | + private final List<String> pendingReadRequests; | |
65 | 66 | private final Queue<LwM2mQueuedRequest> queuedRequests; |
66 | 67 | private boolean init; |
68 | + private volatile boolean updateFw; | |
67 | 69 | |
68 | 70 | public Object clone() throws CloneNotSupportedException { |
69 | 71 | return super.clone(); |
... | ... | @@ -75,12 +77,14 @@ public class LwM2mClient implements Cloneable { |
75 | 77 | this.securityInfo = securityInfo; |
76 | 78 | this.credentialsResponse = credentialsResponse; |
77 | 79 | this.delayedRequests = new ConcurrentHashMap<>(); |
78 | - this.pendingRequests = new CopyOnWriteArrayList<>(); | |
80 | + this.pendingReadRequests = new CopyOnWriteArrayList<>(); | |
79 | 81 | this.resources = new ConcurrentHashMap<>(); |
80 | 82 | this.profileId = profileId; |
81 | 83 | this.sessionId = sessionId; |
82 | 84 | this.init = false; |
85 | + this.updateFw = false; | |
83 | 86 | this.queuedRequests = new ConcurrentLinkedQueue<>(); |
87 | + this.frUpdate = new LwM2mFirmwareUpdate(); | |
84 | 88 | } |
85 | 89 | |
86 | 90 | public boolean saveResourceValue(String pathRez, LwM2mResource rez, LwM2mModelProvider modelProvider) { |
... | ... | @@ -103,15 +107,13 @@ public class LwM2mClient implements Cloneable { |
103 | 107 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez)); |
104 | 108 | String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); |
105 | 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 | 111 | .getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()) : null; |
108 | 112 | } |
109 | 113 | |
110 | 114 | public Collection<LwM2mResource> getNewResourcesForInstance(String pathRezIdVer, LwM2mModelProvider modelProvider, |
111 | 115 | LwM2mValueConverterImpl converter) { |
112 | 116 | LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer)); |
113 | - String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); | |
114 | - String verRez = getVerFromPathIdVerOrId(pathRezIdVer); | |
115 | 117 | Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet(); |
116 | 118 | Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration) |
117 | 119 | .getObjectModel(pathIds.getObjectId()).resources; |
... | ... | @@ -170,11 +172,11 @@ public class LwM2mClient implements Cloneable { |
170 | 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 | 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 | 180 | this.init = true; |
179 | 181 | serviceImpl.putDelayedUpdateResourcesThingsboard(this); |
180 | 182 | } | ... | ... |
... | ... | @@ -25,7 +25,7 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
25 | 25 | import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; |
26 | 26 | import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; |
27 | 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 | 30 | import java.util.Arrays; |
31 | 31 | import java.util.Map; |
... | ... | @@ -34,7 +34,7 @@ import java.util.UUID; |
34 | 34 | import java.util.concurrent.ConcurrentHashMap; |
35 | 35 | |
36 | 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 | 39 | @Service |
40 | 40 | @TbLwM2mTransportComponent |
... | ... | @@ -82,12 +82,12 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { |
82 | 82 | |
83 | 83 | @Override |
84 | 84 | public LwM2mClient getLwM2mClientWithReg(Registration registration, String registrationId) { |
85 | - LwM2mClient client = registrationId != null ? | |
85 | + LwM2mClient client = registrationId != null && this.lwM2mClients.containsKey(registrationId) ? | |
86 | 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 | 93 | @Override |
... | ... | @@ -118,7 +118,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { |
118 | 118 | */ |
119 | 119 | @Override |
120 | 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 | 122 | if (store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { |
123 | 123 | UUID profileUuid = (store.getDeviceProfile() != null && addUpdateProfileParameters(store.getDeviceProfile())) ? store.getDeviceProfile().getUuidId() : null; |
124 | 124 | LwM2mClient client; |
... | ... | @@ -165,7 +165,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { |
165 | 165 | |
166 | 166 | @Override |
167 | 167 | public boolean addUpdateProfileParameters(DeviceProfile deviceProfile) { |
168 | - LwM2mClientProfile lwM2MClientProfile = LwM2mTransportHandler.getLwM2MClientProfileFromThingsboard(deviceProfile); | |
168 | + LwM2mClientProfile lwM2MClientProfile = LwM2mTransportHandlerUtil.getLwM2MClientProfileFromThingsboard(deviceProfile); | |
169 | 169 | if (lwM2MClientProfile != null) { |
170 | 170 | profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile); |
171 | 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 | 21 | import org.eclipse.leshan.server.registration.Registration; |
22 | 22 | import org.thingsboard.server.gen.transport.TransportProtos; |
23 | 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 | 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 | 30 | @Data |
31 | 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 | 47 | import org.thingsboard.server.common.data.DeviceTransportType; |
48 | 48 | import org.thingsboard.server.common.data.TransportPayloadType; |
49 | 49 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
50 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
50 | 51 | import org.thingsboard.server.common.data.id.FirmwareId; |
51 | 52 | import org.thingsboard.server.common.msg.EncryptionUtil; |
52 | 53 | import org.thingsboard.server.common.msg.tools.TbRateLimitsException; |
... | ... | @@ -59,6 +60,7 @@ import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; |
59 | 60 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
60 | 61 | import org.thingsboard.server.common.transport.service.DefaultTransportService; |
61 | 62 | import org.thingsboard.server.common.transport.service.SessionMetaData; |
63 | +import org.thingsboard.server.common.transport.util.SslUtil; | |
62 | 64 | import org.thingsboard.server.gen.transport.TransportProtos; |
63 | 65 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; |
64 | 66 | import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent; |
... | ... | @@ -68,7 +70,6 @@ import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor; |
68 | 70 | import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx; |
69 | 71 | import org.thingsboard.server.transport.mqtt.session.GatewaySessionHandler; |
70 | 72 | import org.thingsboard.server.transport.mqtt.session.MqttTopicMatcher; |
71 | -import org.thingsboard.server.common.transport.util.SslUtil; | |
72 | 73 | |
73 | 74 | import javax.net.ssl.SSLPeerUnverifiedException; |
74 | 75 | import java.io.IOException; |
... | ... | @@ -97,6 +98,8 @@ import static io.netty.handler.codec.mqtt.MqttMessageType.UNSUBACK; |
97 | 98 | import static io.netty.handler.codec.mqtt.MqttQoS.AT_LEAST_ONCE; |
98 | 99 | import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE; |
99 | 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 | 105 | * @author Andrew Shvayka |
... | ... | @@ -104,7 +107,9 @@ import static io.netty.handler.codec.mqtt.MqttQoS.FAILURE; |
104 | 107 | @Slf4j |
105 | 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 | 114 | private static final String PAYLOAD_TOO_LARGE = "PAYLOAD_TOO_LARGE"; |
110 | 115 | |
... | ... | @@ -314,38 +319,10 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
314 | 319 | } else if (topicName.equals(MqttTopics.DEVICE_CLAIM_TOPIC)) { |
315 | 320 | TransportProtos.ClaimDeviceMsg claimDeviceMsg = payloadAdaptor.convertToClaimDevice(deviceSessionCtx, mqttMsg); |
316 | 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 | 326 | } else { |
350 | 327 | transportService.reportActivity(deviceSessionCtx.getSessionInfo()); |
351 | 328 | ack(ctx, msgId); |
... | ... | @@ -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 | 372 | private void ack(ChannelHandlerContext ctx, int msgId) { |
361 | 373 | if (msgId > 0) { |
362 | 374 | ctx.writeAndFlush(createMqttPubAckMsg(msgId)); |
... | ... | @@ -435,7 +447,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
435 | 447 | if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())) { |
436 | 448 | FirmwareId firmwareId = new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())); |
437 | 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 | 451 | } else { |
440 | 452 | sendFirmwareError(ctx, response.getResponseStatus().toString()); |
441 | 453 | } |
... | ... | @@ -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 | 464 | log.trace("[{}] Send firmware [{}] to device!", sessionId, firmwareId); |
453 | 465 | ack(ctx, msgId); |
454 | 466 | try { |
455 | 467 | byte[] firmwareChunk = context.getFirmwareDataCache().get(firmwareId, chunkSize, chunk); |
456 | 468 | deviceSessionCtx.getPayloadAdaptor() |
457 | - .convertToPublish(deviceSessionCtx, firmwareChunk, requestId, chunk) | |
469 | + .convertToPublish(deviceSessionCtx, firmwareChunk, requestId, chunk, type) | |
458 | 470 | .ifPresent(deviceSessionCtx.getChannel()::writeAndFlush); |
459 | 471 | if (firmwareChunk != null && chunkSize != firmwareChunk.length) { |
460 | 472 | scheduler.schedule(() -> processDisconnect(ctx), 60, TimeUnit.SECONDS); |
... | ... | @@ -504,6 +516,8 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
504 | 516 | case MqttTopics.DEVICE_PROVISION_RESPONSE_TOPIC: |
505 | 517 | case MqttTopics.DEVICE_FIRMWARE_RESPONSES_TOPIC: |
506 | 518 | case MqttTopics.DEVICE_FIRMWARE_ERROR_TOPIC: |
519 | + case MqttTopics.DEVICE_SOFTWARE_RESPONSES_TOPIC: | |
520 | + case MqttTopics.DEVICE_SOFTWARE_ERROR_TOPIC: | |
507 | 521 | registerSubQoS(topic, grantedQoSList, reqQoS); |
508 | 522 | break; |
509 | 523 | default: | ... | ... |
... | ... | @@ -30,6 +30,7 @@ import lombok.extern.slf4j.Slf4j; |
30 | 30 | import org.springframework.stereotype.Component; |
31 | 31 | import org.springframework.util.StringUtils; |
32 | 32 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
33 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
33 | 34 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
34 | 35 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
35 | 36 | import org.thingsboard.server.gen.transport.TransportProtos; |
... | ... | @@ -43,6 +44,9 @@ import java.util.Optional; |
43 | 44 | import java.util.Set; |
44 | 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 | 51 | * @author Andrew Shvayka |
48 | 52 | */ |
... | ... | @@ -151,8 +155,8 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { |
151 | 155 | } |
152 | 156 | |
153 | 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 | 162 | public static JsonElement validateJsonPayload(UUID sessionId, ByteBuf payloadData) throws AdaptorException { | ... | ... |
... | ... | @@ -23,6 +23,7 @@ import io.netty.handler.codec.mqtt.MqttMessage; |
23 | 23 | import io.netty.handler.codec.mqtt.MqttMessageType; |
24 | 24 | import io.netty.handler.codec.mqtt.MqttPublishMessage; |
25 | 25 | import io.netty.handler.codec.mqtt.MqttPublishVariableHeader; |
26 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
26 | 27 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
27 | 28 | import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; |
28 | 29 | import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg; |
... | ... | @@ -77,7 +78,7 @@ public interface MqttTransportAdaptor { |
77 | 78 | |
78 | 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 | 83 | default MqttPublishMessage createMqttPublishMsg(MqttDeviceAwareSessionContext ctx, String topic, byte[] payloadInBytes) { |
83 | 84 | MqttFixedHeader mqttFixedHeader = | ... | ... |
... | ... | @@ -28,6 +28,7 @@ import lombok.extern.slf4j.Slf4j; |
28 | 28 | import org.springframework.stereotype.Component; |
29 | 29 | import org.springframework.util.StringUtils; |
30 | 30 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
31 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
31 | 32 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
32 | 33 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
33 | 34 | import org.thingsboard.server.common.transport.adaptor.ProtoConverter; |
... | ... | @@ -38,6 +39,8 @@ import org.thingsboard.server.transport.mqtt.session.MqttDeviceAwareSessionConte |
38 | 39 | |
39 | 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 | 44 | @Component |
42 | 45 | @Slf4j |
43 | 46 | public class ProtoMqttAdaptor implements MqttTransportAdaptor { |
... | ... | @@ -165,8 +168,8 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor { |
165 | 168 | } |
166 | 169 | |
167 | 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 | 175 | @Override | ... | ... |
... | ... | @@ -51,11 +51,13 @@ public abstract class TransportContext { |
51 | 51 | @Getter |
52 | 52 | private ExecutorService executor; |
53 | 53 | |
54 | - | |
55 | 54 | @Getter |
56 | 55 | @Autowired |
57 | 56 | private FirmwareDataCache firmwareDataCache; |
58 | 57 | |
58 | + @Autowired | |
59 | + private TransportResourceCache transportResourceCache; | |
60 | + | |
59 | 61 | @PostConstruct |
60 | 62 | public void init() { |
61 | 63 | executor = ThingsBoardExecutors.newWorkStealingPool(50, getClass()); | ... | ... |
... | ... | @@ -83,6 +83,8 @@ public interface DeviceDao extends Dao<Device>, TenantEntityDao { |
83 | 83 | |
84 | 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 | 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 | 56 | import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; |
57 | 57 | import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; |
58 | 58 | import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; |
59 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
59 | 60 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
60 | 61 | import org.thingsboard.server.common.data.id.TenantId; |
61 | 62 | import org.thingsboard.server.common.data.page.PageData; |
... | ... | @@ -406,9 +407,31 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
406 | 407 | if (firmware == null) { |
407 | 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 | 413 | if (firmware.getData() == null) { |
410 | 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 | 53 | import org.thingsboard.server.common.data.device.data.MqttDeviceTransportConfiguration; |
54 | 54 | import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration; |
55 | 55 | import org.thingsboard.server.common.data.edge.Edge; |
56 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
56 | 57 | import org.thingsboard.server.common.data.id.CustomerId; |
57 | 58 | import org.thingsboard.server.common.data.id.DeviceId; |
58 | 59 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
... | ... | @@ -361,7 +362,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe |
361 | 362 | |
362 | 363 | @Override |
363 | 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 | 366 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
366 | 367 | validateString(type, "Incorrect type " + type); |
367 | 368 | validatePageLink(pageLink); |
... | ... | @@ -369,6 +370,15 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe |
369 | 370 | } |
370 | 371 | |
371 | 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 | 382 | public PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink) { |
373 | 383 | log.trace("Executing findDeviceInfosByTenantIdAndType, tenantId [{}], type [{}], pageLink [{}]", tenantId, type, pageLink); |
374 | 384 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
... | ... | @@ -696,9 +706,31 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe |
696 | 706 | if (firmware == null) { |
697 | 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 | 712 | if (firmware.getData() == null) { |
700 | 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 | }; | ... | ... |