Showing
11 changed files
with
111 additions
and
23 deletions
... | ... | @@ -355,10 +355,12 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService |
355 | 355 | pageData = tenantService.findTenants(pageLink); |
356 | 356 | for (Tenant tenant : pageData.getData()) { |
357 | 357 | List<EntitySubtype> deviceTypes = deviceService.findDeviceTypesByTenantId(tenant.getId()).get(); |
358 | - deviceProfileService.findOrCreateDefaultDeviceProfile(tenant.getId()); | |
358 | + try { | |
359 | + deviceProfileService.createDefaultDeviceProfile(tenant.getId()); | |
360 | + } catch (Exception e){} | |
359 | 361 | for (EntitySubtype deviceType : deviceTypes) { |
360 | 362 | try { |
361 | - deviceProfileService.createDeviceProfile(tenant.getId(), deviceType.getType()); | |
363 | + deviceProfileService.findOrCreateDeviceProfile(tenant.getId(), deviceType.getType()); | |
362 | 364 | } catch (Exception e) { |
363 | 365 | } |
364 | 366 | } | ... | ... |
... | ... | @@ -27,6 +27,8 @@ public interface DeviceProfileService { |
27 | 27 | |
28 | 28 | DeviceProfile findDeviceProfileById(TenantId tenantId, DeviceProfileId deviceProfileId); |
29 | 29 | |
30 | + DeviceProfile findDeviceProfileByName(TenantId tenantId, String profileName); | |
31 | + | |
30 | 32 | DeviceProfileInfo findDeviceProfileInfoById(TenantId tenantId, DeviceProfileId deviceProfileId); |
31 | 33 | |
32 | 34 | DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile); |
... | ... | @@ -37,12 +39,10 @@ public interface DeviceProfileService { |
37 | 39 | |
38 | 40 | PageData<DeviceProfileInfo> findDeviceProfileInfos(TenantId tenantId, PageLink pageLink); |
39 | 41 | |
40 | - DeviceProfile findOrCreateDefaultDeviceProfile(TenantId tenantId); | |
42 | + DeviceProfile findOrCreateDeviceProfile(TenantId tenantId, String profileName); | |
41 | 43 | |
42 | 44 | DeviceProfile createDefaultDeviceProfile(TenantId tenantId); |
43 | 45 | |
44 | - DeviceProfile createDeviceProfile(TenantId tenantId, String profileName); | |
45 | - | |
46 | 46 | DeviceProfile findDefaultDeviceProfile(TenantId tenantId); |
47 | 47 | |
48 | 48 | DeviceProfileInfo findDefaultDeviceProfileInfo(TenantId tenantId); | ... | ... |
... | ... | @@ -39,6 +39,7 @@ import io.netty.util.concurrent.Future; |
39 | 39 | import io.netty.util.concurrent.GenericFutureListener; |
40 | 40 | import lombok.extern.slf4j.Slf4j; |
41 | 41 | import org.springframework.util.StringUtils; |
42 | +import org.thingsboard.server.common.data.DeviceProfile; | |
42 | 43 | import org.thingsboard.server.common.data.DeviceTransportType; |
43 | 44 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
44 | 45 | import org.thingsboard.server.common.msg.EncryptionUtil; |
... | ... | @@ -574,7 +575,13 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
574 | 575 | try { |
575 | 576 | adaptor.convertToPublish(deviceSessionCtx, rpcResponse).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush); |
576 | 577 | } catch (Exception e) { |
577 | - log.trace("[{}] Failed to convert device RPC commandto MQTT msg", sessionId, e); | |
578 | + log.trace("[{}] Failed to convert device RPC command to MQTT msg", sessionId, e); | |
578 | 579 | } |
579 | 580 | } |
581 | + | |
582 | + @Override | |
583 | + public void onProfileUpdate(DeviceProfile deviceProfile) { | |
584 | + deviceSessionCtx.getDeviceInfo().setDeviceType(deviceProfile.getName()); | |
585 | + sessionInfo = SessionInfoProto.newBuilder().mergeFrom(sessionInfo).setDeviceType(deviceProfile.getName()).build(); | |
586 | + } | |
580 | 587 | } | ... | ... |
... | ... | @@ -184,4 +184,15 @@ public interface DeviceDao extends Dao<Device> { |
184 | 184 | ListenableFuture<Device> findDeviceByTenantIdAndIdAsync(TenantId tenantId, UUID id); |
185 | 185 | |
186 | 186 | Long countDevicesByDeviceProfileId(TenantId tenantId, UUID deviceProfileId); |
187 | + | |
188 | + /** | |
189 | + * Find devices by tenantId, profileId and page link. | |
190 | + * | |
191 | + * @param tenantId the tenantId | |
192 | + * @param profileId the profileId | |
193 | + * @param pageLink the page link | |
194 | + * @return the list of device objects | |
195 | + */ | |
196 | + PageData<Device> findDevicesByTenantIdAndProfileId(UUID tenantId, UUID profileId, PageLink pageLink); | |
197 | + | |
187 | 198 | } | ... | ... |
... | ... | @@ -37,4 +37,6 @@ public interface DeviceProfileDao extends Dao<DeviceProfile> { |
37 | 37 | DeviceProfile findDefaultDeviceProfile(TenantId tenantId); |
38 | 38 | |
39 | 39 | DeviceProfileInfo findDefaultDeviceProfileInfo(TenantId tenantId); |
40 | + | |
41 | + DeviceProfile findByName(TenantId tenantId, String profileName); | |
40 | 42 | } | ... | ... |
... | ... | @@ -23,10 +23,12 @@ import org.springframework.cache.Cache; |
23 | 23 | import org.springframework.cache.CacheManager; |
24 | 24 | import org.springframework.cache.annotation.Cacheable; |
25 | 25 | import org.springframework.stereotype.Service; |
26 | +import org.thingsboard.server.common.data.Device; | |
26 | 27 | import org.thingsboard.server.common.data.DeviceProfile; |
27 | 28 | import org.thingsboard.server.common.data.DeviceProfileInfo; |
28 | 29 | import org.thingsboard.server.common.data.DeviceProfileType; |
29 | 30 | import org.thingsboard.server.common.data.DeviceTransportType; |
31 | +import org.thingsboard.server.common.data.EntitySubtype; | |
30 | 32 | import org.thingsboard.server.common.data.Tenant; |
31 | 33 | import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; |
32 | 34 | import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration; |
... | ... | @@ -44,6 +46,7 @@ import org.thingsboard.server.dao.tenant.TenantDao; |
44 | 46 | |
45 | 47 | import java.util.Arrays; |
46 | 48 | import java.util.Collections; |
49 | +import java.util.List; | |
47 | 50 | |
48 | 51 | import static org.thingsboard.server.common.data.CacheConstants.DEVICE_PROFILE_CACHE; |
49 | 52 | import static org.thingsboard.server.dao.service.Validator.validateId; |
... | ... | @@ -54,6 +57,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
54 | 57 | |
55 | 58 | private static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; |
56 | 59 | private static final String INCORRECT_DEVICE_PROFILE_ID = "Incorrect deviceProfileId "; |
60 | + private static final String INCORRECT_DEVICE_PROFILE_NAME = "Incorrect deviceProfileName "; | |
57 | 61 | |
58 | 62 | @Autowired |
59 | 63 | private DeviceProfileDao deviceProfileDao; |
... | ... | @@ -62,6 +66,9 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
62 | 66 | private DeviceDao deviceDao; |
63 | 67 | |
64 | 68 | @Autowired |
69 | + private DeviceService deviceService; | |
70 | + | |
71 | + @Autowired | |
65 | 72 | private TenantDao tenantDao; |
66 | 73 | |
67 | 74 | @Autowired |
... | ... | @@ -75,6 +82,13 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
75 | 82 | return deviceProfileDao.findById(tenantId, deviceProfileId.getId()); |
76 | 83 | } |
77 | 84 | |
85 | + @Override | |
86 | + public DeviceProfile findDeviceProfileByName(TenantId tenantId, String profileName) { | |
87 | + log.trace("Executing findDeviceProfileByName [{}][{}]", tenantId, profileName); | |
88 | + Validator.validateString(profileName, INCORRECT_DEVICE_PROFILE_NAME + profileName); | |
89 | + return deviceProfileDao.findByName(tenantId, profileName); | |
90 | + } | |
91 | + | |
78 | 92 | @Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{'info', #deviceProfileId.id}") |
79 | 93 | @Override |
80 | 94 | public DeviceProfileInfo findDeviceProfileInfoById(TenantId tenantId, DeviceProfileId deviceProfileId) { |
... | ... | @@ -87,6 +101,10 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
87 | 101 | public DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile) { |
88 | 102 | log.trace("Executing saveDeviceProfile [{}]", deviceProfile); |
89 | 103 | deviceProfileValidator.validate(deviceProfile, DeviceProfile::getTenantId); |
104 | + DeviceProfile oldDeviceProfile = null; | |
105 | + if (deviceProfile.getId() != null) { | |
106 | + oldDeviceProfile = deviceProfileDao.findById(deviceProfile.getTenantId(), deviceProfile.getId().getId()); | |
107 | + } | |
90 | 108 | DeviceProfile savedDeviceProfile; |
91 | 109 | try { |
92 | 110 | savedDeviceProfile = deviceProfileDao.save(deviceProfile.getTenantId(), deviceProfile); |
... | ... | @@ -101,10 +119,23 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
101 | 119 | Cache cache = cacheManager.getCache(DEVICE_PROFILE_CACHE); |
102 | 120 | cache.evict(Collections.singletonList(savedDeviceProfile.getId().getId())); |
103 | 121 | cache.evict(Arrays.asList("info", savedDeviceProfile.getId().getId())); |
122 | + cache.evict(Arrays.asList(deviceProfile.getTenantId().getId(), deviceProfile.getName())); | |
104 | 123 | if (savedDeviceProfile.isDefault()) { |
105 | 124 | cache.evict(Arrays.asList("default", savedDeviceProfile.getTenantId().getId())); |
106 | 125 | cache.evict(Arrays.asList("default", "info", savedDeviceProfile.getTenantId().getId())); |
107 | 126 | } |
127 | + if (oldDeviceProfile != null && !oldDeviceProfile.getName().equals(deviceProfile.getName())) { | |
128 | + PageLink pageLink = new PageLink(100); | |
129 | + PageData<Device> pageData; | |
130 | + do { | |
131 | + pageData = deviceDao.findDevicesByTenantIdAndProfileId(deviceProfile.getTenantId().getId(), deviceProfile.getUuidId(), pageLink); | |
132 | + for (Device device : pageData.getData()) { | |
133 | + device.setType(deviceProfile.getName()); | |
134 | + deviceService.saveDevice(device); | |
135 | + } | |
136 | + pageLink = pageLink.nextPageLink(); | |
137 | + } while (pageData.hasNext()); | |
138 | + } | |
108 | 139 | return savedDeviceProfile; |
109 | 140 | } |
110 | 141 | |
... | ... | @@ -116,10 +147,11 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
116 | 147 | if (deviceProfile != null && deviceProfile.isDefault()) { |
117 | 148 | throw new DataValidationException("Deletion of Default Device Profile is prohibited!"); |
118 | 149 | } |
119 | - this.removeDeviceProfile(tenantId, deviceProfileId); | |
150 | + this.removeDeviceProfile(tenantId, deviceProfile); | |
120 | 151 | } |
121 | 152 | |
122 | - private void removeDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId) { | |
153 | + private void removeDeviceProfile(TenantId tenantId, DeviceProfile deviceProfile) { | |
154 | + DeviceProfileId deviceProfileId = deviceProfile.getId(); | |
123 | 155 | try { |
124 | 156 | deviceProfileDao.removeById(tenantId, deviceProfileId.getId()); |
125 | 157 | } catch (Exception t) { |
... | ... | @@ -134,6 +166,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
134 | 166 | Cache cache = cacheManager.getCache(DEVICE_PROFILE_CACHE); |
135 | 167 | cache.evict(Collections.singletonList(deviceProfileId.getId())); |
136 | 168 | cache.evict(Arrays.asList("info", deviceProfileId.getId())); |
169 | + cache.evict(Arrays.asList(tenantId.getId(), deviceProfile.getName())); | |
137 | 170 | } |
138 | 171 | |
139 | 172 | @Override |
... | ... | @@ -152,12 +185,13 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
152 | 185 | return deviceProfileDao.findDeviceProfileInfos(tenantId, pageLink); |
153 | 186 | } |
154 | 187 | |
188 | + @Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{#tenantId.id, #name}") | |
155 | 189 | @Override |
156 | - public DeviceProfile findOrCreateDefaultDeviceProfile(TenantId tenantId) { | |
190 | + public DeviceProfile findOrCreateDeviceProfile(TenantId tenantId, String name) { | |
157 | 191 | log.trace("Executing findOrCreateDefaultDeviceProfile"); |
158 | - DeviceProfile deviceProfile = findDefaultDeviceProfile(tenantId); | |
192 | + DeviceProfile deviceProfile = findDeviceProfileByName(tenantId, name); | |
159 | 193 | if (deviceProfile == null) { |
160 | - deviceProfile = this.createDefaultDeviceProfile(tenantId); | |
194 | + deviceProfile = this.doCreateDefaultDeviceProfile(tenantId, name, name.equals("default")); | |
161 | 195 | } |
162 | 196 | return deviceProfile; |
163 | 197 | } |
... | ... | @@ -168,12 +202,6 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
168 | 202 | return doCreateDefaultDeviceProfile(tenantId, "default", true); |
169 | 203 | } |
170 | 204 | |
171 | - @Override | |
172 | - public DeviceProfile createDeviceProfile(TenantId tenantId, String profileName) { | |
173 | - log.trace("Executing createDefaultDeviceProfile tenantId [{}], profileName [{}]", tenantId, profileName); | |
174 | - return doCreateDefaultDeviceProfile(tenantId, profileName, false); | |
175 | - } | |
176 | - | |
177 | 205 | private DeviceProfile doCreateDefaultDeviceProfile(TenantId tenantId, String profileName, boolean defaultProfile) { |
178 | 206 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
179 | 207 | DeviceProfile deviceProfile = new DeviceProfile(); |
... | ... | @@ -227,6 +255,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
227 | 255 | deviceProfileDao.save(tenantId, deviceProfile); |
228 | 256 | cache.evict(Collections.singletonList(previousDefaultDeviceProfile.getId().getId())); |
229 | 257 | cache.evict(Arrays.asList("info", previousDefaultDeviceProfile.getId().getId())); |
258 | + cache.evict(Arrays.asList(tenantId.getId(), previousDefaultDeviceProfile.getName())); | |
230 | 259 | changed = true; |
231 | 260 | } |
232 | 261 | if (changed) { |
... | ... | @@ -234,6 +263,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
234 | 263 | cache.evict(Arrays.asList("info", deviceProfile.getId().getId())); |
235 | 264 | cache.evict(Arrays.asList("default", tenantId.getId())); |
236 | 265 | cache.evict(Arrays.asList("default", "info", tenantId.getId())); |
266 | + cache.evict(Arrays.asList(tenantId.getId(), deviceProfile.getName())); | |
237 | 267 | } |
238 | 268 | return changed; |
239 | 269 | } |
... | ... | @@ -309,7 +339,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D |
309 | 339 | |
310 | 340 | @Override |
311 | 341 | protected void removeEntity(TenantId tenantId, DeviceProfile entity) { |
312 | - removeDeviceProfile(tenantId, entity.getId()); | |
342 | + removeDeviceProfile(tenantId, entity); | |
313 | 343 | } |
314 | 344 | }; |
315 | 345 | ... | ... |
... | ... | @@ -169,8 +169,14 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe |
169 | 169 | deviceValidator.validate(device, Device::getTenantId); |
170 | 170 | Device savedDevice; |
171 | 171 | try { |
172 | + DeviceProfile deviceProfile; | |
172 | 173 | if (device.getDeviceProfileId() == null) { |
173 | - DeviceProfile deviceProfile = this.deviceProfileService.findOrCreateDefaultDeviceProfile(device.getTenantId()); | |
174 | + if (!StringUtils.isEmpty(device.getType())) { | |
175 | + deviceProfile = this.deviceProfileService.findOrCreateDeviceProfile(device.getTenantId(), device.getType()); | |
176 | + } else { | |
177 | + deviceProfile = this.deviceProfileService.findDefaultDeviceProfile(device.getTenantId()); | |
178 | + device.setType(deviceProfile.getName()); | |
179 | + } | |
174 | 180 | device.setDeviceProfileId(new DeviceProfileId(deviceProfile.getId().getId())); |
175 | 181 | DeviceData deviceData = new DeviceData(); |
176 | 182 | switch (deviceProfile.getType()) { |
... | ... | @@ -178,7 +184,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe |
178 | 184 | deviceData.setConfiguration(new DefaultDeviceConfiguration()); |
179 | 185 | break; |
180 | 186 | } |
181 | - switch (deviceProfile.getTransportType()){ | |
187 | + switch (deviceProfile.getTransportType()) { | |
182 | 188 | case DEFAULT: |
183 | 189 | deviceData.setTransportConfiguration(new DefaultDeviceTransportConfiguration()); |
184 | 190 | break; |
... | ... | @@ -190,7 +196,14 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe |
190 | 196 | break; |
191 | 197 | } |
192 | 198 | device.setDeviceData(deviceData); |
199 | + } else { | |
200 | + deviceProfile = this.deviceProfileService.findDeviceProfileById(device.getTenantId(), device.getDeviceProfileId()); | |
201 | + if (deviceProfile == null) { | |
202 | + throw new DataValidationException("Device is referencing non existing device profile!"); | |
203 | + } | |
193 | 204 | } |
205 | + device.setType(deviceProfile.getName()); | |
206 | + | |
194 | 207 | savedDevice = deviceDao.save(device.getTenantId(), device); |
195 | 208 | } catch (Exception t) { |
196 | 209 | ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); |
... | ... | @@ -441,9 +454,6 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe |
441 | 454 | |
442 | 455 | @Override |
443 | 456 | protected void validateDataImpl(TenantId tenantId, Device device) { |
444 | - if (StringUtils.isEmpty(device.getType())) { | |
445 | - throw new DataValidationException("Device type should be specified!"); | |
446 | - } | |
447 | 457 | if (StringUtils.isEmpty(device.getName())) { |
448 | 458 | throw new DataValidationException("Device name should be specified!"); |
449 | 459 | } | ... | ... |
... | ... | @@ -20,6 +20,7 @@ import org.springframework.data.domain.Pageable; |
20 | 20 | import org.springframework.data.jpa.repository.Query; |
21 | 21 | import org.springframework.data.repository.PagingAndSortingRepository; |
22 | 22 | import org.springframework.data.repository.query.Param; |
23 | +import org.thingsboard.server.common.data.DeviceProfile; | |
23 | 24 | import org.thingsboard.server.common.data.DeviceProfileInfo; |
24 | 25 | import org.thingsboard.server.dao.model.sql.DeviceProfileEntity; |
25 | 26 | |
... | ... | @@ -53,4 +54,7 @@ public interface DeviceProfileRepository extends PagingAndSortingRepository<Devi |
53 | 54 | "FROM DeviceProfileEntity d " + |
54 | 55 | "WHERE d.tenantId = :tenantId AND d.isDefault = true") |
55 | 56 | DeviceProfileInfo findDefaultDeviceProfileInfo(@Param("tenantId") UUID tenantId); |
57 | + | |
58 | + DeviceProfile findByTenantIdAndName(UUID id, String profileName); | |
59 | + | |
56 | 60 | } | ... | ... |
... | ... | @@ -46,6 +46,14 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit |
46 | 46 | @Param("searchText") String searchText, |
47 | 47 | Pageable pageable); |
48 | 48 | |
49 | + @Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " + | |
50 | + "AND d.deviceProfileId = :profileId " + | |
51 | + "AND LOWER(d.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") | |
52 | + Page<DeviceEntity> findByTenantIdAndProfileId(@Param("tenantId") UUID tenantId, | |
53 | + @Param("profileId") UUID profileId, | |
54 | + @Param("searchText") String searchText, | |
55 | + Pageable pageable); | |
56 | + | |
49 | 57 | @Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " + |
50 | 58 | "FROM DeviceEntity d " + |
51 | 59 | "LEFT JOIN CustomerEntity c on c.id = d.customerId " + | ... | ... |
... | ... | @@ -105,6 +105,16 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device> |
105 | 105 | } |
106 | 106 | |
107 | 107 | @Override |
108 | + public PageData<Device> findDevicesByTenantIdAndProfileId(UUID tenantId, UUID profileId, PageLink pageLink) { | |
109 | + return DaoUtil.toPageData( | |
110 | + deviceRepository.findByTenantIdAndProfileId( | |
111 | + tenantId, | |
112 | + profileId, | |
113 | + Objects.toString(pageLink.getTextSearch(), ""), | |
114 | + DaoUtil.toPageable(pageLink))); | |
115 | + } | |
116 | + | |
117 | + @Override | |
108 | 118 | public PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink) { |
109 | 119 | return DaoUtil.toPageData( |
110 | 120 | deviceRepository.findDeviceInfosByTenantIdAndCustomerId( | ... | ... |
... | ... | @@ -80,4 +80,8 @@ public class JpaDeviceProfileDao extends JpaAbstractSearchTextDao<DeviceProfileE |
80 | 80 | return deviceProfileRepository.findDefaultDeviceProfileInfo(tenantId.getId()); |
81 | 81 | } |
82 | 82 | |
83 | + @Override | |
84 | + public DeviceProfile findByName(TenantId tenantId, String profileName) { | |
85 | + return deviceProfileRepository.findByTenantIdAndName(tenantId.getId(), profileName); | |
86 | + } | |
83 | 87 | } | ... | ... |