diff --git a/application/src/main/data/upgrade/3.2.2/schema_update.sql b/application/src/main/data/upgrade/3.2.2/schema_update.sql index da120f680e..af3fd418a8 100644 --- a/application/src/main/data/upgrade/3.2.2/schema_update.sql +++ b/application/src/main/data/upgrade/3.2.2/schema_update.sql @@ -63,6 +63,7 @@ CREATE TABLE IF NOT EXISTS firmware ( id uuid NOT NULL CONSTRAINT firmware_pkey PRIMARY KEY, created_time bigint NOT NULL, tenant_id uuid NOT NULL, + device_profile_id uuid, type varchar(32) NOT NULL, title varchar(255) NOT NULL, version varchar(255) NOT NULL, @@ -78,10 +79,12 @@ CREATE TABLE IF NOT EXISTS firmware ( ); ALTER TABLE device_profile - ADD COLUMN IF NOT EXISTS firmware_id uuid; + ADD COLUMN IF NOT EXISTS firmware_id uuid, + ADD COLUMN IF NOT EXISTS software_id uuid; ALTER TABLE device - ADD COLUMN IF NOT EXISTS firmware_id uuid; + ADD COLUMN IF NOT EXISTS firmware_id uuid, + ADD COLUMN IF NOT EXISTS software_id uuid; DO $$ BEGIN @@ -91,11 +94,23 @@ DO $$ FOREIGN KEY (firmware_id) REFERENCES firmware(id); END IF; + IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_software_device_profile') THEN + ALTER TABLE device_profile + ADD CONSTRAINT fk_software_device_profile + FOREIGN KEY (firmware_id) REFERENCES firmware(id); + END IF; + IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device') THEN ALTER TABLE device ADD CONSTRAINT fk_firmware_device FOREIGN KEY (firmware_id) REFERENCES firmware(id); END IF; + + IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_software_device') THEN + ALTER TABLE device + ADD CONSTRAINT fk_software_device + FOREIGN KEY (firmware_id) REFERENCES firmware(id); + END IF; END; $$; diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java index 020fd7c524..9df20674c8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java @@ -56,6 +56,7 @@ import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfilePr import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; +import org.thingsboard.server.common.data.firmware.FirmwareType; import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; @@ -405,9 +406,15 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D if (firmware == null) { throw new DataValidationException("Can't assign non-existent firmware!"); } + if (!firmware.getType().equals(FirmwareType.FIRMWARE)) { + throw new DataValidationException("Can't assign firmware with type: " + firmware.getType()); + } if (firmware.getData() == null) { throw new DataValidationException("Can't assign firmware with empty data!"); } + if (!firmware.getDeviceProfileId().equals(deviceProfile.getId())) { + throw new DataValidationException("Can't assign firmware with different deviceProfile!"); + } } if (deviceProfile.getSoftwareId() != null) { @@ -415,9 +422,15 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D if (software == null) { throw new DataValidationException("Can't assign non-existent software!"); } + if (!software.getType().equals(FirmwareType.SOFTWARE)) { + throw new DataValidationException("Can't assign software with type: " + software.getType()); + } if (software.getData() == null) { throw new DataValidationException("Can't assign software with empty data!"); } + if (!software.getDeviceProfileId().equals(deviceProfile.getId())) { + throw new DataValidationException("Can't assign firmware with different deviceProfile!"); + } } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java index dd9b46b62f..11d2fecd24 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java @@ -51,6 +51,7 @@ import org.thingsboard.server.common.data.device.data.DeviceData; import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfiguration; import org.thingsboard.server.common.data.device.data.MqttDeviceTransportConfiguration; import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.firmware.FirmwareType; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceProfileId; @@ -683,6 +684,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe if (firmware == null) { throw new DataValidationException("Can't assign non-existent firmware!"); } + if (!firmware.getType().equals(FirmwareType.FIRMWARE)) { + throw new DataValidationException("Can't assign firmware with type: " + firmware.getType()); + } if (firmware.getData() == null) { throw new DataValidationException("Can't assign firmware with empty data!"); } @@ -696,6 +700,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe if (software == null) { throw new DataValidationException("Can't assign non-existent software!"); } + if (!software.getType().equals(FirmwareType.SOFTWARE)) { + throw new DataValidationException("Can't assign software with type: " + software.getType()); + } if (software.getData() == null) { throw new DataValidationException("Can't assign software with empty data!"); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/firmware/BaseFirmwareService.java b/dao/src/main/java/org/thingsboard/server/dao/firmware/BaseFirmwareService.java index 207d629bbe..6ac3df8292 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/firmware/BaseFirmwareService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/firmware/BaseFirmwareService.java @@ -191,6 +191,7 @@ public class BaseFirmwareService implements FirmwareService { protected void validateUpdate(TenantId tenantId, FirmwareInfo firmware) { FirmwareInfo firmwareOld = firmwareInfoDao.findById(tenantId, firmware.getUuidId()); + validateUpdateDeviceProfile(firmware, firmwareOld); BaseFirmwareService.validateUpdate(firmware, firmwareOld); } }; @@ -247,6 +248,7 @@ public class BaseFirmwareService implements FirmwareService { protected void validateUpdate(TenantId tenantId, Firmware firmware) { Firmware firmwareOld = firmwareDao.findById(tenantId, firmware.getUuidId()); + validateUpdateDeviceProfile(firmware, firmwareOld); BaseFirmwareService.validateUpdate(firmware, firmwareOld); if (firmwareOld.getData() != null && !firmwareOld.getData().equals(firmware.getData())) { @@ -255,11 +257,15 @@ public class BaseFirmwareService implements FirmwareService { } }; - private static void validateUpdate(FirmwareInfo firmware, FirmwareInfo firmwareOld) { - if (!firmwareOld.getDeviceProfileId().equals(firmware.getDeviceProfileId())) { - throw new DataValidationException("Updating firmware deviceProfile is prohibited!"); + private void validateUpdateDeviceProfile(FirmwareInfo firmware, FirmwareInfo firmwareOld) { + if (firmwareOld.getDeviceProfileId() != null && !firmwareOld.getDeviceProfileId().equals(firmware.getDeviceProfileId())) { + if (firmwareInfoDao.isFirmwareUsed(firmwareOld.getId(), firmware.getType(), firmwareOld.getDeviceProfileId())) { + throw new DataValidationException("Can`t update deviceProfileId because firmware is already in use!"); + } } + } + private static void validateUpdate(FirmwareInfo firmware, FirmwareInfo firmwareOld) { if (!firmwareOld.getType().equals(firmware.getType())) { throw new DataValidationException("Updating type is prohibited!"); } @@ -303,9 +309,7 @@ public class BaseFirmwareService implements FirmwareService { } } - if (firmwareInfo.getDeviceProfileId() == null) { - throw new DataValidationException("Firmware should be assigned to deviceProfile!"); - } else { + if (firmwareInfo.getDeviceProfileId() != null) { DeviceProfile deviceProfile = deviceProfileDao.findById(firmwareInfo.getTenantId(), firmwareInfo.getDeviceProfileId().getId()); if (deviceProfile == null) { throw new DataValidationException("Firmware is referencing to non-existent device profile!"); diff --git a/dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareInfoDao.java index 32ca8dc528..7cb6c3a57f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareInfoDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareInfoDao.java @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.firmware; import org.thingsboard.server.common.data.FirmwareInfo; import org.thingsboard.server.common.data.firmware.FirmwareType; import org.thingsboard.server.common.data.id.DeviceProfileId; +import org.thingsboard.server.common.data.id.FirmwareId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; @@ -31,4 +32,6 @@ public interface FirmwareInfoDao extends Dao { PageData findFirmwareInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, FirmwareType firmwareType, boolean hasData, PageLink pageLink); + boolean isFirmwareUsed(FirmwareId firmwareId, FirmwareType type, DeviceProfileId deviceProfileId); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareEntity.java index a10ec8f7ed..4f3aded716 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareEntity.java @@ -32,9 +32,9 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.Lob; import javax.persistence.EnumType; import javax.persistence.Enumerated; +import javax.persistence.Lob; import javax.persistence.Table; import java.nio.ByteBuffer; import java.util.UUID; @@ -110,7 +110,9 @@ public class FirmwareEntity extends BaseSqlEntity implements SearchTex this.createdTime = firmware.getCreatedTime(); this.setUuid(firmware.getUuidId()); this.tenantId = firmware.getTenantId().getId(); - this.deviceProfileId = firmware.getDeviceProfileId().getId(); + if (firmware.getDeviceProfileId() != null) { + this.deviceProfileId = firmware.getDeviceProfileId().getId(); + } this.type = firmware.getType(); this.title = firmware.getTitle(); this.version = firmware.getVersion(); @@ -138,7 +140,9 @@ public class FirmwareEntity extends BaseSqlEntity implements SearchTex Firmware firmware = new Firmware(new FirmwareId(id)); firmware.setCreatedTime(createdTime); firmware.setTenantId(new TenantId(tenantId)); - firmware.setDeviceProfileId(new DeviceProfileId(deviceProfileId)); + if (deviceProfileId != null) { + firmware.setDeviceProfileId(new DeviceProfileId(deviceProfileId)); + } firmware.setType(type); firmware.setTitle(title); firmware.setVersion(version); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareInfoEntity.java index b1e058a012..bb62db5ea4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareInfoEntity.java @@ -109,7 +109,9 @@ public class FirmwareInfoEntity extends BaseSqlEntity implements S this.setUuid(firmware.getUuidId()); this.tenantId = firmware.getTenantId().getId(); this.type = firmware.getType(); - this.deviceProfileId = firmware.getDeviceProfileId().getId(); + if (firmware.getDeviceProfileId() != null) { + this.deviceProfileId = firmware.getDeviceProfileId().getId(); + } this.title = firmware.getTitle(); this.version = firmware.getVersion(); this.fileName = firmware.getFileName(); @@ -154,7 +156,9 @@ public class FirmwareInfoEntity extends BaseSqlEntity implements S FirmwareInfo firmware = new FirmwareInfo(new FirmwareId(id)); firmware.setCreatedTime(createdTime); firmware.setTenantId(new TenantId(tenantId)); - firmware.setDeviceProfileId(new DeviceProfileId(deviceProfileId)); + if (deviceProfileId != null) { + firmware.setDeviceProfileId(new DeviceProfileId(deviceProfileId)); + } firmware.setType(type); firmware.setTitle(title); firmware.setVersion(version); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareInfoRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareInfoRepository.java index 5a7af9997b..dab6ce3304 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareInfoRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareInfoRepository.java @@ -48,4 +48,13 @@ public interface FirmwareInfoRepository extends CrudRepository