Commit 5ca0e05ab57ae1c0aead5a1956bd16a3f80f1d73
Committed by
GitHub
Merge pull request #4524 from thingsboard/feature/sota
FOTA/SOTA
Showing
66 changed files
with
1239 additions
and
263 deletions
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | } | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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()); | ... | ... |
... | ... | @@ -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 = "current_fw_title"; | |
99 | - public static final String CURRENT_FIRMWARE_VERSION = "current_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; | ... | ... |
... | ... | @@ -41,6 +41,9 @@ import org.thingsboard.common.util.JacksonUtil; |
41 | 41 | import org.thingsboard.server.cache.firmware.FirmwareDataCache; |
42 | 42 | import org.thingsboard.server.common.data.Device; |
43 | 43 | import org.thingsboard.server.common.data.DeviceProfile; |
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; | |
44 | 47 | import org.thingsboard.server.common.data.id.FirmwareId; |
45 | 48 | import org.thingsboard.server.common.transport.TransportService; |
46 | 49 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
... | ... | @@ -79,7 +82,6 @@ import java.util.stream.Collectors; |
79 | 82 | |
80 | 83 | import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST; |
81 | 84 | import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION; |
82 | -import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_VERSION; | |
83 | 85 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; |
84 | 86 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; |
85 | 87 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.CLIENT_NOT_AUTHORIZED; |
... | ... | @@ -332,7 +334,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
332 | 334 | String pathName = tsKvProto.getKv().getKey(); |
333 | 335 | String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName); |
334 | 336 | Object valueNew = this.lwM2mTransportContextServer.getValueFromKvProto(tsKvProto.getKv()); |
335 | - if (FIRMWARE_VERSION.equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) { | |
337 | + if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) { | |
336 | 338 | this.getInfoFirmwareUpdate(lwM2MClient); |
337 | 339 | } |
338 | 340 | if (pathIdVer != null) { |
... | ... | @@ -358,7 +360,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
358 | 360 | msg.getSharedUpdatedList().forEach(tsKvProto -> { |
359 | 361 | String pathName = tsKvProto.getKv().getKey(); |
360 | 362 | Object valueNew = this.lwM2mTransportContextServer.getValueFromKvProto(tsKvProto.getKv()); |
361 | - if (FIRMWARE_VERSION.equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) { | |
363 | + if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) { | |
362 | 364 | lwM2MClient.getFrUpdate().setCurrentFwVersion((String) valueNew); |
363 | 365 | } |
364 | 366 | }); | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | }; | ... | ... |
... | ... | @@ -27,13 +27,17 @@ import org.springframework.cache.CacheManager; |
27 | 27 | import org.springframework.cache.annotation.Cacheable; |
28 | 28 | import org.springframework.stereotype.Service; |
29 | 29 | import org.thingsboard.server.cache.firmware.FirmwareDataCache; |
30 | +import org.thingsboard.server.common.data.DeviceProfile; | |
30 | 31 | import org.thingsboard.server.common.data.Firmware; |
31 | 32 | import org.thingsboard.server.common.data.FirmwareInfo; |
32 | 33 | import org.thingsboard.server.common.data.Tenant; |
34 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
35 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | |
33 | 36 | import org.thingsboard.server.common.data.id.FirmwareId; |
34 | 37 | import org.thingsboard.server.common.data.id.TenantId; |
35 | 38 | import org.thingsboard.server.common.data.page.PageData; |
36 | 39 | import org.thingsboard.server.common.data.page.PageLink; |
40 | +import org.thingsboard.server.dao.device.DeviceProfileDao; | |
37 | 41 | import org.thingsboard.server.dao.exception.DataValidationException; |
38 | 42 | import org.thingsboard.server.dao.service.DataValidator; |
39 | 43 | import org.thingsboard.server.dao.service.PaginatedRemover; |
... | ... | @@ -56,6 +60,7 @@ public class BaseFirmwareService implements FirmwareService { |
56 | 60 | public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; |
57 | 61 | |
58 | 62 | private final TenantDao tenantDao; |
63 | + private final DeviceProfileDao deviceProfileDao; | |
59 | 64 | private final FirmwareDao firmwareDao; |
60 | 65 | private final FirmwareInfoDao firmwareInfoDao; |
61 | 66 | private final CacheManager cacheManager; |
... | ... | @@ -124,7 +129,8 @@ public class BaseFirmwareService implements FirmwareService { |
124 | 129 | public ListenableFuture<FirmwareInfo> findFirmwareInfoByIdAsync(TenantId tenantId, FirmwareId firmwareId) { |
125 | 130 | log.trace("Executing findFirmwareInfoByIdAsync [{}]", firmwareId); |
126 | 131 | validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId); |
127 | - return firmwareInfoDao.findByIdAsync(tenantId, firmwareId.getId()); } | |
132 | + return firmwareInfoDao.findByIdAsync(tenantId, firmwareId.getId()); | |
133 | + } | |
128 | 134 | |
129 | 135 | @Override |
130 | 136 | public PageData<FirmwareInfo> findTenantFirmwaresByTenantId(TenantId tenantId, PageLink pageLink) { |
... | ... | @@ -135,11 +141,11 @@ public class BaseFirmwareService implements FirmwareService { |
135 | 141 | } |
136 | 142 | |
137 | 143 | @Override |
138 | - public PageData<FirmwareInfo> findTenantFirmwaresByTenantIdAndHasData(TenantId tenantId, boolean hasData, PageLink pageLink) { | |
144 | + public PageData<FirmwareInfo> findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, FirmwareType firmwareType, boolean hasData, PageLink pageLink) { | |
139 | 145 | log.trace("Executing findTenantFirmwaresByTenantIdAndHasData, tenantId [{}], hasData [{}] pageLink [{}]", tenantId, hasData, pageLink); |
140 | 146 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
141 | 147 | validatePageLink(pageLink); |
142 | - return firmwareInfoDao.findFirmwareInfoByTenantIdAndHasData(tenantId, hasData, pageLink); | |
148 | + return firmwareInfoDao.findFirmwareInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(tenantId, deviceProfileId, firmwareType, hasData, pageLink); | |
143 | 149 | } |
144 | 150 | |
145 | 151 | @Override |
... | ... | @@ -157,6 +163,10 @@ public class BaseFirmwareService implements FirmwareService { |
157 | 163 | throw new DataValidationException("The firmware referenced by the devices cannot be deleted!"); |
158 | 164 | } else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_firmware_device_profile")) { |
159 | 165 | throw new DataValidationException("The firmware referenced by the device profile cannot be deleted!"); |
166 | + } else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_software_device")) { | |
167 | + throw new DataValidationException("The software referenced by the devices cannot be deleted!"); | |
168 | + } else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_software_device_profile")) { | |
169 | + throw new DataValidationException("The software referenced by the device profile cannot be deleted!"); | |
160 | 170 | } else { |
161 | 171 | throw t; |
162 | 172 | } |
... | ... | @@ -173,29 +183,15 @@ public class BaseFirmwareService implements FirmwareService { |
173 | 183 | private DataValidator<FirmwareInfo> firmwareInfoValidator = new DataValidator<>() { |
174 | 184 | |
175 | 185 | @Override |
176 | - protected void validateDataImpl(TenantId tenantId, FirmwareInfo firmware) { | |
177 | - if (firmware.getTenantId() == null) { | |
178 | - throw new DataValidationException("Firmware should be assigned to tenant!"); | |
179 | - } else { | |
180 | - Tenant tenant = tenantDao.findById(firmware.getTenantId(), firmware.getTenantId().getId()); | |
181 | - if (tenant == null) { | |
182 | - throw new DataValidationException("Firmware is referencing to non-existent tenant!"); | |
183 | - } | |
184 | - } | |
185 | - | |
186 | - if (StringUtils.isEmpty(firmware.getTitle())) { | |
187 | - throw new DataValidationException("Firmware title should be specified!"); | |
188 | - } | |
189 | - | |
190 | - if (StringUtils.isEmpty(firmware.getVersion())) { | |
191 | - throw new DataValidationException("Firmware version should be specified!"); | |
192 | - } | |
186 | + protected void validateDataImpl(TenantId tenantId, FirmwareInfo firmwareInfo) { | |
187 | + validateImpl(firmwareInfo); | |
193 | 188 | } |
194 | 189 | |
195 | 190 | @Override |
196 | 191 | protected void validateUpdate(TenantId tenantId, FirmwareInfo firmware) { |
197 | 192 | FirmwareInfo firmwareOld = firmwareInfoDao.findById(tenantId, firmware.getUuidId()); |
198 | 193 | |
194 | + validateUpdateDeviceProfile(firmware, firmwareOld); | |
199 | 195 | BaseFirmwareService.validateUpdate(firmware, firmwareOld); |
200 | 196 | } |
201 | 197 | }; |
... | ... | @@ -204,22 +200,7 @@ public class BaseFirmwareService implements FirmwareService { |
204 | 200 | |
205 | 201 | @Override |
206 | 202 | protected void validateDataImpl(TenantId tenantId, Firmware firmware) { |
207 | - if (firmware.getTenantId() == null) { | |
208 | - throw new DataValidationException("Firmware should be assigned to tenant!"); | |
209 | - } else { | |
210 | - Tenant tenant = tenantDao.findById(firmware.getTenantId(), firmware.getTenantId().getId()); | |
211 | - if (tenant == null) { | |
212 | - throw new DataValidationException("Firmware is referencing to non-existent tenant!"); | |
213 | - } | |
214 | - } | |
215 | - | |
216 | - if (StringUtils.isEmpty(firmware.getTitle())) { | |
217 | - throw new DataValidationException("Firmware title should be specified!"); | |
218 | - } | |
219 | - | |
220 | - if (StringUtils.isEmpty(firmware.getVersion())) { | |
221 | - throw new DataValidationException("Firmware version should be specified!"); | |
222 | - } | |
203 | + validateImpl(firmware); | |
223 | 204 | |
224 | 205 | if (StringUtils.isEmpty(firmware.getFileName())) { |
225 | 206 | throw new DataValidationException("Firmware file name should be specified!"); |
... | ... | @@ -267,6 +248,7 @@ public class BaseFirmwareService implements FirmwareService { |
267 | 248 | protected void validateUpdate(TenantId tenantId, Firmware firmware) { |
268 | 249 | Firmware firmwareOld = firmwareDao.findById(tenantId, firmware.getUuidId()); |
269 | 250 | |
251 | + validateUpdateDeviceProfile(firmware, firmwareOld); | |
270 | 252 | BaseFirmwareService.validateUpdate(firmware, firmwareOld); |
271 | 253 | |
272 | 254 | if (firmwareOld.getData() != null && !firmwareOld.getData().equals(firmware.getData())) { |
... | ... | @@ -275,7 +257,19 @@ public class BaseFirmwareService implements FirmwareService { |
275 | 257 | } |
276 | 258 | }; |
277 | 259 | |
260 | + private void validateUpdateDeviceProfile(FirmwareInfo firmware, FirmwareInfo firmwareOld) { | |
261 | + if (firmwareOld.getDeviceProfileId() != null && !firmwareOld.getDeviceProfileId().equals(firmware.getDeviceProfileId())) { | |
262 | + if (firmwareInfoDao.isFirmwareUsed(firmwareOld.getId(), firmware.getType(), firmwareOld.getDeviceProfileId())) { | |
263 | + throw new DataValidationException("Can`t update deviceProfileId because firmware is already in use!"); | |
264 | + } | |
265 | + } | |
266 | + } | |
267 | + | |
278 | 268 | private static void validateUpdate(FirmwareInfo firmware, FirmwareInfo firmwareOld) { |
269 | + if (!firmwareOld.getType().equals(firmware.getType())) { | |
270 | + throw new DataValidationException("Updating type is prohibited!"); | |
271 | + } | |
272 | + | |
279 | 273 | if (!firmwareOld.getTitle().equals(firmware.getTitle())) { |
280 | 274 | throw new DataValidationException("Updating firmware title is prohibited!"); |
281 | 275 | } |
... | ... | @@ -305,6 +299,36 @@ public class BaseFirmwareService implements FirmwareService { |
305 | 299 | } |
306 | 300 | } |
307 | 301 | |
302 | + private void validateImpl(FirmwareInfo firmwareInfo) { | |
303 | + if (firmwareInfo.getTenantId() == null) { | |
304 | + throw new DataValidationException("Firmware should be assigned to tenant!"); | |
305 | + } else { | |
306 | + Tenant tenant = tenantDao.findById(firmwareInfo.getTenantId(), firmwareInfo.getTenantId().getId()); | |
307 | + if (tenant == null) { | |
308 | + throw new DataValidationException("Firmware is referencing to non-existent tenant!"); | |
309 | + } | |
310 | + } | |
311 | + | |
312 | + if (firmwareInfo.getDeviceProfileId() != null) { | |
313 | + DeviceProfile deviceProfile = deviceProfileDao.findById(firmwareInfo.getTenantId(), firmwareInfo.getDeviceProfileId().getId()); | |
314 | + if (deviceProfile == null) { | |
315 | + throw new DataValidationException("Firmware is referencing to non-existent device profile!"); | |
316 | + } | |
317 | + } | |
318 | + | |
319 | + if (firmwareInfo.getType() == null) { | |
320 | + throw new DataValidationException("Type should be specified!"); | |
321 | + } | |
322 | + | |
323 | + if (StringUtils.isEmpty(firmwareInfo.getTitle())) { | |
324 | + throw new DataValidationException("Firmware title should be specified!"); | |
325 | + } | |
326 | + | |
327 | + if (StringUtils.isEmpty(firmwareInfo.getVersion())) { | |
328 | + throw new DataValidationException("Firmware version should be specified!"); | |
329 | + } | |
330 | + } | |
331 | + | |
308 | 332 | private PaginatedRemover<TenantId, FirmwareInfo> tenantFirmwareRemover = |
309 | 333 | new PaginatedRemover<>() { |
310 | 334 | ... | ... |
... | ... | @@ -16,6 +16,9 @@ |
16 | 16 | package org.thingsboard.server.dao.firmware; |
17 | 17 | |
18 | 18 | import org.thingsboard.server.common.data.FirmwareInfo; |
19 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
20 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | |
21 | +import org.thingsboard.server.common.data.id.FirmwareId; | |
19 | 22 | import org.thingsboard.server.common.data.id.TenantId; |
20 | 23 | import org.thingsboard.server.common.data.page.PageData; |
21 | 24 | import org.thingsboard.server.common.data.page.PageLink; |
... | ... | @@ -27,6 +30,8 @@ public interface FirmwareInfoDao extends Dao<FirmwareInfo> { |
27 | 30 | |
28 | 31 | PageData<FirmwareInfo> findFirmwareInfoByTenantId(TenantId tenantId, PageLink pageLink); |
29 | 32 | |
30 | - PageData<FirmwareInfo> findFirmwareInfoByTenantIdAndHasData(TenantId tenantId, boolean hasData, PageLink pageLink); | |
33 | + PageData<FirmwareInfo> findFirmwareInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, FirmwareType firmwareType, boolean hasData, PageLink pageLink); | |
34 | + | |
35 | + boolean isFirmwareUsed(FirmwareId firmwareId, FirmwareType type, DeviceProfileId deviceProfileId); | |
31 | 36 | |
32 | 37 | } | ... | ... |
... | ... | @@ -154,6 +154,7 @@ public class ModelConstants { |
154 | 154 | public static final String DEVICE_DEVICE_PROFILE_ID_PROPERTY = "device_profile_id"; |
155 | 155 | public static final String DEVICE_DEVICE_DATA_PROPERTY = "device_data"; |
156 | 156 | public static final String DEVICE_FIRMWARE_ID_PROPERTY = "firmware_id"; |
157 | + public static final String DEVICE_SOFTWARE_ID_PROPERTY = "software_id"; | |
157 | 158 | |
158 | 159 | public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text"; |
159 | 160 | public static final String DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_by_type_and_search_text"; |
... | ... | @@ -178,6 +179,7 @@ public class ModelConstants { |
178 | 179 | public static final String DEVICE_PROFILE_DEFAULT_QUEUE_NAME_PROPERTY = "default_queue_name"; |
179 | 180 | public static final String DEVICE_PROFILE_PROVISION_DEVICE_KEY = "provision_device_key"; |
180 | 181 | public static final String DEVICE_PROFILE_FIRMWARE_ID_PROPERTY = "firmware_id"; |
182 | + public static final String DEVICE_PROFILE_SOFTWARE_ID_PROPERTY = "software_id"; | |
181 | 183 | |
182 | 184 | /** |
183 | 185 | * Cassandra entityView constants. |
... | ... | @@ -476,6 +478,8 @@ public class ModelConstants { |
476 | 478 | */ |
477 | 479 | public static final String FIRMWARE_TABLE_NAME = "firmware"; |
478 | 480 | public static final String FIRMWARE_TENANT_ID_COLUMN = TENANT_ID_COLUMN; |
481 | + public static final String FIRMWARE_DEVICE_PROFILE_ID_COLUMN = "device_profile_id"; | |
482 | + public static final String FIRMWARE_TYPE_COLUMN = "type"; | |
479 | 483 | public static final String FIRMWARE_TITLE_COLUMN = TITLE_PROPERTY; |
480 | 484 | public static final String FIRMWARE_VERSION_COLUMN = "version"; |
481 | 485 | public static final String FIRMWARE_FILE_NAME_COLUMN = "file_name"; | ... | ... |
... | ... | @@ -22,6 +22,7 @@ import lombok.EqualsAndHashCode; |
22 | 22 | import org.hibernate.annotations.Type; |
23 | 23 | import org.hibernate.annotations.TypeDef; |
24 | 24 | import org.hibernate.annotations.TypeDefs; |
25 | +import org.thingsboard.common.util.JacksonUtil; | |
25 | 26 | import org.thingsboard.server.common.data.Device; |
26 | 27 | import org.thingsboard.server.common.data.device.data.DeviceData; |
27 | 28 | import org.thingsboard.server.common.data.id.CustomerId; |
... | ... | @@ -32,7 +33,6 @@ import org.thingsboard.server.common.data.id.TenantId; |
32 | 33 | import org.thingsboard.server.dao.model.BaseSqlEntity; |
33 | 34 | import org.thingsboard.server.dao.model.ModelConstants; |
34 | 35 | import org.thingsboard.server.dao.model.SearchTextEntity; |
35 | -import org.thingsboard.common.util.JacksonUtil; | |
36 | 36 | import org.thingsboard.server.dao.util.mapping.JsonBinaryType; |
37 | 37 | import org.thingsboard.server.dao.util.mapping.JsonStringType; |
38 | 38 | |
... | ... | @@ -43,8 +43,8 @@ import java.util.UUID; |
43 | 43 | @Data |
44 | 44 | @EqualsAndHashCode(callSuper = true) |
45 | 45 | @TypeDefs({ |
46 | - @TypeDef(name = "json", typeClass = JsonStringType.class), | |
47 | - @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) | |
46 | + @TypeDef(name = "json", typeClass = JsonStringType.class), | |
47 | + @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) | |
48 | 48 | }) |
49 | 49 | @MappedSuperclass |
50 | 50 | public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEntity<T> implements SearchTextEntity<T> { |
... | ... | @@ -77,6 +77,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti |
77 | 77 | @Column(name = ModelConstants.DEVICE_FIRMWARE_ID_PROPERTY, columnDefinition = "uuid") |
78 | 78 | private UUID firmwareId; |
79 | 79 | |
80 | + @Column(name = ModelConstants.DEVICE_SOFTWARE_ID_PROPERTY, columnDefinition = "uuid") | |
81 | + private UUID softwareId; | |
82 | + | |
80 | 83 | @Type(type = "jsonb") |
81 | 84 | @Column(name = ModelConstants.DEVICE_DEVICE_DATA_PROPERTY, columnDefinition = "jsonb") |
82 | 85 | private JsonNode deviceData; |
... | ... | @@ -102,6 +105,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti |
102 | 105 | if (device.getFirmwareId() != null) { |
103 | 106 | this.firmwareId = device.getFirmwareId().getId(); |
104 | 107 | } |
108 | + if (device.getSoftwareId() != null) { | |
109 | + this.softwareId = device.getSoftwareId().getId(); | |
110 | + } | |
105 | 111 | this.deviceData = JacksonUtil.convertValue(device.getDeviceData(), ObjectNode.class); |
106 | 112 | this.name = device.getName(); |
107 | 113 | this.type = device.getType(); |
... | ... | @@ -122,6 +128,7 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti |
122 | 128 | this.searchText = deviceEntity.getSearchText(); |
123 | 129 | this.additionalInfo = deviceEntity.getAdditionalInfo(); |
124 | 130 | this.firmwareId = deviceEntity.getFirmwareId(); |
131 | + this.softwareId = deviceEntity.getSoftwareId(); | |
125 | 132 | } |
126 | 133 | |
127 | 134 | @Override |
... | ... | @@ -149,6 +156,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti |
149 | 156 | if (firmwareId != null) { |
150 | 157 | device.setFirmwareId(new FirmwareId(firmwareId)); |
151 | 158 | } |
159 | + if (softwareId != null) { | |
160 | + device.setSoftwareId(new FirmwareId(softwareId)); | |
161 | + } | |
152 | 162 | device.setDeviceData(JacksonUtil.convertValue(deviceData, DeviceData.class)); |
153 | 163 | device.setName(name); |
154 | 164 | device.setType(type); | ... | ... |
... | ... | @@ -21,9 +21,10 @@ import lombok.Data; |
21 | 21 | import lombok.EqualsAndHashCode; |
22 | 22 | import org.hibernate.annotations.Type; |
23 | 23 | import org.hibernate.annotations.TypeDef; |
24 | +import org.thingsboard.common.util.JacksonUtil; | |
24 | 25 | import org.thingsboard.server.common.data.DeviceProfile; |
25 | -import org.thingsboard.server.common.data.DeviceProfileType; | |
26 | 26 | import org.thingsboard.server.common.data.DeviceProfileProvisionType; |
27 | +import org.thingsboard.server.common.data.DeviceProfileType; | |
27 | 28 | import org.thingsboard.server.common.data.DeviceTransportType; |
28 | 29 | import org.thingsboard.server.common.data.device.profile.DeviceProfileData; |
29 | 30 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
... | ... | @@ -33,7 +34,6 @@ import org.thingsboard.server.common.data.id.TenantId; |
33 | 34 | import org.thingsboard.server.dao.model.BaseSqlEntity; |
34 | 35 | import org.thingsboard.server.dao.model.ModelConstants; |
35 | 36 | import org.thingsboard.server.dao.model.SearchTextEntity; |
36 | -import org.thingsboard.common.util.JacksonUtil; | |
37 | 37 | import org.thingsboard.server.dao.util.mapping.JsonBinaryType; |
38 | 38 | |
39 | 39 | import javax.persistence.Column; |
... | ... | @@ -87,12 +87,15 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl |
87 | 87 | @Column(name = ModelConstants.DEVICE_PROFILE_PROFILE_DATA_PROPERTY, columnDefinition = "jsonb") |
88 | 88 | private JsonNode profileData; |
89 | 89 | |
90 | - @Column(name=ModelConstants.DEVICE_PROFILE_PROVISION_DEVICE_KEY) | |
90 | + @Column(name = ModelConstants.DEVICE_PROFILE_PROVISION_DEVICE_KEY) | |
91 | 91 | private String provisionDeviceKey; |
92 | 92 | |
93 | - @Column(name=ModelConstants.DEVICE_PROFILE_FIRMWARE_ID_PROPERTY) | |
93 | + @Column(name = ModelConstants.DEVICE_PROFILE_FIRMWARE_ID_PROPERTY) | |
94 | 94 | private UUID firmwareId; |
95 | 95 | |
96 | + @Column(name = ModelConstants.DEVICE_PROFILE_SOFTWARE_ID_PROPERTY) | |
97 | + private UUID softwareId; | |
98 | + | |
96 | 99 | public DeviceProfileEntity() { |
97 | 100 | super(); |
98 | 101 | } |
... | ... | @@ -120,6 +123,9 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl |
120 | 123 | if (deviceProfile.getFirmwareId() != null) { |
121 | 124 | this.firmwareId = deviceProfile.getFirmwareId().getId(); |
122 | 125 | } |
126 | + if (deviceProfile.getSoftwareId() != null) { | |
127 | + this.firmwareId = deviceProfile.getSoftwareId().getId(); | |
128 | + } | |
123 | 129 | } |
124 | 130 | |
125 | 131 | @Override |
... | ... | @@ -160,6 +166,10 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl |
160 | 166 | deviceProfile.setFirmwareId(new FirmwareId(firmwareId)); |
161 | 167 | } |
162 | 168 | |
169 | + if (softwareId != null) { | |
170 | + deviceProfile.setSoftwareId(new FirmwareId(softwareId)); | |
171 | + } | |
172 | + | |
163 | 173 | return deviceProfile; |
164 | 174 | } |
165 | 175 | } | ... | ... |
... | ... | @@ -21,6 +21,8 @@ import lombok.EqualsAndHashCode; |
21 | 21 | import org.hibernate.annotations.Type; |
22 | 22 | import org.hibernate.annotations.TypeDef; |
23 | 23 | import org.thingsboard.server.common.data.Firmware; |
24 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
25 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | |
24 | 26 | import org.thingsboard.server.common.data.id.FirmwareId; |
25 | 27 | import org.thingsboard.server.common.data.id.TenantId; |
26 | 28 | import org.thingsboard.server.dao.model.BaseSqlEntity; |
... | ... | @@ -30,6 +32,8 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType; |
30 | 32 | |
31 | 33 | import javax.persistence.Column; |
32 | 34 | import javax.persistence.Entity; |
35 | +import javax.persistence.EnumType; | |
36 | +import javax.persistence.Enumerated; | |
33 | 37 | import javax.persistence.Lob; |
34 | 38 | import javax.persistence.Table; |
35 | 39 | import java.nio.ByteBuffer; |
... | ... | @@ -40,10 +44,12 @@ import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CHECKSUM_ |
40 | 44 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CONTENT_TYPE_COLUMN; |
41 | 45 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DATA_COLUMN; |
42 | 46 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DATA_SIZE_COLUMN; |
47 | +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DEVICE_PROFILE_ID_COLUMN; | |
43 | 48 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_FILE_NAME_COLUMN; |
44 | 49 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TABLE_NAME; |
45 | 50 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TENANT_ID_COLUMN; |
46 | 51 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TITLE_COLUMN; |
52 | +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TYPE_COLUMN; | |
47 | 53 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_VERSION_COLUMN; |
48 | 54 | import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY; |
49 | 55 | |
... | ... | @@ -57,6 +63,13 @@ public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTex |
57 | 63 | @Column(name = FIRMWARE_TENANT_ID_COLUMN) |
58 | 64 | private UUID tenantId; |
59 | 65 | |
66 | + @Column(name = FIRMWARE_DEVICE_PROFILE_ID_COLUMN) | |
67 | + private UUID deviceProfileId; | |
68 | + | |
69 | + @Enumerated(EnumType.STRING) | |
70 | + @Column(name = FIRMWARE_TYPE_COLUMN) | |
71 | + private FirmwareType type; | |
72 | + | |
60 | 73 | @Column(name = FIRMWARE_TITLE_COLUMN) |
61 | 74 | private String title; |
62 | 75 | |
... | ... | @@ -97,6 +110,10 @@ public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTex |
97 | 110 | this.createdTime = firmware.getCreatedTime(); |
98 | 111 | this.setUuid(firmware.getUuidId()); |
99 | 112 | this.tenantId = firmware.getTenantId().getId(); |
113 | + if (firmware.getDeviceProfileId() != null) { | |
114 | + this.deviceProfileId = firmware.getDeviceProfileId().getId(); | |
115 | + } | |
116 | + this.type = firmware.getType(); | |
100 | 117 | this.title = firmware.getTitle(); |
101 | 118 | this.version = firmware.getVersion(); |
102 | 119 | this.fileName = firmware.getFileName(); |
... | ... | @@ -123,6 +140,10 @@ public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTex |
123 | 140 | Firmware firmware = new Firmware(new FirmwareId(id)); |
124 | 141 | firmware.setCreatedTime(createdTime); |
125 | 142 | firmware.setTenantId(new TenantId(tenantId)); |
143 | + if (deviceProfileId != null) { | |
144 | + firmware.setDeviceProfileId(new DeviceProfileId(deviceProfileId)); | |
145 | + } | |
146 | + firmware.setType(type); | |
126 | 147 | firmware.setTitle(title); |
127 | 148 | firmware.setVersion(version); |
128 | 149 | firmware.setFileName(fileName); | ... | ... |
... | ... | @@ -22,6 +22,8 @@ import org.hibernate.annotations.Type; |
22 | 22 | import org.hibernate.annotations.TypeDef; |
23 | 23 | import org.thingsboard.common.util.JacksonUtil; |
24 | 24 | import org.thingsboard.server.common.data.FirmwareInfo; |
25 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
26 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | |
25 | 27 | import org.thingsboard.server.common.data.id.FirmwareId; |
26 | 28 | import org.thingsboard.server.common.data.id.TenantId; |
27 | 29 | import org.thingsboard.server.dao.model.BaseSqlEntity; |
... | ... | @@ -31,6 +33,8 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType; |
31 | 33 | |
32 | 34 | import javax.persistence.Column; |
33 | 35 | import javax.persistence.Entity; |
36 | +import javax.persistence.EnumType; | |
37 | +import javax.persistence.Enumerated; | |
34 | 38 | import javax.persistence.Table; |
35 | 39 | import javax.persistence.Transient; |
36 | 40 | import java.util.UUID; |
... | ... | @@ -38,13 +42,13 @@ import java.util.UUID; |
38 | 42 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CHECKSUM_ALGORITHM_COLUMN; |
39 | 43 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CHECKSUM_COLUMN; |
40 | 44 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CONTENT_TYPE_COLUMN; |
41 | -import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DATA_COLUMN; | |
42 | 45 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DATA_SIZE_COLUMN; |
46 | +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DEVICE_PROFILE_ID_COLUMN; | |
43 | 47 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_FILE_NAME_COLUMN; |
44 | -import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_HAS_DATA_PROPERTY; | |
45 | 48 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TABLE_NAME; |
46 | 49 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TENANT_ID_COLUMN; |
47 | 50 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TITLE_COLUMN; |
51 | +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TYPE_COLUMN; | |
48 | 52 | import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_VERSION_COLUMN; |
49 | 53 | import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY; |
50 | 54 | |
... | ... | @@ -58,6 +62,13 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S |
58 | 62 | @Column(name = FIRMWARE_TENANT_ID_COLUMN) |
59 | 63 | private UUID tenantId; |
60 | 64 | |
65 | + @Column(name = FIRMWARE_DEVICE_PROFILE_ID_COLUMN) | |
66 | + private UUID deviceProfileId; | |
67 | + | |
68 | + @Enumerated(EnumType.STRING) | |
69 | + @Column(name = FIRMWARE_TYPE_COLUMN) | |
70 | + private FirmwareType type; | |
71 | + | |
61 | 72 | @Column(name = FIRMWARE_TITLE_COLUMN) |
62 | 73 | private String title; |
63 | 74 | |
... | ... | @@ -97,6 +108,10 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S |
97 | 108 | this.createdTime = firmware.getCreatedTime(); |
98 | 109 | this.setUuid(firmware.getUuidId()); |
99 | 110 | this.tenantId = firmware.getTenantId().getId(); |
111 | + this.type = firmware.getType(); | |
112 | + if (firmware.getDeviceProfileId() != null) { | |
113 | + this.deviceProfileId = firmware.getDeviceProfileId().getId(); | |
114 | + } | |
100 | 115 | this.title = firmware.getTitle(); |
101 | 116 | this.version = firmware.getVersion(); |
102 | 117 | this.fileName = firmware.getFileName(); |
... | ... | @@ -107,12 +122,14 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S |
107 | 122 | this.additionalInfo = firmware.getAdditionalInfo(); |
108 | 123 | } |
109 | 124 | |
110 | - public FirmwareInfoEntity(UUID id, long createdTime, UUID tenantId, String title, String version, | |
125 | + public FirmwareInfoEntity(UUID id, long createdTime, UUID tenantId, UUID deviceProfileId, FirmwareType type, String title, String version, | |
111 | 126 | String fileName, String contentType, String checksumAlgorithm, String checksum, Long dataSize, |
112 | 127 | Object additionalInfo, boolean hasData) { |
113 | 128 | this.id = id; |
114 | 129 | this.createdTime = createdTime; |
115 | 130 | this.tenantId = tenantId; |
131 | + this.deviceProfileId = deviceProfileId; | |
132 | + this.type = type; | |
116 | 133 | this.title = title; |
117 | 134 | this.version = version; |
118 | 135 | this.fileName = fileName; |
... | ... | @@ -139,6 +156,10 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S |
139 | 156 | FirmwareInfo firmware = new FirmwareInfo(new FirmwareId(id)); |
140 | 157 | firmware.setCreatedTime(createdTime); |
141 | 158 | firmware.setTenantId(new TenantId(tenantId)); |
159 | + if (deviceProfileId != null) { | |
160 | + firmware.setDeviceProfileId(new DeviceProfileId(deviceProfileId)); | |
161 | + } | |
162 | + firmware.setType(type); | |
142 | 163 | firmware.setTitle(title); |
143 | 164 | firmware.setVersion(version); |
144 | 165 | firmware.setFileName(fileName); | ... | ... |
... | ... | @@ -104,6 +104,15 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit |
104 | 104 | @Param("textSearch") String textSearch, |
105 | 105 | Pageable pageable); |
106 | 106 | |
107 | + @Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " + | |
108 | + "AND d.type = :type " + | |
109 | + "AND d.softwareId = null " + | |
110 | + "AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") | |
111 | + Page<DeviceEntity> findByTenantIdAndTypeAndSoftwareIdIsNull(@Param("tenantId") UUID tenantId, | |
112 | + @Param("type") String type, | |
113 | + @Param("textSearch") String textSearch, | |
114 | + Pageable pageable); | |
115 | + | |
107 | 116 | @Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " + |
108 | 117 | "FROM DeviceEntity d " + |
109 | 118 | "LEFT JOIN CustomerEntity c on c.id = d.customerId " + | ... | ... |
... | ... | @@ -165,6 +165,16 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device> |
165 | 165 | } |
166 | 166 | |
167 | 167 | @Override |
168 | + public PageData<Device> findDevicesByTenantIdAndTypeAndEmptySoftware(UUID tenantId, String type, PageLink pageLink) { | |
169 | + return DaoUtil.toPageData( | |
170 | + deviceRepository.findByTenantIdAndTypeAndSoftwareIdIsNull( | |
171 | + tenantId, | |
172 | + type, | |
173 | + Objects.toString(pageLink.getTextSearch(), ""), | |
174 | + DaoUtil.toPageable(pageLink))); | |
175 | + } | |
176 | + | |
177 | + @Override | |
168 | 178 | public PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(UUID tenantId, String type, PageLink pageLink) { |
169 | 179 | return DaoUtil.toPageData( |
170 | 180 | deviceRepository.findDeviceInfosByTenantIdAndType( | ... | ... |
... | ... | @@ -20,27 +20,41 @@ import org.springframework.data.domain.Pageable; |
20 | 20 | import org.springframework.data.jpa.repository.Query; |
21 | 21 | import org.springframework.data.repository.CrudRepository; |
22 | 22 | import org.springframework.data.repository.query.Param; |
23 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
23 | 24 | import org.thingsboard.server.dao.model.sql.FirmwareInfoEntity; |
24 | 25 | |
25 | 26 | import java.util.UUID; |
26 | 27 | |
27 | 28 | public interface FirmwareInfoRepository extends CrudRepository<FirmwareInfoEntity, UUID> { |
28 | - @Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " + | |
29 | + @Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.deviceProfileId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " + | |
29 | 30 | "f.tenantId = :tenantId " + |
30 | 31 | "AND LOWER(f.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") |
31 | 32 | Page<FirmwareInfoEntity> findAllByTenantId(@Param("tenantId") UUID tenantId, |
32 | 33 | @Param("searchText") String searchText, |
33 | 34 | Pageable pageable); |
34 | 35 | |
35 | - @Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " + | |
36 | + @Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.deviceProfileId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " + | |
36 | 37 | "f.tenantId = :tenantId " + |
38 | + "AND f.deviceProfileId = :deviceProfileId " + | |
39 | + "AND f.type = :type " + | |
37 | 40 | "AND ((f.data IS NOT NULL AND :hasData = true) OR (f.data IS NULL AND :hasData = false ))" + |
38 | 41 | "AND LOWER(f.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") |
39 | - Page<FirmwareInfoEntity> findAllByTenantIdAndHasData(@Param("tenantId") UUID tenantId, | |
40 | - @Param("hasData") boolean hasData, | |
41 | - @Param("searchText") String searchText, | |
42 | - Pageable pageable); | |
42 | + Page<FirmwareInfoEntity> findAllByTenantIdAndTypeAndDeviceProfileIdAndHasData(@Param("tenantId") UUID tenantId, | |
43 | + @Param("deviceProfileId") UUID deviceProfileId, | |
44 | + @Param("type") FirmwareType type, | |
45 | + @Param("hasData") boolean hasData, | |
46 | + @Param("searchText") String searchText, | |
47 | + Pageable pageable); | |
43 | 48 | |
44 | - @Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE f.id = :id") | |
49 | + @Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.deviceProfileId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE f.id = :id") | |
45 | 50 | FirmwareInfoEntity findFirmwareInfoById(@Param("id") UUID id); |
51 | + | |
52 | + @Query(value = "SELECT exists(SELECT * " + | |
53 | + "FROM device_profile AS dp " + | |
54 | + "LEFT JOIN device AS d ON dp.id = d.device_profile_id " + | |
55 | + "WHERE dp.id = :deviceProfileId AND " + | |
56 | + "(('FIRMWARE' = :type AND (dp.firmware_id = :firmwareId OR d.firmware_id = :firmwareId)) " + | |
57 | + "OR ('SOFTWARE' = :type AND (dp.software_id = :firmwareId or d.software_id = :firmwareId))))", nativeQuery = true) | |
58 | + boolean isFirmwareUsed(@Param("firmwareId") UUID firmwareId, @Param("deviceProfileId") UUID deviceProfileId, @Param("type") String type); | |
59 | + | |
46 | 60 | } | ... | ... |
... | ... | @@ -20,6 +20,9 @@ import org.springframework.beans.factory.annotation.Autowired; |
20 | 20 | import org.springframework.data.repository.CrudRepository; |
21 | 21 | import org.springframework.stereotype.Component; |
22 | 22 | import org.thingsboard.server.common.data.FirmwareInfo; |
23 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
24 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | |
25 | +import org.thingsboard.server.common.data.id.FirmwareId; | |
23 | 26 | import org.thingsboard.server.common.data.id.TenantId; |
24 | 27 | import org.thingsboard.server.common.data.page.PageData; |
25 | 28 | import org.thingsboard.server.common.data.page.PageLink; |
... | ... | @@ -73,12 +76,19 @@ public class JpaFirmwareInfoDao extends JpaAbstractSearchTextDao<FirmwareInfoEnt |
73 | 76 | } |
74 | 77 | |
75 | 78 | @Override |
76 | - public PageData<FirmwareInfo> findFirmwareInfoByTenantIdAndHasData(TenantId tenantId, boolean hasData, PageLink pageLink) { | |
79 | + public PageData<FirmwareInfo> findFirmwareInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, FirmwareType firmwareType, boolean hasData, PageLink pageLink) { | |
77 | 80 | return DaoUtil.toPageData(firmwareInfoRepository |
78 | - .findAllByTenantIdAndHasData( | |
81 | + .findAllByTenantIdAndTypeAndDeviceProfileIdAndHasData( | |
79 | 82 | tenantId.getId(), |
83 | + deviceProfileId.getId(), | |
84 | + firmwareType, | |
80 | 85 | hasData, |
81 | 86 | Objects.toString(pageLink.getTextSearch(), ""), |
82 | 87 | DaoUtil.toPageable(pageLink))); |
83 | 88 | } |
89 | + | |
90 | + @Override | |
91 | + public boolean isFirmwareUsed(FirmwareId firmwareId, FirmwareType type, DeviceProfileId deviceProfileId) { | |
92 | + return firmwareInfoRepository.isFirmwareUsed(firmwareId.getId(), deviceProfileId.getId(), type.name()); | |
93 | + } | |
84 | 94 | } | ... | ... |
... | ... | @@ -162,6 +162,8 @@ CREATE TABLE IF NOT EXISTS firmware ( |
162 | 162 | id uuid NOT NULL CONSTRAINT firmware_pkey PRIMARY KEY, |
163 | 163 | created_time bigint NOT NULL, |
164 | 164 | tenant_id uuid NOT NULL, |
165 | + device_profile_id uuid , | |
166 | + type varchar(32) NOT NULL, | |
165 | 167 | title varchar(255) NOT NULL, |
166 | 168 | version varchar(255) NOT NULL, |
167 | 169 | file_name varchar(255), |
... | ... | @@ -188,13 +190,15 @@ CREATE TABLE IF NOT EXISTS device_profile ( |
188 | 190 | is_default boolean, |
189 | 191 | tenant_id uuid, |
190 | 192 | firmware_id uuid, |
193 | + software_id uuid, | |
191 | 194 | default_rule_chain_id uuid, |
192 | 195 | default_queue_name varchar(255), |
193 | 196 | provision_device_key varchar, |
194 | 197 | CONSTRAINT device_profile_name_unq_key UNIQUE (tenant_id, name), |
195 | 198 | CONSTRAINT device_provision_key_unq_key UNIQUE (provision_device_key), |
196 | 199 | CONSTRAINT fk_default_rule_chain_device_profile FOREIGN KEY (default_rule_chain_id) REFERENCES rule_chain(id), |
197 | - CONSTRAINT fk_firmware_device_profile FOREIGN KEY (firmware_id) REFERENCES firmware(id) | |
200 | + CONSTRAINT fk_firmware_device_profile FOREIGN KEY (firmware_id) REFERENCES firmware(id), | |
201 | + CONSTRAINT fk_software_device_profile FOREIGN KEY (software_id) REFERENCES firmware(id) | |
198 | 202 | ); |
199 | 203 | |
200 | 204 | CREATE TABLE IF NOT EXISTS device ( |
... | ... | @@ -210,9 +214,11 @@ CREATE TABLE IF NOT EXISTS device ( |
210 | 214 | search_text varchar(255), |
211 | 215 | tenant_id uuid, |
212 | 216 | firmware_id uuid, |
217 | + software_id uuid, | |
213 | 218 | CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name), |
214 | 219 | CONSTRAINT fk_device_profile FOREIGN KEY (device_profile_id) REFERENCES device_profile(id), |
215 | - CONSTRAINT fk_firmware_device FOREIGN KEY (firmware_id) REFERENCES firmware(id) | |
220 | + CONSTRAINT fk_firmware_device FOREIGN KEY (firmware_id) REFERENCES firmware(id), | |
221 | + CONSTRAINT fk_software_device FOREIGN KEY (software_id) REFERENCES firmware(id) | |
216 | 222 | ); |
217 | 223 | |
218 | 224 | CREATE TABLE IF NOT EXISTS device_credentials ( | ... | ... |
... | ... | @@ -45,3 +45,4 @@ CREATE INDEX IF NOT EXISTS idx_asset_type ON asset(tenant_id, type); |
45 | 45 | CREATE INDEX IF NOT EXISTS idx_attribute_kv_by_key_and_last_update_ts ON attribute_kv(entity_id, attribute_key, last_update_ts desc); |
46 | 46 | |
47 | 47 | CREATE INDEX IF NOT EXISTS idx_audit_log_tenant_id_and_created_time ON audit_log(tenant_id, created_time); |
48 | + | ... | ... |
... | ... | @@ -180,6 +180,8 @@ CREATE TABLE IF NOT EXISTS firmware ( |
180 | 180 | id uuid NOT NULL CONSTRAINT firmware_pkey PRIMARY KEY, |
181 | 181 | created_time bigint NOT NULL, |
182 | 182 | tenant_id uuid NOT NULL, |
183 | + device_profile_id uuid , | |
184 | + type varchar(32) NOT NULL, | |
183 | 185 | title varchar(255) NOT NULL, |
184 | 186 | version varchar(255) NOT NULL, |
185 | 187 | file_name varchar(255), |
... | ... | @@ -191,6 +193,7 @@ CREATE TABLE IF NOT EXISTS firmware ( |
191 | 193 | additional_info varchar, |
192 | 194 | search_text varchar(255), |
193 | 195 | CONSTRAINT firmware_tenant_title_version_unq_key UNIQUE (tenant_id, title, version) |
196 | +-- CONSTRAINT fk_device_profile_firmware FOREIGN KEY (device_profile_id) REFERENCES device_profile(id) ON DELETE CASCADE | |
194 | 197 | ); |
195 | 198 | |
196 | 199 | CREATE TABLE IF NOT EXISTS device_profile ( |
... | ... | @@ -206,15 +209,26 @@ CREATE TABLE IF NOT EXISTS device_profile ( |
206 | 209 | is_default boolean, |
207 | 210 | tenant_id uuid, |
208 | 211 | firmware_id uuid, |
212 | + software_id uuid, | |
209 | 213 | default_rule_chain_id uuid, |
210 | 214 | default_queue_name varchar(255), |
211 | 215 | provision_device_key varchar, |
212 | 216 | CONSTRAINT device_profile_name_unq_key UNIQUE (tenant_id, name), |
213 | 217 | CONSTRAINT device_provision_key_unq_key UNIQUE (provision_device_key), |
214 | 218 | CONSTRAINT fk_default_rule_chain_device_profile FOREIGN KEY (default_rule_chain_id) REFERENCES rule_chain(id), |
215 | - CONSTRAINT fk_firmware_device_profile FOREIGN KEY (firmware_id) REFERENCES firmware(id) | |
219 | + CONSTRAINT fk_firmware_device_profile FOREIGN KEY (firmware_id) REFERENCES firmware(id), | |
220 | + CONSTRAINT fk_software_device_profile FOREIGN KEY (software_id) REFERENCES firmware(id) | |
216 | 221 | ); |
217 | 222 | |
223 | +-- We will use one-to-many relation in the first release and extend this feature in case of user requests | |
224 | +-- CREATE TABLE IF NOT EXISTS device_profile_firmware ( | |
225 | +-- device_profile_id uuid NOT NULL, | |
226 | +-- firmware_id uuid NOT NULL, | |
227 | +-- CONSTRAINT device_profile_firmware_unq_key UNIQUE (device_profile_id, firmware_id), | |
228 | +-- CONSTRAINT fk_device_profile_firmware_device_profile FOREIGN KEY (device_profile_id) REFERENCES device_profile(id) ON DELETE CASCADE, | |
229 | +-- CONSTRAINT fk_device_profile_firmware_firmware FOREIGN KEY (firmware_id) REFERENCES firmware(id) ON DELETE CASCADE, | |
230 | +-- ); | |
231 | + | |
218 | 232 | CREATE TABLE IF NOT EXISTS device ( |
219 | 233 | id uuid NOT NULL CONSTRAINT device_pkey PRIMARY KEY, |
220 | 234 | created_time bigint NOT NULL, |
... | ... | @@ -228,9 +242,11 @@ CREATE TABLE IF NOT EXISTS device ( |
228 | 242 | search_text varchar(255), |
229 | 243 | tenant_id uuid, |
230 | 244 | firmware_id uuid, |
245 | + software_id uuid, | |
231 | 246 | CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name), |
232 | 247 | CONSTRAINT fk_device_profile FOREIGN KEY (device_profile_id) REFERENCES device_profile(id), |
233 | - CONSTRAINT fk_firmware_device FOREIGN KEY (firmware_id) REFERENCES firmware(id) | |
248 | + CONSTRAINT fk_firmware_device FOREIGN KEY (firmware_id) REFERENCES firmware(id), | |
249 | + CONSTRAINT fk_software_device FOREIGN KEY (software_id) REFERENCES firmware(id) | |
234 | 250 | ); |
235 | 251 | |
236 | 252 | CREATE TABLE IF NOT EXISTS device_credentials ( | ... | ... |
... | ... | @@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.DeviceProfileInfo; |
30 | 30 | import org.thingsboard.server.common.data.DeviceTransportType; |
31 | 31 | import org.thingsboard.server.common.data.Firmware; |
32 | 32 | import org.thingsboard.server.common.data.Tenant; |
33 | +import org.thingsboard.server.common.data.firmware.FirmwareType; | |
33 | 34 | import org.thingsboard.server.common.data.id.TenantId; |
34 | 35 | import org.thingsboard.server.common.data.page.PageData; |
35 | 36 | import org.thingsboard.server.common.data.page.PageLink; |
... | ... | @@ -43,6 +44,8 @@ import java.util.concurrent.ExecutionException; |
43 | 44 | import java.util.concurrent.Executors; |
44 | 45 | import java.util.stream.Collectors; |
45 | 46 | |
47 | +import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE; | |
48 | + | |
46 | 49 | public class BaseDeviceProfileServiceTest extends AbstractServiceTest { |
47 | 50 | |
48 | 51 | private IdComparator<DeviceProfile> idComparator = new IdComparator<>(); |
... | ... | @@ -97,6 +100,8 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest { |
97 | 100 | |
98 | 101 | Firmware firmware = new Firmware(); |
99 | 102 | firmware.setTenantId(tenantId); |
103 | + firmware.setDeviceProfileId(savedDeviceProfile.getId()); | |
104 | + firmware.setType(FIRMWARE); | |
100 | 105 | firmware.setTitle("my firmware"); |
101 | 106 | firmware.setVersion("v1.0"); |
102 | 107 | firmware.setFileName("test.txt"); | ... | ... |
... | ... | @@ -20,10 +20,13 @@ import org.apache.commons.lang3.RandomStringUtils; |
20 | 20 | import org.junit.After; |
21 | 21 | import org.junit.Assert; |
22 | 22 | import org.junit.Before; |
23 | +import org.junit.Rule; | |
23 | 24 | import org.junit.Test; |
25 | +import org.junit.rules.ExpectedException; | |
24 | 26 | import org.thingsboard.server.common.data.Customer; |
25 | 27 | import org.thingsboard.server.common.data.Device; |
26 | 28 | import org.thingsboard.server.common.data.DeviceInfo; |
29 | +import org.thingsboard.server.common.data.DeviceProfile; | |
27 | 30 | import org.thingsboard.server.common.data.EntitySubtype; |
28 | 31 | import org.thingsboard.server.common.data.Firmware; |
29 | 32 | import org.thingsboard.server.common.data.Tenant; |
... | ... | @@ -42,6 +45,7 @@ import java.util.ArrayList; |
42 | 45 | import java.util.Collections; |
43 | 46 | import java.util.List; |
44 | 47 | |
48 | +import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE; | |
45 | 49 | import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; |
46 | 50 | |
47 | 51 | public abstract class BaseDeviceServiceTest extends AbstractServiceTest { |
... | ... | @@ -66,6 +70,9 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { |
66 | 70 | tenantProfileService.deleteTenantProfiles(anotherTenantId); |
67 | 71 | } |
68 | 72 | |
73 | + @Rule | |
74 | + public ExpectedException thrown = ExpectedException.none(); | |
75 | + | |
69 | 76 | @Test |
70 | 77 | public void testSaveDevicesWithoutMaxDeviceLimit() { |
71 | 78 | Device device = this.saveDevice(tenantId, "My device"); |
... | ... | @@ -183,6 +190,8 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { |
183 | 190 | |
184 | 191 | Firmware firmware = new Firmware(); |
185 | 192 | firmware.setTenantId(tenantId); |
193 | + firmware.setDeviceProfileId(device.getDeviceProfileId()); | |
194 | + firmware.setType(FIRMWARE); | |
186 | 195 | firmware.setTitle("my firmware"); |
187 | 196 | firmware.setVersion("v1.0"); |
188 | 197 | firmware.setFileName("test.txt"); |
... | ... | @@ -198,6 +207,40 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { |
198 | 207 | Device foundDevice = deviceService.findDeviceById(tenantId, savedDevice.getId()); |
199 | 208 | Assert.assertEquals(foundDevice.getName(), savedDevice.getName()); |
200 | 209 | } |
210 | + | |
211 | + @Test | |
212 | + public void testAssignFirmwareToDeviceWithDifferentDeviceProfile() { | |
213 | + Device device = new Device(); | |
214 | + device.setTenantId(tenantId); | |
215 | + device.setName("My device"); | |
216 | + device.setType("default"); | |
217 | + Device savedDevice = deviceService.saveDevice(device); | |
218 | + | |
219 | + Assert.assertNotNull(savedDevice); | |
220 | + | |
221 | + DeviceProfile deviceProfile = createDeviceProfile(tenantId, "New device Profile"); | |
222 | + DeviceProfile savedProfile = deviceProfileService.saveDeviceProfile(deviceProfile); | |
223 | + Assert.assertNotNull(savedProfile); | |
224 | + | |
225 | + Firmware firmware = new Firmware(); | |
226 | + firmware.setTenantId(tenantId); | |
227 | + firmware.setDeviceProfileId(savedProfile.getId()); | |
228 | + firmware.setType(FIRMWARE); | |
229 | + firmware.setTitle("my firmware"); | |
230 | + firmware.setVersion("v1.0"); | |
231 | + firmware.setFileName("test.txt"); | |
232 | + firmware.setContentType("text/plain"); | |
233 | + firmware.setChecksumAlgorithm("sha256"); | |
234 | + firmware.setChecksum("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a"); | |
235 | + firmware.setData(ByteBuffer.wrap(new byte[]{1})); | |
236 | + Firmware savedFirmware = firmwareService.saveFirmware(firmware); | |
237 | + | |
238 | + savedDevice.setFirmwareId(savedFirmware.getId()); | |
239 | + | |
240 | + thrown.expect(DataValidationException.class); | |
241 | + thrown.expectMessage("Can't assign firmware with different deviceProfile!"); | |
242 | + deviceService.saveDevice(savedDevice); | |
243 | + } | |
201 | 244 | |
202 | 245 | @Test(expected = DataValidationException.class) |
203 | 246 | public void testSaveDeviceWithEmptyName() { | ... | ... |
... | ... | @@ -19,13 +19,16 @@ import com.datastax.oss.driver.api.core.uuid.Uuids; |
19 | 19 | import org.junit.After; |
20 | 20 | import org.junit.Assert; |
21 | 21 | import org.junit.Before; |
22 | +import org.junit.Rule; | |
22 | 23 | import org.junit.Test; |
24 | +import org.junit.rules.ExpectedException; | |
23 | 25 | import org.thingsboard.common.util.JacksonUtil; |
24 | 26 | import org.thingsboard.server.common.data.Device; |
25 | 27 | import org.thingsboard.server.common.data.DeviceProfile; |
26 | 28 | import org.thingsboard.server.common.data.Firmware; |
27 | 29 | import org.thingsboard.server.common.data.FirmwareInfo; |
28 | 30 | import org.thingsboard.server.common.data.Tenant; |
31 | +import org.thingsboard.server.common.data.id.DeviceProfileId; | |
29 | 32 | import org.thingsboard.server.common.data.id.TenantId; |
30 | 33 | import org.thingsboard.server.common.data.page.PageData; |
31 | 34 | import org.thingsboard.server.common.data.page.PageLink; |
... | ... | @@ -36,6 +39,8 @@ import java.util.ArrayList; |
36 | 39 | import java.util.Collections; |
37 | 40 | import java.util.List; |
38 | 41 | |
42 | +import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE; | |
43 | + | |
39 | 44 | public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
40 | 45 | |
41 | 46 | public static final String TITLE = "My firmware"; |
... | ... | @@ -50,6 +55,8 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
50 | 55 | |
51 | 56 | private TenantId tenantId; |
52 | 57 | |
58 | + private DeviceProfileId deviceProfileId; | |
59 | + | |
53 | 60 | @Before |
54 | 61 | public void before() { |
55 | 62 | Tenant tenant = new Tenant(); |
... | ... | @@ -57,8 +64,16 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
57 | 64 | Tenant savedTenant = tenantService.saveTenant(tenant); |
58 | 65 | Assert.assertNotNull(savedTenant); |
59 | 66 | tenantId = savedTenant.getId(); |
67 | + | |
68 | + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile"); | |
69 | + DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile); | |
70 | + Assert.assertNotNull(savedDeviceProfile); | |
71 | + deviceProfileId = savedDeviceProfile.getId(); | |
60 | 72 | } |
61 | 73 | |
74 | + @Rule | |
75 | + public ExpectedException thrown = ExpectedException.none(); | |
76 | + | |
62 | 77 | @After |
63 | 78 | public void after() { |
64 | 79 | tenantService.deleteTenant(tenantId); |
... | ... | @@ -68,6 +83,8 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
68 | 83 | public void testSaveFirmware() { |
69 | 84 | Firmware firmware = new Firmware(); |
70 | 85 | firmware.setTenantId(tenantId); |
86 | + firmware.setDeviceProfileId(deviceProfileId); | |
87 | + firmware.setType(FIRMWARE); | |
71 | 88 | firmware.setTitle(TITLE); |
72 | 89 | firmware.setVersion(VERSION); |
73 | 90 | firmware.setFileName(FILE_NAME); |
... | ... | @@ -99,6 +116,8 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
99 | 116 | public void testSaveFirmwareInfoAndUpdateWithData() { |
100 | 117 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
101 | 118 | firmwareInfo.setTenantId(tenantId); |
119 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | |
120 | + firmwareInfo.setType(FIRMWARE); | |
102 | 121 | firmwareInfo.setTitle(TITLE); |
103 | 122 | firmwareInfo.setVersion(VERSION); |
104 | 123 | FirmwareInfo savedFirmwareInfo = firmwareService.saveFirmwareInfo(firmwareInfo); |
... | ... | @@ -112,6 +131,8 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
112 | 131 | Firmware firmware = new Firmware(savedFirmwareInfo.getId()); |
113 | 132 | firmware.setCreatedTime(firmwareInfo.getCreatedTime()); |
114 | 133 | firmware.setTenantId(tenantId); |
134 | + firmware.setDeviceProfileId(deviceProfileId); | |
135 | + firmware.setType(FIRMWARE); | |
115 | 136 | firmware.setTitle(TITLE); |
116 | 137 | firmware.setVersion(VERSION); |
117 | 138 | firmware.setFileName(FILE_NAME); |
... | ... | @@ -135,9 +156,11 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
135 | 156 | firmwareService.deleteFirmware(tenantId, savedFirmwareInfo.getId()); |
136 | 157 | } |
137 | 158 | |
138 | - @Test(expected = DataValidationException.class) | |
159 | + @Test | |
139 | 160 | public void testSaveFirmwareWithEmptyTenant() { |
140 | 161 | Firmware firmware = new Firmware(); |
162 | + firmware.setDeviceProfileId(deviceProfileId); | |
163 | + firmware.setType(FIRMWARE); | |
141 | 164 | firmware.setTitle(TITLE); |
142 | 165 | firmware.setVersion(VERSION); |
143 | 166 | firmware.setFileName(FILE_NAME); |
... | ... | @@ -145,65 +168,108 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
145 | 168 | firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
146 | 169 | firmware.setChecksum(CHECKSUM); |
147 | 170 | firmware.setData(DATA); |
171 | + | |
172 | + thrown.expect(DataValidationException.class); | |
173 | + thrown.expectMessage("Firmware should be assigned to tenant!"); | |
148 | 174 | firmwareService.saveFirmware(firmware); |
149 | 175 | } |
150 | 176 | |
151 | - @Test(expected = DataValidationException.class) | |
177 | + @Test | |
178 | + public void testSaveFirmwareWithEmptyType() { | |
179 | + Firmware firmware = new Firmware(); | |
180 | + firmware.setTenantId(tenantId); | |
181 | + firmware.setDeviceProfileId(deviceProfileId); | |
182 | + firmware.setTitle(TITLE); | |
183 | + firmware.setVersion(VERSION); | |
184 | + firmware.setFileName(FILE_NAME); | |
185 | + firmware.setContentType(CONTENT_TYPE); | |
186 | + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); | |
187 | + firmware.setChecksum(CHECKSUM); | |
188 | + firmware.setData(DATA); | |
189 | + | |
190 | + thrown.expect(DataValidationException.class); | |
191 | + thrown.expectMessage("Type should be specified!"); | |
192 | + firmwareService.saveFirmware(firmware); | |
193 | + } | |
194 | + | |
195 | + @Test | |
152 | 196 | public void testSaveFirmwareWithEmptyTitle() { |
153 | 197 | Firmware firmware = new Firmware(); |
154 | 198 | firmware.setTenantId(tenantId); |
199 | + firmware.setDeviceProfileId(deviceProfileId); | |
200 | + firmware.setType(FIRMWARE); | |
155 | 201 | firmware.setVersion(VERSION); |
156 | 202 | firmware.setFileName(FILE_NAME); |
157 | 203 | firmware.setContentType(CONTENT_TYPE); |
158 | 204 | firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
159 | 205 | firmware.setChecksum(CHECKSUM); |
160 | 206 | firmware.setData(DATA); |
207 | + | |
208 | + thrown.expect(DataValidationException.class); | |
209 | + thrown.expectMessage("Firmware title should be specified!"); | |
161 | 210 | firmwareService.saveFirmware(firmware); |
162 | 211 | } |
163 | 212 | |
164 | - @Test(expected = DataValidationException.class) | |
213 | + @Test | |
165 | 214 | public void testSaveFirmwareWithEmptyFileName() { |
166 | 215 | Firmware firmware = new Firmware(); |
167 | 216 | firmware.setTenantId(tenantId); |
217 | + firmware.setDeviceProfileId(deviceProfileId); | |
218 | + firmware.setType(FIRMWARE); | |
168 | 219 | firmware.setTitle(TITLE); |
169 | 220 | firmware.setVersion(VERSION); |
170 | 221 | firmware.setContentType(CONTENT_TYPE); |
171 | 222 | firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
172 | 223 | firmware.setChecksum(CHECKSUM); |
173 | 224 | firmware.setData(DATA); |
225 | + | |
226 | + thrown.expect(DataValidationException.class); | |
227 | + thrown.expectMessage("Firmware file name should be specified!"); | |
174 | 228 | firmwareService.saveFirmware(firmware); |
175 | 229 | } |
176 | 230 | |
177 | - @Test(expected = DataValidationException.class) | |
231 | + @Test | |
178 | 232 | public void testSaveFirmwareWithEmptyContentType() { |
179 | 233 | Firmware firmware = new Firmware(); |
180 | 234 | firmware.setTenantId(tenantId); |
235 | + firmware.setDeviceProfileId(deviceProfileId); | |
236 | + firmware.setType(FIRMWARE); | |
181 | 237 | firmware.setTitle(TITLE); |
182 | 238 | firmware.setVersion(VERSION); |
183 | 239 | firmware.setFileName(FILE_NAME); |
184 | 240 | firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
185 | 241 | firmware.setChecksum(CHECKSUM); |
186 | 242 | firmware.setData(DATA); |
243 | + | |
244 | + thrown.expect(DataValidationException.class); | |
245 | + thrown.expectMessage("Firmware content type should be specified!"); | |
187 | 246 | firmwareService.saveFirmware(firmware); |
188 | 247 | } |
189 | 248 | |
190 | - @Test(expected = DataValidationException.class) | |
249 | + @Test | |
191 | 250 | public void testSaveFirmwareWithEmptyData() { |
192 | 251 | Firmware firmware = new Firmware(); |
193 | 252 | firmware.setTenantId(tenantId); |
253 | + firmware.setDeviceProfileId(deviceProfileId); | |
254 | + firmware.setType(FIRMWARE); | |
194 | 255 | firmware.setTitle(TITLE); |
195 | 256 | firmware.setVersion(VERSION); |
196 | 257 | firmware.setFileName(FILE_NAME); |
197 | 258 | firmware.setContentType(CONTENT_TYPE); |
198 | 259 | firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
199 | 260 | firmware.setChecksum(CHECKSUM); |
261 | + | |
262 | + thrown.expect(DataValidationException.class); | |
263 | + thrown.expectMessage("Firmware data should be specified!"); | |
200 | 264 | firmwareService.saveFirmware(firmware); |
201 | 265 | } |
202 | 266 | |
203 | - @Test(expected = DataValidationException.class) | |
267 | + @Test | |
204 | 268 | public void testSaveFirmwareWithInvalidTenant() { |
205 | 269 | Firmware firmware = new Firmware(); |
206 | 270 | firmware.setTenantId(new TenantId(Uuids.timeBased())); |
271 | + firmware.setDeviceProfileId(deviceProfileId); | |
272 | + firmware.setType(FIRMWARE); | |
207 | 273 | firmware.setTitle(TITLE); |
208 | 274 | firmware.setVersion(VERSION); |
209 | 275 | firmware.setFileName(FILE_NAME); |
... | ... | @@ -211,41 +277,77 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
211 | 277 | firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
212 | 278 | firmware.setChecksum(CHECKSUM); |
213 | 279 | firmware.setData(DATA); |
280 | + | |
281 | + thrown.expect(DataValidationException.class); | |
282 | + thrown.expectMessage("Firmware is referencing to non-existent tenant!"); | |
214 | 283 | firmwareService.saveFirmware(firmware); |
215 | 284 | } |
216 | 285 | |
217 | - @Test(expected = DataValidationException.class) | |
286 | + @Test | |
287 | + public void testSaveFirmwareWithInvalidDeviceProfileId() { | |
288 | + Firmware firmware = new Firmware(); | |
289 | + firmware.setTenantId(tenantId); | |
290 | + firmware.setDeviceProfileId(new DeviceProfileId(Uuids.timeBased())); | |
291 | + firmware.setType(FIRMWARE); | |
292 | + firmware.setTitle(TITLE); | |
293 | + firmware.setVersion(VERSION); | |
294 | + firmware.setFileName(FILE_NAME); | |
295 | + firmware.setContentType(CONTENT_TYPE); | |
296 | + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); | |
297 | + firmware.setChecksum(CHECKSUM); | |
298 | + firmware.setData(DATA); | |
299 | + | |
300 | + thrown.expect(DataValidationException.class); | |
301 | + thrown.expectMessage("Firmware is referencing to non-existent device profile!"); | |
302 | + firmwareService.saveFirmware(firmware); | |
303 | + } | |
304 | + | |
305 | + @Test | |
218 | 306 | public void testSaveFirmwareWithEmptyChecksum() { |
219 | 307 | Firmware firmware = new Firmware(); |
220 | - firmware.setTenantId(new TenantId(Uuids.timeBased())); | |
308 | + firmware.setTenantId(tenantId); | |
309 | + firmware.setDeviceProfileId(deviceProfileId); | |
310 | + firmware.setType(FIRMWARE); | |
221 | 311 | firmware.setTitle(TITLE); |
222 | 312 | firmware.setVersion(VERSION); |
223 | 313 | firmware.setFileName(FILE_NAME); |
224 | 314 | firmware.setContentType(CONTENT_TYPE); |
225 | 315 | firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
226 | 316 | firmware.setData(DATA); |
317 | + | |
318 | + thrown.expect(DataValidationException.class); | |
319 | + thrown.expectMessage("Firmware checksum should be specified!"); | |
227 | 320 | firmwareService.saveFirmware(firmware); |
228 | 321 | } |
229 | 322 | |
230 | - @Test(expected = DataValidationException.class) | |
323 | + @Test | |
231 | 324 | public void testSaveFirmwareInfoWithExistingTitleAndVersion() { |
232 | 325 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
233 | 326 | firmwareInfo.setTenantId(tenantId); |
327 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | |
328 | + firmwareInfo.setType(FIRMWARE); | |
234 | 329 | firmwareInfo.setTitle(TITLE); |
235 | 330 | firmwareInfo.setVersion(VERSION); |
236 | 331 | firmwareService.saveFirmwareInfo(firmwareInfo); |
237 | 332 | |
238 | 333 | FirmwareInfo newFirmwareInfo = new FirmwareInfo(); |
239 | 334 | newFirmwareInfo.setTenantId(tenantId); |
335 | + newFirmwareInfo.setDeviceProfileId(deviceProfileId); | |
336 | + newFirmwareInfo.setType(FIRMWARE); | |
240 | 337 | newFirmwareInfo.setTitle(TITLE); |
241 | 338 | newFirmwareInfo.setVersion(VERSION); |
339 | + | |
340 | + thrown.expect(DataValidationException.class); | |
341 | + thrown.expectMessage("Firmware with such title and version already exists!"); | |
242 | 342 | firmwareService.saveFirmwareInfo(newFirmwareInfo); |
243 | 343 | } |
244 | 344 | |
245 | - @Test(expected = DataValidationException.class) | |
345 | + @Test | |
246 | 346 | public void testSaveFirmwareWithExistingTitleAndVersion() { |
247 | 347 | Firmware firmware = new Firmware(); |
248 | 348 | firmware.setTenantId(tenantId); |
349 | + firmware.setDeviceProfileId(deviceProfileId); | |
350 | + firmware.setType(FIRMWARE); | |
249 | 351 | firmware.setTitle(TITLE); |
250 | 352 | firmware.setVersion(VERSION); |
251 | 353 | firmware.setFileName(FILE_NAME); |
... | ... | @@ -257,18 +359,27 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
257 | 359 | |
258 | 360 | Firmware newFirmware = new Firmware(); |
259 | 361 | newFirmware.setTenantId(tenantId); |
362 | + newFirmware.setDeviceProfileId(deviceProfileId); | |
363 | + newFirmware.setType(FIRMWARE); | |
260 | 364 | newFirmware.setTitle(TITLE); |
261 | 365 | newFirmware.setVersion(VERSION); |
262 | 366 | newFirmware.setFileName(FILE_NAME); |
263 | 367 | newFirmware.setContentType(CONTENT_TYPE); |
368 | + newFirmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); | |
369 | + newFirmware.setChecksum(CHECKSUM); | |
264 | 370 | newFirmware.setData(DATA); |
371 | + | |
372 | + thrown.expect(DataValidationException.class); | |
373 | + thrown.expectMessage("Firmware with such title and version already exists!"); | |
265 | 374 | firmwareService.saveFirmware(newFirmware); |
266 | 375 | } |
267 | 376 | |
268 | - @Test(expected = DataValidationException.class) | |
377 | + @Test | |
269 | 378 | public void testDeleteFirmwareWithReferenceByDevice() { |
270 | 379 | Firmware firmware = new Firmware(); |
271 | 380 | firmware.setTenantId(tenantId); |
381 | + firmware.setDeviceProfileId(deviceProfileId); | |
382 | + firmware.setType(FIRMWARE); | |
272 | 383 | firmware.setTitle(TITLE); |
273 | 384 | firmware.setVersion(VERSION); |
274 | 385 | firmware.setFileName(FILE_NAME); |
... | ... | @@ -281,11 +392,13 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
281 | 392 | Device device = new Device(); |
282 | 393 | device.setTenantId(tenantId); |
283 | 394 | device.setName("My device"); |
284 | - device.setType("default"); | |
395 | + device.setDeviceProfileId(deviceProfileId); | |
285 | 396 | device.setFirmwareId(savedFirmware.getId()); |
286 | 397 | Device savedDevice = deviceService.saveDevice(device); |
287 | 398 | |
288 | 399 | try { |
400 | + thrown.expect(DataValidationException.class); | |
401 | + thrown.expectMessage("The firmware referenced by the devices cannot be deleted!"); | |
289 | 402 | firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); |
290 | 403 | } finally { |
291 | 404 | deviceService.deleteDevice(tenantId, savedDevice.getId()); |
... | ... | @@ -293,10 +406,12 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
293 | 406 | } |
294 | 407 | } |
295 | 408 | |
296 | - @Test(expected = DataValidationException.class) | |
297 | - public void testDeleteFirmwareWithReferenceByDeviceProfile() { | |
409 | + @Test | |
410 | + public void testUpdateDeviceProfileIdWithReferenceByDevice() { | |
298 | 411 | Firmware firmware = new Firmware(); |
299 | 412 | firmware.setTenantId(tenantId); |
413 | + firmware.setDeviceProfileId(deviceProfileId); | |
414 | + firmware.setType(FIRMWARE); | |
300 | 415 | firmware.setTitle(TITLE); |
301 | 416 | firmware.setVersion(VERSION); |
302 | 417 | firmware.setFileName(FILE_NAME); |
... | ... | @@ -306,12 +421,81 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
306 | 421 | firmware.setData(DATA); |
307 | 422 | Firmware savedFirmware = firmwareService.saveFirmware(firmware); |
308 | 423 | |
309 | - DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile"); | |
310 | - deviceProfile.setFirmwareId(savedFirmware.getId()); | |
424 | + Device device = new Device(); | |
425 | + device.setTenantId(tenantId); | |
426 | + device.setName("My device"); | |
427 | + device.setDeviceProfileId(deviceProfileId); | |
428 | + device.setFirmwareId(savedFirmware.getId()); | |
429 | + Device savedDevice = deviceService.saveDevice(device); | |
430 | + | |
431 | + try { | |
432 | + thrown.expect(DataValidationException.class); | |
433 | + thrown.expectMessage("Can`t update deviceProfileId because firmware is already in use!"); | |
434 | + savedFirmware.setDeviceProfileId(null); | |
435 | + firmwareService.saveFirmware(savedFirmware); | |
436 | + } finally { | |
437 | + deviceService.deleteDevice(tenantId, savedDevice.getId()); | |
438 | + firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); | |
439 | + } | |
440 | + } | |
441 | + | |
442 | + @Test | |
443 | + public void testDeleteFirmwareWithReferenceByDeviceProfile() { | |
444 | + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Test Device Profile"); | |
311 | 445 | DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile); |
312 | 446 | |
447 | + Firmware firmware = new Firmware(); | |
448 | + firmware.setTenantId(tenantId); | |
449 | + firmware.setDeviceProfileId(savedDeviceProfile.getId()); | |
450 | + firmware.setType(FIRMWARE); | |
451 | + firmware.setTitle(TITLE); | |
452 | + firmware.setVersion(VERSION); | |
453 | + firmware.setFileName(FILE_NAME); | |
454 | + firmware.setContentType(CONTENT_TYPE); | |
455 | + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); | |
456 | + firmware.setChecksum(CHECKSUM); | |
457 | + firmware.setData(DATA); | |
458 | + Firmware savedFirmware = firmwareService.saveFirmware(firmware); | |
459 | + | |
460 | + savedDeviceProfile.setFirmwareId(savedFirmware.getId()); | |
461 | + deviceProfileService.saveDeviceProfile(savedDeviceProfile); | |
462 | + | |
313 | 463 | try { |
464 | + thrown.expect(DataValidationException.class); | |
465 | + thrown.expectMessage("The firmware referenced by the device profile cannot be deleted!"); | |
466 | + firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); | |
467 | + } finally { | |
468 | + deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId()); | |
314 | 469 | firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); |
470 | + } | |
471 | + } | |
472 | + | |
473 | + @Test | |
474 | + public void testUpdateDeviceProfileIdWithReferenceByDeviceProfile() { | |
475 | + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Test Device Profile"); | |
476 | + DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile); | |
477 | + | |
478 | + Firmware firmware = new Firmware(); | |
479 | + firmware.setTenantId(tenantId); | |
480 | + firmware.setDeviceProfileId(savedDeviceProfile.getId()); | |
481 | + firmware.setType(FIRMWARE); | |
482 | + firmware.setTitle(TITLE); | |
483 | + firmware.setVersion(VERSION); | |
484 | + firmware.setFileName(FILE_NAME); | |
485 | + firmware.setContentType(CONTENT_TYPE); | |
486 | + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); | |
487 | + firmware.setChecksum(CHECKSUM); | |
488 | + firmware.setData(DATA); | |
489 | + Firmware savedFirmware = firmwareService.saveFirmware(firmware); | |
490 | + | |
491 | + savedDeviceProfile.setFirmwareId(savedFirmware.getId()); | |
492 | + deviceProfileService.saveDeviceProfile(savedDeviceProfile); | |
493 | + | |
494 | + try { | |
495 | + thrown.expect(DataValidationException.class); | |
496 | + thrown.expectMessage("Can`t update deviceProfileId because firmware is already in use!"); | |
497 | + savedFirmware.setDeviceProfileId(null); | |
498 | + firmwareService.saveFirmware(savedFirmware); | |
315 | 499 | } finally { |
316 | 500 | deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId()); |
317 | 501 | firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); |
... | ... | @@ -322,6 +506,8 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
322 | 506 | public void testFindFirmwareById() { |
323 | 507 | Firmware firmware = new Firmware(); |
324 | 508 | firmware.setTenantId(tenantId); |
509 | + firmware.setDeviceProfileId(deviceProfileId); | |
510 | + firmware.setType(FIRMWARE); | |
325 | 511 | firmware.setTitle(TITLE); |
326 | 512 | firmware.setVersion(VERSION); |
327 | 513 | firmware.setFileName(FILE_NAME); |
... | ... | @@ -341,6 +527,8 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
341 | 527 | public void testFindFirmwareInfoById() { |
342 | 528 | FirmwareInfo firmware = new FirmwareInfo(); |
343 | 529 | firmware.setTenantId(tenantId); |
530 | + firmware.setDeviceProfileId(deviceProfileId); | |
531 | + firmware.setType(FIRMWARE); | |
344 | 532 | firmware.setTitle(TITLE); |
345 | 533 | firmware.setVersion(VERSION); |
346 | 534 | FirmwareInfo savedFirmware = firmwareService.saveFirmwareInfo(firmware); |
... | ... | @@ -355,6 +543,8 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
355 | 543 | public void testDeleteFirmware() { |
356 | 544 | Firmware firmware = new Firmware(); |
357 | 545 | firmware.setTenantId(tenantId); |
546 | + firmware.setDeviceProfileId(deviceProfileId); | |
547 | + firmware.setType(FIRMWARE); | |
358 | 548 | firmware.setTitle(TITLE); |
359 | 549 | firmware.setVersion(VERSION); |
360 | 550 | firmware.setFileName(FILE_NAME); |
... | ... | @@ -377,6 +567,8 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
377 | 567 | for (int i = 0; i < 165; i++) { |
378 | 568 | Firmware firmware = new Firmware(); |
379 | 569 | firmware.setTenantId(tenantId); |
570 | + firmware.setDeviceProfileId(deviceProfileId); | |
571 | + firmware.setType(FIRMWARE); | |
380 | 572 | firmware.setTitle(TITLE); |
381 | 573 | firmware.setVersion(VERSION + i); |
382 | 574 | firmware.setFileName(FILE_NAME); |
... | ... | @@ -420,6 +612,8 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
420 | 612 | for (int i = 0; i < 165; i++) { |
421 | 613 | FirmwareInfo firmwareInfo = new FirmwareInfo(); |
422 | 614 | firmwareInfo.setTenantId(tenantId); |
615 | + firmwareInfo.setDeviceProfileId(deviceProfileId); | |
616 | + firmwareInfo.setType(FIRMWARE); | |
423 | 617 | firmwareInfo.setTitle(TITLE); |
424 | 618 | firmwareInfo.setVersion(VERSION + i); |
425 | 619 | firmwareInfo.setFileName(FILE_NAME); |
... | ... | @@ -434,7 +628,7 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
434 | 628 | PageLink pageLink = new PageLink(16); |
435 | 629 | PageData<FirmwareInfo> pageData; |
436 | 630 | do { |
437 | - pageData = firmwareService.findTenantFirmwaresByTenantIdAndHasData(tenantId, false, pageLink); | |
631 | + pageData = firmwareService.findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(tenantId, deviceProfileId, FIRMWARE, false, pageLink); | |
438 | 632 | loadedFirmwares.addAll(pageData.getData()); |
439 | 633 | if (pageData.hasNext()) { |
440 | 634 | pageLink = pageLink.nextPageLink(); |
... | ... | @@ -450,6 +644,8 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
450 | 644 | Firmware firmware = new Firmware(f.getId()); |
451 | 645 | firmware.setCreatedTime(f.getCreatedTime()); |
452 | 646 | firmware.setTenantId(f.getTenantId()); |
647 | + firmware.setDeviceProfileId(deviceProfileId); | |
648 | + firmware.setType(FIRMWARE); | |
453 | 649 | firmware.setTitle(f.getTitle()); |
454 | 650 | firmware.setVersion(f.getVersion()); |
455 | 651 | firmware.setFileName(FILE_NAME); |
... | ... | @@ -465,7 +661,7 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
465 | 661 | loadedFirmwares = new ArrayList<>(); |
466 | 662 | pageLink = new PageLink(16); |
467 | 663 | do { |
468 | - pageData = firmwareService.findTenantFirmwaresByTenantIdAndHasData(tenantId, true, pageLink); | |
664 | + pageData = firmwareService.findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(tenantId, deviceProfileId, FIRMWARE, true, pageLink); | |
469 | 665 | loadedFirmwares.addAll(pageData.getData()); |
470 | 666 | if (pageData.hasNext()) { |
471 | 667 | pageLink = pageLink.nextPageLink(); | ... | ... |
... | ... | @@ -361,7 +361,7 @@ export class EntityService { |
361 | 361 | break; |
362 | 362 | case EntityType.FIRMWARE: |
363 | 363 | pageLink.sortOrder.property = 'title'; |
364 | - entitiesObservable = this.firmwareService.getFirmwares(pageLink, true, config); | |
364 | + entitiesObservable = this.firmwareService.getFirmwares(pageLink, config); | |
365 | 365 | break; |
366 | 366 | } |
367 | 367 | return entitiesObservable; | ... | ... |
... | ... | @@ -20,7 +20,7 @@ import { PageLink } from '@shared/models/page/page-link'; |
20 | 20 | import { defaultHttpOptionsFromConfig, defaultHttpUploadOptions, RequestConfig } from '@core/http/http-utils'; |
21 | 21 | import { Observable } from 'rxjs'; |
22 | 22 | import { PageData } from '@shared/models/page/page-data'; |
23 | -import { Firmware, FirmwareInfo } from '@shared/models/firmware.models'; | |
23 | +import { Firmware, FirmwareInfo, FirmwareType } from '@shared/models/firmware.models'; | |
24 | 24 | import { catchError, map, mergeMap } from 'rxjs/operators'; |
25 | 25 | import { deepClone, isDefinedAndNotNull } from '@core/utils'; |
26 | 26 | |
... | ... | @@ -34,12 +34,13 @@ export class FirmwareService { |
34 | 34 | |
35 | 35 | } |
36 | 36 | |
37 | - public getFirmwares(pageLink: PageLink, hasData?: boolean, config?: RequestConfig): Observable<PageData<FirmwareInfo>> { | |
38 | - let url = `/api/firmwares`; | |
39 | - if (isDefinedAndNotNull(hasData)) { | |
40 | - url += `/${hasData}`; | |
41 | - } | |
42 | - url += `${pageLink.toQuery()}`; | |
37 | + public getFirmwares(pageLink: PageLink, config?: RequestConfig): Observable<PageData<FirmwareInfo>> { | |
38 | + return this.http.get<PageData<FirmwareInfo>>(`/api/firmwares${pageLink.toQuery()}`, defaultHttpOptionsFromConfig(config)); | |
39 | + } | |
40 | + | |
41 | + public getFirmwaresInfoByDeviceProfileId(pageLink: PageLink, deviceProfileId: string, type: FirmwareType, | |
42 | + hasData = true, config?: RequestConfig): Observable<PageData<FirmwareInfo>> { | |
43 | + const url = `/api/firmwares/${deviceProfileId}/${type}/${hasData}${pageLink.toQuery()}`; | |
43 | 44 | return this.http.get<PageData<FirmwareInfo>>(url, defaultHttpOptionsFromConfig(config)); |
44 | 45 | } |
45 | 46 | ... | ... |
... | ... | @@ -60,10 +60,6 @@ |
60 | 60 | {{ 'device-profile.type-required' | translate }} |
61 | 61 | </mat-error> |
62 | 62 | </mat-form-field> |
63 | - <tb-firmware-autocomplete | |
64 | - [useFullEntityId]="true" | |
65 | - formControlName="firmwareId"> | |
66 | - </tb-firmware-autocomplete> | |
67 | 63 | <mat-form-field class="mat-block"> |
68 | 64 | <mat-label translate>device-profile.description</mat-label> |
69 | 65 | <textarea matInput formControlName="description" rows="2"></textarea> | ... | ... |
... | ... | @@ -108,7 +108,6 @@ export class AddDeviceProfileDialogComponent extends |
108 | 108 | type: [DeviceProfileType.DEFAULT, [Validators.required]], |
109 | 109 | defaultRuleChainId: [null, []], |
110 | 110 | defaultQueueName: ['', []], |
111 | - firmwareId: [null], | |
112 | 111 | description: ['', []] |
113 | 112 | } |
114 | 113 | ); |
... | ... | @@ -187,7 +186,6 @@ export class AddDeviceProfileDialogComponent extends |
187 | 186 | transportType: this.transportConfigFormGroup.get('transportType').value, |
188 | 187 | provisionType: deviceProvisionConfiguration.type, |
189 | 188 | provisionDeviceKey, |
190 | - firmwareId: this.deviceProfileDetailsFormGroup.get('firmwareId').value, | |
191 | 189 | description: this.deviceProfileDetailsFormGroup.get('description').value, |
192 | 190 | profileData: { |
193 | 191 | configuration: createDeviceProfileConfiguration(DeviceProfileType.DEFAULT), | ... | ... |
... | ... | @@ -65,8 +65,16 @@ |
65 | 65 | </tb-queue-type-list> |
66 | 66 | <tb-firmware-autocomplete |
67 | 67 | [useFullEntityId]="true" |
68 | + [type]="firmwareTypes.FIRMWARE" | |
69 | + [deviceProfileId]="deviceProfileId?.id" | |
68 | 70 | formControlName="firmwareId"> |
69 | 71 | </tb-firmware-autocomplete> |
72 | + <tb-firmware-autocomplete | |
73 | + [useFullEntityId]="true" | |
74 | + [type]="firmwareTypes.SOFTWARE" | |
75 | + [deviceProfileId]="deviceProfileId?.id" | |
76 | + formControlName="softwareId"> | |
77 | + </tb-firmware-autocomplete> | |
70 | 78 | <mat-form-field fxHide class="mat-block"> |
71 | 79 | <mat-label translate>device-profile.type</mat-label> |
72 | 80 | <mat-select formControlName="type" required> | ... | ... |
... | ... | @@ -40,6 +40,7 @@ import { EntityType } from '@shared/models/entity-type.models'; |
40 | 40 | import { RuleChainId } from '@shared/models/id/rule-chain-id'; |
41 | 41 | import { ServiceType } from '@shared/models/queue.models'; |
42 | 42 | import { EntityId } from '@shared/models/id/entity-id'; |
43 | +import { FirmwareType } from '@shared/models/firmware.models'; | |
43 | 44 | |
44 | 45 | @Component({ |
45 | 46 | selector: 'tb-device-profile', |
... | ... | @@ -69,6 +70,8 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { |
69 | 70 | |
70 | 71 | deviceProfileId: EntityId; |
71 | 72 | |
73 | + firmwareTypes = FirmwareType; | |
74 | + | |
72 | 75 | constructor(protected store: Store<AppState>, |
73 | 76 | protected translate: TranslateService, |
74 | 77 | @Optional() @Inject('entity') protected entityValue: DeviceProfile, |
... | ... | @@ -110,6 +113,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { |
110 | 113 | defaultRuleChainId: [entity && entity.defaultRuleChainId ? entity.defaultRuleChainId.id : null, []], |
111 | 114 | defaultQueueName: [entity ? entity.defaultQueueName : '', []], |
112 | 115 | firmwareId: [entity ? entity.firmwareId : null], |
116 | + softwareId: [entity ? entity.softwareId : null], | |
113 | 117 | description: [entity ? entity.description : '', []], |
114 | 118 | } |
115 | 119 | ); |
... | ... | @@ -186,6 +190,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { |
186 | 190 | this.entityForm.patchValue({defaultRuleChainId: entity.defaultRuleChainId ? entity.defaultRuleChainId.id : null}, {emitEvent: false}); |
187 | 191 | this.entityForm.patchValue({defaultQueueName: entity.defaultQueueName}, {emitEvent: false}); |
188 | 192 | this.entityForm.patchValue({firmwareId: entity.firmwareId}, {emitEvent: false}); |
193 | + this.entityForm.patchValue({softwareId: entity.softwareId}, {emitEvent: false}); | |
189 | 194 | this.entityForm.patchValue({description: entity.description}, {emitEvent: false}); |
190 | 195 | } |
191 | 196 | ... | ... |
... | ... | @@ -48,10 +48,6 @@ |
48 | 48 | <mat-label translate>device.label</mat-label> |
49 | 49 | <input matInput formControlName="label"> |
50 | 50 | </mat-form-field> |
51 | - <tb-firmware-autocomplete | |
52 | - [useFullEntityId]="true" | |
53 | - formControlName="firmwareId"> | |
54 | - </tb-firmware-autocomplete> | |
55 | 51 | <mat-form-field class="mat-block" style="padding-bottom: 14px;"> |
56 | 52 | <mat-label translate>device-profile.transport-type</mat-label> |
57 | 53 | <mat-select formControlName="transportType" required> | ... | ... |
... | ... | @@ -107,7 +107,6 @@ export class DeviceWizardDialogComponent extends |
107 | 107 | this.deviceWizardFormGroup = this.fb.group({ |
108 | 108 | name: ['', Validators.required], |
109 | 109 | label: [''], |
110 | - firmwareId: [null], | |
111 | 110 | gateway: [false], |
112 | 111 | overwriteActivityTime: [false], |
113 | 112 | transportType: [DeviceTransportType.DEFAULT, Validators.required], |
... | ... | @@ -313,7 +312,6 @@ export class DeviceWizardDialogComponent extends |
313 | 312 | const device = { |
314 | 313 | name: this.deviceWizardFormGroup.get('name').value, |
315 | 314 | label: this.deviceWizardFormGroup.get('label').value, |
316 | - firmwareId: this.deviceWizardFormGroup.get('firmwareId').value, | |
317 | 315 | deviceProfileId: profileId, |
318 | 316 | additionalInfo: { |
319 | 317 | gateway: this.deviceWizardFormGroup.get('gateway').value, | ... | ... |
... | ... | @@ -103,8 +103,16 @@ |
103 | 103 | </mat-form-field> |
104 | 104 | <tb-firmware-autocomplete |
105 | 105 | [useFullEntityId]="true" |
106 | + [type]="firmwareTypes.FIRMWARE" | |
107 | + [deviceProfileId]="entityForm.get('deviceProfileId').value?.id" | |
106 | 108 | formControlName="firmwareId"> |
107 | 109 | </tb-firmware-autocomplete> |
110 | + <tb-firmware-autocomplete | |
111 | + [useFullEntityId]="true" | |
112 | + [type]="firmwareTypes.SOFTWARE" | |
113 | + [deviceProfileId]="entityForm.get('deviceProfileId').value?.id" | |
114 | + formControlName="softwareId"> | |
115 | + </tb-firmware-autocomplete> | |
108 | 116 | <tb-device-data |
109 | 117 | formControlName="deviceData" |
110 | 118 | required> | ... | ... |
... | ... | @@ -34,6 +34,7 @@ import { ActionNotificationShow } from '@core/notification/notification.actions' |
34 | 34 | import { TranslateService } from '@ngx-translate/core'; |
35 | 35 | import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; |
36 | 36 | import { Subject } from 'rxjs'; |
37 | +import { FirmwareType } from '@shared/models/firmware.models'; | |
37 | 38 | |
38 | 39 | @Component({ |
39 | 40 | selector: 'tb-device', |
... | ... | @@ -48,6 +49,8 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> { |
48 | 49 | |
49 | 50 | deviceScope: 'tenant' | 'customer' | 'customer_user' | 'edge'; |
50 | 51 | |
52 | + firmwareTypes = FirmwareType; | |
53 | + | |
51 | 54 | constructor(protected store: Store<AppState>, |
52 | 55 | protected translate: TranslateService, |
53 | 56 | @Inject('entity') protected entityValue: DeviceInfo, |
... | ... | @@ -80,6 +83,7 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> { |
80 | 83 | name: [entity ? entity.name : '', [Validators.required]], |
81 | 84 | deviceProfileId: [entity ? entity.deviceProfileId : null, [Validators.required]], |
82 | 85 | firmwareId: [entity ? entity.firmwareId : null], |
86 | + softwareId: [entity ? entity.softwareId : null], | |
83 | 87 | label: [entity ? entity.label : ''], |
84 | 88 | deviceData: [entity ? entity.deviceData : null, [Validators.required]], |
85 | 89 | additionalInfo: this.fb.group( |
... | ... | @@ -94,19 +98,19 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> { |
94 | 98 | } |
95 | 99 | |
96 | 100 | updateForm(entity: DeviceInfo) { |
97 | - this.entityForm.patchValue({name: entity.name}); | |
98 | - this.entityForm.patchValue({deviceProfileId: entity.deviceProfileId}); | |
99 | - this.entityForm.patchValue({firmwareId: entity.firmwareId}); | |
100 | - this.entityForm.patchValue({label: entity.label}); | |
101 | - this.entityForm.patchValue({deviceData: entity.deviceData}); | |
102 | 101 | this.entityForm.patchValue({ |
103 | - additionalInfo: | |
104 | - { | |
105 | - gateway: entity.additionalInfo ? entity.additionalInfo.gateway : false, | |
106 | - overwriteActivityTime: entity.additionalInfo ? entity.additionalInfo.overwriteActivityTime : false | |
107 | - } | |
102 | + name: entity.name, | |
103 | + deviceProfileId: entity.deviceProfileId, | |
104 | + firmwareId: entity.firmwareId, | |
105 | + softwareId: entity.softwareId, | |
106 | + label: entity.label, | |
107 | + deviceData: entity.deviceData, | |
108 | + additionalInfo: { | |
109 | + gateway: entity.additionalInfo ? entity.additionalInfo.gateway : false, | |
110 | + overwriteActivityTime: entity.additionalInfo ? entity.additionalInfo.overwriteActivityTime : false, | |
111 | + description: entity.additionalInfo ? entity.additionalInfo.description : '' | |
112 | + } | |
108 | 113 | }); |
109 | - this.entityForm.patchValue({additionalInfo: {description: entity.additionalInfo ? entity.additionalInfo.description : ''}}); | |
110 | 114 | } |
111 | 115 | |
112 | 116 | |
... | ... | @@ -152,6 +156,10 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> { |
152 | 156 | this.entityForm.markAsDirty(); |
153 | 157 | } |
154 | 158 | } |
159 | + this.entityForm.patchValue({ | |
160 | + firmwareId: null, | |
161 | + softwareId: null | |
162 | + }); | |
155 | 163 | } |
156 | 164 | } |
157 | 165 | } | ... | ... |
... | ... | @@ -21,7 +21,12 @@ import { |
21 | 21 | EntityTableColumn, |
22 | 22 | EntityTableConfig |
23 | 23 | } from '@home/models/entity/entities-table-config.models'; |
24 | -import { Firmware, FirmwareInfo } from '@shared/models/firmware.models'; | |
24 | +import { | |
25 | + ChecksumAlgorithmTranslationMap, | |
26 | + Firmware, | |
27 | + FirmwareInfo, | |
28 | + FirmwareTypeTranslationMap | |
29 | +} from '@shared/models/firmware.models'; | |
25 | 30 | import { EntityType, entityTypeResources, entityTypeTranslations } from '@shared/models/entity-type.models'; |
26 | 31 | import { TranslateService } from '@ngx-translate/core'; |
27 | 32 | import { DatePipe } from '@angular/common'; |
... | ... | @@ -49,14 +54,17 @@ export class FirmwareTableConfigResolve implements Resolve<EntityTableConfig<Fir |
49 | 54 | |
50 | 55 | this.config.columns.push( |
51 | 56 | new DateEntityTableColumn<FirmwareInfo>('createdTime', 'common.created-time', this.datePipe, '150px'), |
52 | - new EntityTableColumn<FirmwareInfo>('title', 'firmware.title', '33%'), | |
53 | - new EntityTableColumn<FirmwareInfo>('version', 'firmware.version', '33%'), | |
54 | - new EntityTableColumn<FirmwareInfo>('fileName', 'firmware.file-name', '33%'), | |
57 | + new EntityTableColumn<FirmwareInfo>('title', 'firmware.title', '25%'), | |
58 | + new EntityTableColumn<FirmwareInfo>('version', 'firmware.version', '25%'), | |
59 | + new EntityTableColumn<FirmwareInfo>('type', 'firmware.type', '25%', entity => { | |
60 | + return this.translate.instant(FirmwareTypeTranslationMap.get(entity.type)); | |
61 | + }), | |
62 | + new EntityTableColumn<FirmwareInfo>('fileName', 'firmware.file-name', '25%'), | |
55 | 63 | new EntityTableColumn<FirmwareInfo>('dataSize', 'firmware.file-size', '70px', entity => { |
56 | 64 | return this.fileSize.transform(entity.dataSize || 0); |
57 | 65 | }), |
58 | 66 | new EntityTableColumn<FirmwareInfo>('checksum', 'firmware.checksum', '540px', entity => { |
59 | - return `${entity.checksumAlgorithm}: ${entity.checksum}`; | |
67 | + return `${ChecksumAlgorithmTranslationMap.get(entity.checksumAlgorithm)}: ${entity.checksum}`; | |
60 | 68 | }, () => ({}), false) |
61 | 69 | ); |
62 | 70 | ... | ... |
... | ... | @@ -67,10 +67,27 @@ |
67 | 67 | </mat-error> |
68 | 68 | </mat-form-field> |
69 | 69 | </div> |
70 | + <div fxLayout="row" fxLayoutGap.gt-xs="8px" fxLayout.xs="column"> | |
71 | + <mat-form-field fxFlex="45"> | |
72 | + <mat-label translate>firmware.type</mat-label> | |
73 | + <input *ngIf="!isAdd" matInput type="text" [readonly]="isEdit" [disabled]="!isEdit" | |
74 | + value="{{ firmwareTypeTranslationMap.get(entityForm.get('type').value) | translate }}"> | |
75 | + <mat-select formControlName="type" required *ngIf="isAdd"> | |
76 | + <mat-option *ngFor="let firmwareType of firmwareTypes" [value]="firmwareType"> | |
77 | + {{ firmwareTypeTranslationMap.get(firmwareType) | translate }} | |
78 | + </mat-option> | |
79 | + </mat-select> | |
80 | + </mat-form-field> | |
81 | + <tb-device-profile-autocomplete | |
82 | + formControlName="deviceProfileId" fxFlex | |
83 | + [editProfileEnabled]="false"> | |
84 | + </tb-device-profile-autocomplete> | |
85 | + </div> | |
70 | 86 | <div fxLayout="row" fxLayoutGap.gt-xs="8px" fxLayoutGap.sm="8px" fxLayout.xs="column" fxLayout.md="column"> |
71 | 87 | <mat-form-field class="mat-block" fxFlex="33"> |
72 | 88 | <mat-label translate>firmware.checksum-algorithm</mat-label> |
73 | - <input *ngIf="!isAdd" matInput formControlName="checksumAlgorithm" type="text" [readonly]="isEdit"> | |
89 | + <input *ngIf="!isAdd" matInput type="text" [readonly]="isEdit" [disabled]="!isEdit" | |
90 | + value="{{ checksumAlgorithmTranslationMap.get(entityForm.get('checksumAlgorithm').value) | translate }}"> | |
74 | 91 | <mat-select formControlName="checksumAlgorithm" *ngIf="isAdd"> |
75 | 92 | <mat-option [value]=null></mat-option> |
76 | 93 | <mat-option *ngFor="let checksumAlgorithm of checksumAlgorithms" [value]="checksumAlgorithm"> | ... | ... |
... | ... | @@ -22,7 +22,13 @@ import { TranslateService } from '@ngx-translate/core'; |
22 | 22 | import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; |
23 | 23 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
24 | 24 | import { EntityComponent } from '@home/components/entity/entity.component'; |
25 | -import { ChecksumAlgorithm, ChecksumAlgorithmTranslationMap, Firmware } from '@shared/models/firmware.models'; | |
25 | +import { | |
26 | + ChecksumAlgorithm, | |
27 | + ChecksumAlgorithmTranslationMap, | |
28 | + Firmware, | |
29 | + FirmwareType, | |
30 | + FirmwareTypeTranslationMap | |
31 | +} from '@shared/models/firmware.models'; | |
26 | 32 | import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators'; |
27 | 33 | import { ActionNotificationShow } from '@core/notification/notification.actions'; |
28 | 34 | |
... | ... | @@ -36,6 +42,8 @@ export class FirmwaresComponent extends EntityComponent<Firmware> implements OnI |
36 | 42 | |
37 | 43 | checksumAlgorithms = Object.values(ChecksumAlgorithm); |
38 | 44 | checksumAlgorithmTranslationMap = ChecksumAlgorithmTranslationMap; |
45 | + firmwareTypes = Object.values(FirmwareType); | |
46 | + firmwareTypeTranslationMap = FirmwareTypeTranslationMap; | |
39 | 47 | |
40 | 48 | constructor(protected store: Store<AppState>, |
41 | 49 | protected translate: TranslateService, |
... | ... | @@ -83,6 +91,8 @@ export class FirmwaresComponent extends EntityComponent<Firmware> implements OnI |
83 | 91 | const form = this.fb.group({ |
84 | 92 | title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]], |
85 | 93 | version: [entity ? entity.version : '', [Validators.required, Validators.maxLength(255)]], |
94 | + type: [entity?.type ? entity.type : FirmwareType.FIRMWARE, [Validators.required]], | |
95 | + deviceProfileId: [entity ? entity.deviceProfileId : null], | |
86 | 96 | checksumAlgorithm: [entity ? entity.checksumAlgorithm : null], |
87 | 97 | checksum: [entity ? entity.checksum : '', Validators.maxLength(1020)], |
88 | 98 | additionalInfo: this.fb.group( |
... | ... | @@ -105,6 +115,8 @@ export class FirmwaresComponent extends EntityComponent<Firmware> implements OnI |
105 | 115 | this.entityForm.patchValue({ |
106 | 116 | title: entity.title, |
107 | 117 | version: entity.version, |
118 | + type: entity.type, | |
119 | + deviceProfileId: entity.deviceProfileId, | |
108 | 120 | checksumAlgorithm: entity.checksumAlgorithm, |
109 | 121 | checksum: entity.checksum, |
110 | 122 | fileName: entity.fileName, | ... | ... |
... | ... | @@ -37,11 +37,11 @@ |
37 | 37 | <mat-option *ngIf="!(filteredFirmwares | async)?.length" [value]="null" class="tb-not-found"> |
38 | 38 | <div class="tb-not-found-content" (click)="$event.stopPropagation()"> |
39 | 39 | <div *ngIf="!textIsNotEmpty(searchText); else searchNotEmpty"> |
40 | - <span translate>firmware.no-firmware-text</span> | |
40 | + <span>{{ notFoundFirmware | translate }}</span> | |
41 | 41 | </div> |
42 | 42 | <ng-template #searchNotEmpty> |
43 | 43 | <span> |
44 | - {{ translate.get('firmware.no-firmware-matching', | |
44 | + {{ translate.get(notMatchingFirmware, | |
45 | 45 | {entity: truncate.transform(searchText, true, 6, '...')}) | async }} |
46 | 46 | </span> |
47 | 47 | </ng-template> | ... | ... |
... | ... | @@ -28,7 +28,7 @@ import { BaseData } from '@shared/models/base-data'; |
28 | 28 | import { EntityService } from '@core/http/entity.service'; |
29 | 29 | import { TruncatePipe } from '@shared/pipe/truncate.pipe'; |
30 | 30 | import { MatAutocompleteTrigger } from '@angular/material/autocomplete'; |
31 | -import { FirmwareInfo } from '@shared/models/firmware.models'; | |
31 | +import { FirmwareInfo, FirmwareType } from '@shared/models/firmware.models'; | |
32 | 32 | import { FirmwareService } from '@core/http/firmware.service'; |
33 | 33 | import { PageLink } from '@shared/models/page/page-link'; |
34 | 34 | import { Direction } from '@shared/models/page/sort-order'; |
... | ... | @@ -50,6 +50,12 @@ export class FirmwareAutocompleteComponent implements ControlValueAccessor, OnIn |
50 | 50 | modelValue: string | null; |
51 | 51 | |
52 | 52 | @Input() |
53 | + type = FirmwareType.FIRMWARE; | |
54 | + | |
55 | + @Input() | |
56 | + deviceProfileId: string; | |
57 | + | |
58 | + @Input() | |
53 | 59 | labelText: string; |
54 | 60 | |
55 | 61 | @Input() |
... | ... | @@ -81,6 +87,23 @@ export class FirmwareAutocompleteComponent implements ControlValueAccessor, OnIn |
81 | 87 | |
82 | 88 | private dirty = false; |
83 | 89 | |
90 | + private firmwareTypeTranslation = new Map<FirmwareType, any>( | |
91 | + [ | |
92 | + [FirmwareType.FIRMWARE, { | |
93 | + label: 'firmware.firmware', | |
94 | + required: 'firmware.firmware-required', | |
95 | + noFound: 'firmware.no-firmware-text', | |
96 | + noMatching: 'firmware.no-firmware-matching' | |
97 | + }], | |
98 | + [FirmwareType.SOFTWARE, { | |
99 | + label: 'firmware.software', | |
100 | + required: 'firmware.software-required', | |
101 | + noFound: 'firmware.no-software-text', | |
102 | + noMatching: 'firmware.no-software-matching' | |
103 | + }] | |
104 | + ] | |
105 | + ); | |
106 | + | |
84 | 107 | private propagateChange = (v: any) => { }; |
85 | 108 | |
86 | 109 | constructor(private store: Store<AppState>, |
... | ... | @@ -160,7 +183,7 @@ export class FirmwareAutocompleteComponent implements ControlValueAccessor, OnIn |
160 | 183 | this.entityService.getEntity(EntityType.FIRMWARE, firmwareId, {ignoreLoading: true, ignoreErrors: true}).subscribe( |
161 | 184 | (entity) => { |
162 | 185 | this.modelValue = entity.id.id; |
163 | - this.firmwareFormGroup.get('firmwareId').patchValue(entity, {emitEvent: false}); | |
186 | + this.firmwareFormGroup.get('firmwareId').patchValue(entity); | |
164 | 187 | }, |
165 | 188 | () => { |
166 | 189 | this.modelValue = null; |
... | ... | @@ -173,6 +196,7 @@ export class FirmwareAutocompleteComponent implements ControlValueAccessor, OnIn |
173 | 196 | } else { |
174 | 197 | this.modelValue = null; |
175 | 198 | this.firmwareFormGroup.get('firmwareId').patchValue('', {emitEvent: false}); |
199 | + this.propagateChange(null); | |
176 | 200 | } |
177 | 201 | } else { |
178 | 202 | this.modelValue = null; |
... | ... | @@ -209,7 +233,8 @@ export class FirmwareAutocompleteComponent implements ControlValueAccessor, OnIn |
209 | 233 | property: 'title', |
210 | 234 | direction: Direction.ASC |
211 | 235 | }); |
212 | - return this.firmwareService.getFirmwares(pageLink, true, {ignoreLoading: true}).pipe( | |
236 | + return this.firmwareService.getFirmwaresInfoByDeviceProfileId(pageLink, this.deviceProfileId, this.type, | |
237 | + true, {ignoreLoading: true}).pipe( | |
213 | 238 | map((data) => data && data.data.length ? data.data : null) |
214 | 239 | ); |
215 | 240 | } |
... | ... | @@ -223,11 +248,19 @@ export class FirmwareAutocompleteComponent implements ControlValueAccessor, OnIn |
223 | 248 | } |
224 | 249 | |
225 | 250 | get placeholderText(): string { |
226 | - return this.labelText || 'firmware.firmware'; | |
251 | + return this.labelText || this.firmwareTypeTranslation.get(this.type).label; | |
227 | 252 | } |
228 | 253 | |
229 | 254 | get requiredErrorText(): string { |
230 | - return this.requiredText || 'firmware.firmware-required'; | |
255 | + return this.requiredText || this.firmwareTypeTranslation.get(this.type).required; | |
256 | + } | |
257 | + | |
258 | + get notFoundFirmware(): string { | |
259 | + return this.firmwareTypeTranslation.get(this.type).noFound; | |
260 | + } | |
261 | + | |
262 | + get notMatchingFirmware(): string { | |
263 | + return this.firmwareTypeTranslation.get(this.type).noMatching; | |
231 | 264 | } |
232 | 265 | |
233 | 266 | firmwareTitleText(firmware: FirmwareInfo): string { | ... | ... |
... | ... | @@ -498,6 +498,7 @@ export interface DeviceProfile extends BaseData<DeviceProfileId> { |
498 | 498 | defaultRuleChainId?: RuleChainId; |
499 | 499 | defaultQueueName?: string; |
500 | 500 | firmwareId?: FirmwareId; |
501 | + softwareId?: FirmwareId; | |
501 | 502 | profileData: DeviceProfileData; |
502 | 503 | } |
503 | 504 | |
... | ... | @@ -558,6 +559,7 @@ export interface Device extends BaseData<DeviceId> { |
558 | 559 | type: string; |
559 | 560 | label: string; |
560 | 561 | firmwareId?: FirmwareId; |
562 | + softwareId?: FirmwareId; | |
561 | 563 | deviceProfileId?: DeviceProfileId; |
562 | 564 | deviceData?: DeviceData; |
563 | 565 | additionalInfo?: any; | ... | ... |
... | ... | @@ -17,6 +17,7 @@ |
17 | 17 | import { BaseData } from '@shared/models/base-data'; |
18 | 18 | import { TenantId } from '@shared/models/id/tenant-id'; |
19 | 19 | import { FirmwareId } from '@shared/models/id/firmware-id'; |
20 | +import { DeviceProfileId } from '@shared/models/id/device-profile-id'; | |
20 | 21 | |
21 | 22 | export enum ChecksumAlgorithm { |
22 | 23 | MD5 = 'md5', |
... | ... | @@ -32,14 +33,28 @@ export const ChecksumAlgorithmTranslationMap = new Map<ChecksumAlgorithm, string |
32 | 33 | ] |
33 | 34 | ); |
34 | 35 | |
36 | +export enum FirmwareType { | |
37 | + FIRMWARE = 'FIRMWARE', | |
38 | + SOFTWARE = 'SOFTWARE' | |
39 | +} | |
40 | + | |
41 | +export const FirmwareTypeTranslationMap = new Map<FirmwareType, string>( | |
42 | + [ | |
43 | + [FirmwareType.FIRMWARE, 'firmware.types.firmware'], | |
44 | + [FirmwareType.SOFTWARE, 'firmware.types.software'] | |
45 | + ] | |
46 | +); | |
47 | + | |
35 | 48 | export interface FirmwareInfo extends BaseData<FirmwareId> { |
36 | 49 | tenantId?: TenantId; |
50 | + type: FirmwareType; | |
51 | + deviceProfileId?: DeviceProfileId; | |
37 | 52 | title?: string; |
38 | 53 | version?: string; |
39 | 54 | hasData?: boolean; |
40 | 55 | fileName: string; |
41 | - checksum?: ChecksumAlgorithm; | |
42 | - checksumAlgorithm?: string; | |
56 | + checksum?: string; | |
57 | + checksumAlgorithm?: ChecksumAlgorithm; | |
43 | 58 | contentType: string; |
44 | 59 | dataSize?: number; |
45 | 60 | additionalInfo?: any; | ... | ... |
... | ... | @@ -1948,6 +1948,8 @@ |
1948 | 1948 | "idCopiedMessage": "Firmware Id has been copied to clipboard", |
1949 | 1949 | "no-firmware-matching": "No firmware matching '{{entity}}' were found.", |
1950 | 1950 | "no-firmware-text": "No firmwares found", |
1951 | + "no-software-matching": "No sowtware matching '{{entity}}' were found.", | |
1952 | + "no-software-text": "No software found", | |
1951 | 1953 | "file-name": "File name", |
1952 | 1954 | "file-size": "File size", |
1953 | 1955 | "file-size-bytes": "File size in bytes", |
... | ... | @@ -1956,8 +1958,15 @@ |
1956 | 1958 | "firmware-required": "Firmware is required.", |
1957 | 1959 | "search": "Search firmwares", |
1958 | 1960 | "selected-firmware": "{ count, plural, 1 {1 firmware} other {# firmwares} } selected", |
1961 | + "software": "Software", | |
1962 | + "software-required": "Software is required.", | |
1959 | 1963 | "title": "Title", |
1960 | 1964 | "title-required": "Title is required.", |
1965 | + "type": "Firmware type", | |
1966 | + "types": { | |
1967 | + "firmware": "Firmware", | |
1968 | + "software": "Software" | |
1969 | + }, | |
1961 | 1970 | "version": "Version", |
1962 | 1971 | "version-required": "Version is required.", |
1963 | 1972 | "warning-after-save-no-edit": "Once the firmware is saved, it will not be possible to change the title and version fields." | ... | ... |