org.bidib.wizard.server.controllers.firmware.FirmwareUpdateController Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bidibwizard-server Show documentation
Show all versions of bidibwizard-server Show documentation
jBiDiB BiDiB Wizard Server POM
package org.bidib.wizard.server.controllers.firmware;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.apache.commons.lang3.StringUtils;
import org.bidib.api.json.types.NodeAddress;
import org.bidib.api.json.types.NodeInfo;
import org.bidib.api.json.types.ProcessingStatusType;
import org.bidib.api.json.types.SystemError;
import org.bidib.api.json.types.firmware.DeviceNodeType;
import org.bidib.api.json.types.firmware.FirmwareNodeUpdate;
import org.bidib.api.json.types.firmware.FirmwareUpdateProgressInfo;
import org.bidib.api.json.types.firmware.FirmwareUpdateProgressInfo.SimpleFirmwareUpdateStatus;
import org.bidib.api.json.types.firmware.FirmwareVersionInfo;
import org.bidib.api.json.types.firmware.NodeFirmware;
import org.bidib.api.json.types.firmware.NodeFirmwareDetails;
import org.bidib.wizard.api.locale.Resources;
import org.bidib.wizard.api.model.NodeInterface;
import org.bidib.wizard.api.model.NodeProvider;
import org.bidib.wizard.api.model.connection.BidibConnection;
import org.bidib.wizard.api.notification.FirmwareUpdateStatus;
import org.bidib.wizard.api.notification.FirmwareUpdateStatus.FirmwareUpdateStatusAction;
import org.bidib.wizard.common.exception.ConnectionException;
import org.bidib.wizard.core.model.connection.ConnectionRegistry;
import org.bidib.wizard.core.service.FirmwareUpdateService;
import org.bidib.wizard.core.service.NodeFirmwareUpdateService;
import org.bidib.wizard.server.aspect.LogExecutionTime;
import org.bidib.wizard.server.config.StompDestinations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.handler.annotation.MessageExceptionHandler;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.annotation.SendToUser;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.reactivex.rxjava3.subjects.SingleSubject;
@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/api/firmware")
public class FirmwareUpdateController /* implements FirmwareUpdateStatusPublisher */ {
private static final Logger LOGGER = LoggerFactory.getLogger(FirmwareUpdateController.class);
@Autowired
private FirmwareUpdateService firmwareUpdateService;
@Autowired
private ConnectionRegistry connectionRegistry;
// The SimpMessagingTemplate is used to send Stomp over WebSocket messages.
@Autowired
private SimpMessagingTemplate messagingTemplate;
public FirmwareUpdateController() {
}
private BidibConnection findConnection(final String connectionId) {
BidibConnection connection = connectionRegistry.getConnection(connectionId);
if (connection == null) {
throw new ConnectionException("No connection available with id: " + connectionId);
}
LOGGER.debug("Found connection: {}", connection);
return connection;
}
@PostConstruct
public void initialize() {
LOGGER.info("Initialize the FirmwareUpdateController.");
}
@GetMapping(path = "/availableFirmware")
public ResponseEntity getAvailableFirmware() {
LOGGER.debug("Get the available firmware.");
List availableFirmware = firmwareUpdateService.queryAvailableFirmware();
return new ResponseEntity<>(availableFirmware.toArray(new FirmwareVersionInfo[0]), HttpStatus.OK);
}
@MessageMapping("/firmware/nodes")
@SendToUser(destinations = StompDestinations.FIRMWARE_NODES_DESTINATION, broadcast = false)
@LogExecutionTime
public FirmwareVersionInfo[] msgGetAvailableFirmware(String text) {
LOGGER.info("Get the available firmware.");
List availableFirmware = firmwareUpdateService.queryAvailableFirmware();
return availableFirmware.toArray(new FirmwareVersionInfo[0]);
}
@MessageMapping("/firmware/details")
@SendToUser(destinations = StompDestinations.FIRMWARE_DETAILS_DESTINATION, broadcast = false)
@LogExecutionTime
public NodeFirmware msgGetFirmwareDetails(NodeFirmwareDetails details) {
int vendorId = details.getManufacturerId();
int productId = details.getProductId();
String version = details.getVersion();
LOGGER
.info("Get the firmware details, vendorId: {}, productId: {}, version: {}.", vendorId, productId, version);
NodeFirmware nodeFirmware = firmwareUpdateService.getFirmwareDetails(vendorId, productId, version);
return nodeFirmware;
}
@MessageMapping("/firmware/node/update")
@SendToUser(destinations = StompDestinations.FIRMWARE_UPDATE_PROGRESS_DESTINATION, broadcast = false)
@LogExecutionTime
public FirmwareUpdateProgressInfo msgFirmwareNodeUpdate(Principal principal, FirmwareNodeUpdate nodeUpdate) {
LOGGER.info("Update the node: {}, principal: {}", nodeUpdate, principal);
String destinationQualifier = principal.getName();
FirmwareVersionInfo version = nodeUpdate.getVersion();
final NodeInfo ni = nodeUpdate.getNode();
long uniqueId = Long.parseLong(ni.getUniqueId());
String connectionId = nodeUpdate.getConnectionId();
// find the matching node provider
NodeProvider nodeProvider = findConnection(connectionId).getNodeProvider();
FirmwareUpdateProgressInfo statusInfo = new FirmwareUpdateProgressInfo();
statusInfo.setConnectionId(connectionId);
statusInfo.setNode(ni);
List nodesList = new ArrayList<>();
NodeInterface node = nodeProvider.findNodeByUniqueId(uniqueId);
if (node == null) {
LOGGER.warn("The delivered node is not registered. Abort update.");
statusInfo.setTotal(100);
statusInfo.setProgress(0);
statusInfo.setStatus(SimpleFirmwareUpdateStatus.FAILED);
statusInfo
.setMsgKey(Resources.prepareResourceKey(NodeFirmwareUpdateService.class, "status.node-not-found"));
return statusInfo;
}
nodesList.add(node);
// get the selected firmware information
DeviceNodeType deviceNode = nodeUpdate.getDeviceNode();
if (deviceNode == null) {
LOGGER.warn("No device node delivered. Abort update.");
statusInfo.setTotal(100);
statusInfo.setProgress(0);
statusInfo.setStatus(SimpleFirmwareUpdateStatus.FAILED);
statusInfo
.setMsgKey(Resources.prepareResourceKey(NodeFirmwareUpdateService.class, "status.device-node-missing"));
return statusInfo;
}
final SingleSubject subjectFinished = SingleSubject.create();
subjectFinished.subscribe(success -> {
LOGGER.info("Firmware update finished, success: {}", success);
}, ex -> {
LOGGER.warn("Perform firmware update failed.", ex);
});
firmwareUpdateService
.updateFirmware(ConnectionRegistry.CONNECTION_ID_MAIN, nodeUpdate.getFirmwarePath(), destinationQualifier,
version, deviceNode, nodesList, subjectFinished);
statusInfo.setNode(ni);
statusInfo.setProgress(1);
statusInfo.setTotal(100);
statusInfo.setStatus(SimpleFirmwareUpdateStatus.RUNNING);
return statusInfo;
}
@MessageExceptionHandler
public String handleException(Throwable exception) {
LOGGER.error("Error detected: ", exception);
final SystemError se = new SystemError(exception.getMessage(), null, LocalDateTime.now(), null);
messagingTemplate.convertAndSend(StompDestinations.SYSTEM_ERROR_DESTINATION, se);
return exception.getMessage();
}
private void publishProgress(
String connectionId, String destinationQualifier, String address, Long uniqueId, Integer progress,
FirmwareUpdateStatusAction firmwareUpdateStatusAction, String msgKey) {
LOGGER
.info("Publish progress, destinationQualifier: {}, address: {}, uniqueId: {}, progress: {}, msgKey: {}",
destinationQualifier, address, uniqueId, progress, msgKey);
String destination = StompDestinations.FIRMWARE_UPDATE_PROGRESS_DESTINATION;
FirmwareUpdateProgressInfo progressInfo = new FirmwareUpdateProgressInfo();
progressInfo.setConnectionId(connectionId);
if (uniqueId != null) {
progressInfo.setNode(new NodeAddress().withUniqueId(uniqueId.toString()).withAddress(address));
}
if (progress != null) {
progressInfo.setProgress(progress);
}
if (firmwareUpdateStatusAction != null) {
progressInfo.setStatus(SimpleFirmwareUpdateStatus.valueOf(firmwareUpdateStatusAction.name()));
}
progressInfo.setMsgKey(msgKey);
messagingTemplate.convertAndSendToUser(destinationQualifier, destination, progressInfo);
}
private void publishStatus(String destinationQualifier, Long uniqueId, ProcessingStatusType processingStatus) {
LOGGER
.info("Publish status, destinationQualifier: {}, uniqueId: {}, processingStatus: {}", destinationQualifier,
uniqueId, processingStatus);
String destination = StompDestinations.FIRMWARE_UPDATE_STATE_DESTINATION;
messagingTemplate.convertAndSendToUser(destinationQualifier, destination, processingStatus);
}
private void publishProgress(String destinationQualifier, Long uniqueId, FirmwareUpdateProgressInfo progressInfo) {
LOGGER
.info("Publish progress, destinationQualifier: {}, uniqueId: {}, progressInfo: {}", destinationQualifier,
uniqueId, progressInfo);
String destination = StompDestinations.FIRMWARE_UPDATE_PROGRESS_DESTINATION;
messagingTemplate.convertAndSendToUser(destinationQualifier, destination, progressInfo);
}
@EventListener
public void eventHandler(final FirmwareUpdateStatus firmwareUpdateStatus) {
LOGGER.info("Handle the firmwareUpdateStatus event: {}", firmwareUpdateStatus);
if (StringUtils.isNotEmpty(firmwareUpdateStatus.getConnectionId())) {
publishProgress(firmwareUpdateStatus.getConnectionId(), firmwareUpdateStatus.getDestinationQualifier(),
firmwareUpdateStatus.getAddress(), firmwareUpdateStatus.getUniqueId(),
firmwareUpdateStatus.getProgress(), firmwareUpdateStatus.getFirmwareUpdateStatusAction(),
firmwareUpdateStatus.getMsgKey());
}
else if (firmwareUpdateStatus.getProcessingStatus() != null) {
publishStatus(firmwareUpdateStatus.getDestinationQualifier(), firmwareUpdateStatus.getUniqueId(),
firmwareUpdateStatus.getProcessingStatus());
}
else if (firmwareUpdateStatus.getProgressInfo() != null) {
publishProgress(firmwareUpdateStatus.getDestinationQualifier(), firmwareUpdateStatus.getUniqueId(),
firmwareUpdateStatus.getProgressInfo());
}
}
}