created FirmwareStateService
This commit is contained in:
parent
81b203efeb
commit
d6f451ccca
@ -119,6 +119,7 @@ import org.thingsboard.server.queue.discovery.PartitionService;
|
||||
import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
|
||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||
import org.thingsboard.server.service.component.ComponentDiscoveryService;
|
||||
import org.thingsboard.server.service.firmware.FirmwareStateService;
|
||||
import org.thingsboard.server.service.lwm2m.LwM2MModelsRepository;
|
||||
import org.thingsboard.server.service.profile.TbDeviceProfileCache;
|
||||
import org.thingsboard.server.service.queue.TbClusterService;
|
||||
@ -240,6 +241,9 @@ public abstract class BaseController {
|
||||
@Autowired
|
||||
protected FirmwareService firmwareService;
|
||||
|
||||
@Autowired
|
||||
protected FirmwareStateService firmwareStateService;
|
||||
|
||||
@Autowired
|
||||
protected TbQueueProducerProvider producerProvider;
|
||||
|
||||
|
||||
@ -70,6 +70,7 @@ import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RestController
|
||||
@ -117,13 +118,25 @@ public class DeviceController extends BaseController {
|
||||
|
||||
checkEntity(device.getId(), device, Resource.DEVICE);
|
||||
|
||||
boolean created = device.getId() == null;
|
||||
|
||||
boolean isFirmwareChanged = false;
|
||||
|
||||
if (created) {
|
||||
isFirmwareChanged = true;
|
||||
} else {
|
||||
Device oldDevice = deviceService.findDeviceById(getTenantId(), device.getId());
|
||||
if (!Objects.equals(device.getFirmwareId(), oldDevice.getFirmwareId()) || !oldDevice.getDeviceProfileId().equals(device.getDeviceProfileId())) {
|
||||
isFirmwareChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
Device savedDevice = checkNotNull(deviceService.saveDeviceWithAccessToken(device, accessToken));
|
||||
|
||||
tbClusterService.onDeviceChange(savedDevice, null);
|
||||
tbClusterService.pushMsgToCore(new DeviceNameOrTypeUpdateMsg(savedDevice.getTenantId(),
|
||||
savedDevice.getId(), savedDevice.getName(), savedDevice.getType()), null);
|
||||
tbClusterService.onEntityStateChange(savedDevice.getTenantId(), savedDevice.getId(),
|
||||
device.getId() == null ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED);
|
||||
tbClusterService.onEntityStateChange(savedDevice.getTenantId(), savedDevice.getId(), created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED);
|
||||
|
||||
logEntityAction(savedDevice.getId(), savedDevice,
|
||||
savedDevice.getCustomerId(),
|
||||
@ -134,12 +147,19 @@ public class DeviceController extends BaseController {
|
||||
} else {
|
||||
deviceStateService.onDeviceUpdated(savedDevice);
|
||||
}
|
||||
|
||||
if (isFirmwareChanged) {
|
||||
firmwareStateService.update(savedDevice, created);
|
||||
}
|
||||
|
||||
return savedDevice;
|
||||
} catch (Exception e) {
|
||||
} catch (
|
||||
Exception e) {
|
||||
logEntityAction(emptyId(EntityType.DEVICE), device,
|
||||
null, device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
|
||||
throw handleException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
|
||||
|
||||
@ -43,6 +43,7 @@ import org.thingsboard.server.service.security.permission.Operation;
|
||||
import org.thingsboard.server.service.security.permission.Resource;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@ -143,6 +144,15 @@ public class DeviceProfileController extends BaseController {
|
||||
|
||||
checkEntity(deviceProfile.getId(), deviceProfile, Resource.DEVICE_PROFILE);
|
||||
|
||||
boolean isFirmwareChanged = false;
|
||||
|
||||
if (!created) {
|
||||
DeviceProfile oldDeviceProfile = deviceProfileService.findDeviceProfileById(getTenantId(), deviceProfile.getId());
|
||||
if (!Objects.equals(deviceProfile.getFirmwareId(), oldDeviceProfile.getFirmwareId())) {
|
||||
isFirmwareChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
DeviceProfile savedDeviceProfile = checkNotNull(deviceProfileService.saveDeviceProfile(deviceProfile));
|
||||
|
||||
tbClusterService.onDeviceProfileChange(savedDeviceProfile, null);
|
||||
@ -153,6 +163,10 @@ public class DeviceProfileController extends BaseController {
|
||||
null,
|
||||
created ? ActionType.ADDED : ActionType.UPDATED, null);
|
||||
|
||||
if (isFirmwareChanged) {
|
||||
firmwareStateService.update(savedDeviceProfile);
|
||||
}
|
||||
|
||||
return savedDeviceProfile;
|
||||
} catch (Exception e) {
|
||||
logEntityAction(emptyId(EntityType.DEVICE_PROFILE), deviceProfile,
|
||||
|
||||
@ -15,7 +15,9 @@
|
||||
*/
|
||||
package org.thingsboard.server.controller;
|
||||
|
||||
import com.google.common.hash.Hashing;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@ -127,6 +129,11 @@ public class FirmwareController extends BaseController {
|
||||
firmware.setVersion(info.getVersion());
|
||||
firmware.setAdditionalInfo(info.getAdditionalInfo());
|
||||
|
||||
if (StringUtils.isEmpty(checksumAlgorithm)) {
|
||||
checksumAlgorithm = "sha256";
|
||||
checksum = Hashing.sha256().hashBytes(file.getBytes()).toString();
|
||||
}
|
||||
|
||||
firmware.setChecksumAlgorithm(checksumAlgorithm);
|
||||
firmware.setChecksum(checksum);
|
||||
firmware.setFileName(file.getOriginalFilename());
|
||||
|
||||
@ -0,0 +1,171 @@
|
||||
/**
|
||||
* Copyright © 2016-2021 The Thingsboard Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.thingsboard.server.service.firmware;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thingsboard.rule.engine.api.RuleEngineTelemetryService;
|
||||
import org.thingsboard.server.common.data.DataConstants;
|
||||
import org.thingsboard.server.common.data.Device;
|
||||
import org.thingsboard.server.common.data.DeviceProfile;
|
||||
import org.thingsboard.server.common.data.Firmware;
|
||||
import org.thingsboard.server.common.data.id.DeviceId;
|
||||
import org.thingsboard.server.common.data.id.FirmwareId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
|
||||
import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
|
||||
import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
|
||||
import org.thingsboard.server.common.data.kv.LongDataEntry;
|
||||
import org.thingsboard.server.common.data.kv.StringDataEntry;
|
||||
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.dao.device.DeviceProfileService;
|
||||
import org.thingsboard.server.dao.device.DeviceService;
|
||||
import org.thingsboard.server.dao.firmware.FirmwareService;
|
||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_CHECKSUM;
|
||||
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_CHECKSUM_ALGORITHM;
|
||||
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_SIZE;
|
||||
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_TITLE;
|
||||
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_VERSION;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@TbCoreComponent
|
||||
public class DefaultFirmwareStateService implements FirmwareStateService {
|
||||
|
||||
private final FirmwareService firmwareService;
|
||||
private final DeviceService deviceService;
|
||||
private final DeviceProfileService deviceProfileService;
|
||||
private final RuleEngineTelemetryService telemetryService;
|
||||
|
||||
public DefaultFirmwareStateService(FirmwareService firmwareService, DeviceService deviceService, DeviceProfileService deviceProfileService, RuleEngineTelemetryService telemetryService) {
|
||||
this.firmwareService = firmwareService;
|
||||
this.deviceService = deviceService;
|
||||
this.deviceProfileService = deviceProfileService;
|
||||
this.telemetryService = telemetryService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Device device, boolean created) {
|
||||
FirmwareId firmwareId = device.getFirmwareId();
|
||||
if (firmwareId == null) {
|
||||
DeviceProfile deviceProfile = deviceProfileService.findDeviceProfileById(device.getTenantId(), device.getDeviceProfileId());
|
||||
firmwareId = deviceProfile.getFirmwareId();
|
||||
}
|
||||
|
||||
if (firmwareId == null) {
|
||||
if (!created) {
|
||||
remove(device);
|
||||
}
|
||||
} else {
|
||||
update(device, firmwareService.findFirmwareById(device.getTenantId(), firmwareId), System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(DeviceProfile deviceProfile) {
|
||||
TenantId tenantId = deviceProfile.getTenantId();
|
||||
|
||||
Consumer<Device> updateConsumer;
|
||||
if (deviceProfile.getFirmwareId() != null) {
|
||||
Firmware firmware = firmwareService.findFirmwareById(tenantId, deviceProfile.getFirmwareId());
|
||||
long ts = System.currentTimeMillis();
|
||||
updateConsumer = d -> update(d, firmware, ts);
|
||||
} else {
|
||||
updateConsumer = this::remove;
|
||||
}
|
||||
|
||||
PageLink pageLink = new PageLink(100);
|
||||
PageData<Device> pageData;
|
||||
do {
|
||||
//TODO: create a query which will return devices without firmware
|
||||
pageData = deviceService.findDevicesByTenantIdAndType(tenantId, deviceProfile.getName(), pageLink);
|
||||
|
||||
pageData.getData().stream().filter(d -> d.getFirmwareId() == null).forEach(updateConsumer);
|
||||
|
||||
if (pageData.hasNext()) {
|
||||
pageLink = pageLink.nextPageLink();
|
||||
}
|
||||
} while (pageData.hasNext());
|
||||
}
|
||||
|
||||
private void update(Device device, Firmware firmware, long ts) {
|
||||
TenantId tenantId = device.getTenantId();
|
||||
DeviceId deviceId = device.getId();
|
||||
|
||||
List<TsKvEntry> telemetry = new ArrayList<>();
|
||||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.TARGET_FIRMWARE_TITLE, firmware.getTitle())));
|
||||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.TARGET_FIRMWARE_VERSION, firmware.getVersion())));
|
||||
|
||||
telemetryService.saveAndNotify(tenantId, deviceId, telemetry, new FutureCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable Void tmp) {
|
||||
log.trace("[{}] Success save telemetry with target firmware for device!", deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
log.error("[{}] Failed to save telemetry with target firmware for device!", deviceId, t);
|
||||
}
|
||||
});
|
||||
|
||||
List<AttributeKvEntry> attributes = new ArrayList<>();
|
||||
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_TITLE, firmware.getTitle())));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_VERSION, firmware.getVersion())));
|
||||
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new LongDataEntry(FIRMWARE_SIZE, (long) firmware.getData().array().length)));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_CHECKSUM_ALGORITHM, firmware.getChecksumAlgorithm())));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_CHECKSUM, firmware.getChecksum())));
|
||||
telemetryService.saveAndNotify(tenantId, deviceId, DataConstants.SHARED_SCOPE, attributes, new FutureCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable Void tmp) {
|
||||
log.trace("[{}] Success save attributes with target firmware!", deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
log.error("[{}] Failed to save attributes with target firmware!", deviceId, t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void remove(Device device) {
|
||||
telemetryService.deleteAndNotify(device.getTenantId(), device.getId(), DataConstants.SHARED_SCOPE,
|
||||
Arrays.asList(FIRMWARE_TITLE, FIRMWARE_VERSION, FIRMWARE_SIZE, FIRMWARE_CHECKSUM_ALGORITHM, FIRMWARE_CHECKSUM),
|
||||
new FutureCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable Void tmp) {
|
||||
log.trace("[{}] Success remove target firmware attributes!", device.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
log.error("[{}] Failed to remove target firmware attributes!", device.getId(), t);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright © 2016-2021 The Thingsboard Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.thingsboard.server.service.firmware;
|
||||
|
||||
import org.thingsboard.server.common.data.Device;
|
||||
import org.thingsboard.server.common.data.DeviceProfile;
|
||||
|
||||
public interface FirmwareStateService {
|
||||
|
||||
void update(Device device, boolean created);
|
||||
|
||||
void update(DeviceProfile deviceProfile);
|
||||
|
||||
}
|
||||
@ -91,4 +91,19 @@ public class DataConstants {
|
||||
public static final String USERNAME = "username";
|
||||
public static final String PASSWORD = "password";
|
||||
|
||||
//firmware
|
||||
//telemetry
|
||||
public static final String CURRENT_FIRMWARE_TITLE = "cur_fw_title";
|
||||
public static final String CURRENT_FIRMWARE_VERSION = "cur_fw_version";
|
||||
public static final String TARGET_FIRMWARE_TITLE = "target_fw_title";
|
||||
public static final String TARGET_FIRMWARE_VERSION = "target_fw_version";
|
||||
public static final String CURRENT_FIRMWARE_STATE = "cur_fw_state";
|
||||
|
||||
//attributes
|
||||
//telemetry
|
||||
public static final String FIRMWARE_TITLE = "fw_title";
|
||||
public static final String FIRMWARE_VERSION = "fw_version";
|
||||
public static final String FIRMWARE_SIZE = "fw_size";
|
||||
public static final String FIRMWARE_CHECKSUM = "fw_checksum";
|
||||
public static final String FIRMWARE_CHECKSUM_ALGORITHM = "fw_checksum_algorithm";
|
||||
}
|
||||
|
||||
@ -114,7 +114,8 @@ public class BaseFirmwareService implements FirmwareService {
|
||||
log.trace("Executing findTenantFirmwaresByTenantIdAndHasData, tenantId [{}], hasData [{}] pageLink [{}]", tenantId, hasData, pageLink);
|
||||
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
|
||||
validatePageLink(pageLink);
|
||||
return firmwareInfoDao.findFirmwareInfoByTenantIdAndHasData(tenantId, hasData, pageLink); }
|
||||
return firmwareInfoDao.findFirmwareInfoByTenantIdAndHasData(tenantId, hasData, pageLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteFirmware(TenantId tenantId, FirmwareId firmwareId) {
|
||||
@ -211,7 +212,9 @@ public class BaseFirmwareService implements FirmwareService {
|
||||
throw new DataValidationException("Firmware data should be specified!");
|
||||
}
|
||||
|
||||
if (firmware.getChecksumAlgorithm() != null) {
|
||||
if (StringUtils.isEmpty(firmware.getChecksumAlgorithm())) {
|
||||
throw new DataValidationException("Firmware checksum algorithm should be specified!");
|
||||
}
|
||||
if (StringUtils.isEmpty(firmware.getChecksum())) {
|
||||
throw new DataValidationException("Firmware checksum should be specified!");
|
||||
}
|
||||
@ -237,7 +240,6 @@ public class BaseFirmwareService implements FirmwareService {
|
||||
throw new DataValidationException("Wrong firmware file!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateUpdate(TenantId tenantId, Firmware firmware) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user