diff --git a/src/main/java/com/esp/espflow/entity/dto/EsptoolExecutableDto.java b/src/main/java/com/esp/espflow/entity/dto/EsptoolExecutableDto.java index 3a1783f..845446f 100644 --- a/src/main/java/com/esp/espflow/entity/dto/EsptoolExecutableDto.java +++ b/src/main/java/com/esp/espflow/entity/dto/EsptoolExecutableDto.java @@ -57,6 +57,8 @@ public static String displayAbsoluteEsptoolPathForCombo(final EsptoolExecutableD if(dtoParam.absolutePathEsptool.startsWith("/tmp")) { data.append("Bundled ".concat(dtoParam.absolutePathEsptool)); } else { + data.append(dtoParam.esptoolVersion); + data.append(" "); data.append(dtoParam.absolutePathEsptool); } return data.toString(); diff --git a/src/main/java/com/esp/espflow/service/EsptoolPathService.java b/src/main/java/com/esp/espflow/service/EsptoolPathService.java index 353ce24..7603ced 100644 --- a/src/main/java/com/esp/espflow/service/EsptoolPathService.java +++ b/src/main/java/com/esp/espflow/service/EsptoolPathService.java @@ -49,6 +49,33 @@ public String esptoolPath() { return esptoolPath; } + /** + * + * @param isBundle or custom executable esptool + * @param absolutePath + * + * @return A {@link String} with esptool bundle path + * + */ + public String esptoolPath(final String absolutePath, boolean isBundle) { + this.esptoolExecutableServiceImpl.findByAbsolutePathEsptoolAndIsBundle(absolutePath, isBundle) + .ifPresentOrElse(esptoolBundleDto -> { + if (esptoolBundleDto.isBundle()) { + this.esptoolPath = this.bundlePath(); + log.info("Loaded esptool.py bundle {}", esptoolPath); + } else { + this.esptoolPath = esptoolBundleDto.absolutePathEsptool(); + this.makeExecutable(esptoolPath); + log.info("Loaded custom esptool.py from {}", esptoolBundleDto.absolutePathEsptool()); + } + }, () -> { + this.esptoolPath = this.bundlePath(); + log.info("Entity is not present, Loaded esptool.py bundle {}", esptoolPath); + }); + + return esptoolPath; + } + private String bundlePath() { this.esptoolPath = JAVA_IO_TEMPORAL_DIR_OS.concat(ESPTOOL_BUNDLE_DIR); switch (GetOsName.getOsName()) { diff --git a/src/main/java/com/esp/espflow/service/EsptoolService.java b/src/main/java/com/esp/espflow/service/EsptoolService.java index 01818e3..88badc0 100644 --- a/src/main/java/com/esp/espflow/service/EsptoolService.java +++ b/src/main/java/com/esp/espflow/service/EsptoolService.java @@ -152,6 +152,21 @@ public Flux showEsptoolVersion() { .map(this::processLineEsptoolVersion); } + /** + * Check if esptool is installed by executing the command esptool.py version for the current system. + * + * @param absolutePath + * @param isBundle or custom executable esptool + * + * @return A {@link Flux } + */ + public Flux showEsptoolVersion(String absolutePath, boolean isBundle) { + final String[] commands = {esptoolPathService.esptoolPath(absolutePath, isBundle), VERSION}; + return this.commandService.processInputStreamLineByLine(commands) + .take(FIRST_LINE_TO_CHECK_IF_IT_EXISTS) + .map(this::processLineEsptoolVersion); + } + /** * This processes the line that has the esptool.py v and thus validates that the esptool.py is correctly installed. * diff --git a/src/main/java/com/esp/espflow/service/respository/EsptoolExecutableRepository.java b/src/main/java/com/esp/espflow/service/respository/EsptoolExecutableRepository.java index 4504f51..1f96a91 100644 --- a/src/main/java/com/esp/espflow/service/respository/EsptoolExecutableRepository.java +++ b/src/main/java/com/esp/espflow/service/respository/EsptoolExecutableRepository.java @@ -12,12 +12,20 @@ @Repository public interface EsptoolExecutableRepository extends JpaRepository { + @Query("SELECT entity " + + "FROM EsptoolExecutableEntity entity " + + "WHERE entity.esptoolVersion = :esptoolVersion " + + "AND entity.isBundle = :isBundle") + Optional findByEsptoolVersionWithBundle(@Param("esptoolVersion")String esptoolVersion, + @Param("isBundle") boolean isBundle); + @Query("SELECT entity " + "FROM EsptoolExecutableEntity entity " + "WHERE entity.absolutePathEsptool = :absolutePathEsptool " + - "AND entity.esptoolVersion = :esptoolVersion") - Optional findByAbsolutePathEsptoolAndEsptoolVersion(@Param("absolutePathEsptool") String absolutePathEsptool, - @Param("esptoolVersion") String esptoolVersion); + "AND entity.isBundle = :isBundle " + + "AND entity.esptoolVersion = ''") + Optional findByAbsolutePathEsptoolAndIsBundle(@Param("absolutePathEsptool") String absolutePathEsptool, + @Param("isBundle") boolean isBundle); @Query("SELECT entity " + "FROM EsptoolExecutableEntity entity " + diff --git a/src/main/java/com/esp/espflow/service/respository/impl/EsptoolExecutableServiceImpl.java b/src/main/java/com/esp/espflow/service/respository/impl/EsptoolExecutableServiceImpl.java index 20dbc8c..8c9bfab 100644 --- a/src/main/java/com/esp/espflow/service/respository/impl/EsptoolExecutableServiceImpl.java +++ b/src/main/java/com/esp/espflow/service/respository/impl/EsptoolExecutableServiceImpl.java @@ -1,5 +1,6 @@ package com.esp.espflow.service.respository.impl; +import com.esp.espflow.entity.EsptoolExecutableEntity; import com.esp.espflow.entity.dto.EsptoolExecutableDto; import com.esp.espflow.mappers.EsptoolBundleMapper; import com.esp.espflow.service.respository.EsptoolExecutableRepository; @@ -26,10 +27,11 @@ public class EsptoolExecutableServiceImpl { * * @param esptoolExecutableDto to save */ - public void save(EsptoolExecutableDto esptoolExecutableDto) { + public EsptoolExecutableDto save(EsptoolExecutableDto esptoolExecutableDto) { var mappedEntity = EsptoolBundleMapper.INSTANCE.dtoToEntity(esptoolExecutableDto); - this.esptoolExecutableRepository.save(mappedEntity); - log.info("Entity saved EsptoolExecutableEntity: {}", mappedEntity); + EsptoolExecutableEntity entitySaved = this.esptoolExecutableRepository.save(mappedEntity); + log.info("Entity saved EsptoolExecutableEntity: {}", entitySaved); + return EsptoolBundleMapper.INSTANCE.entityToDto(entitySaved); } public Optional findById(Long id) { @@ -37,6 +39,11 @@ public Optional findById(Long id) { .map(EsptoolBundleMapper.INSTANCE::entityToDto); } + public Optional findByEsptoolVersionWithBundle(String esptoolVersion, boolean isBundle) { + return this.esptoolExecutableRepository.findByEsptoolVersionWithBundle(esptoolVersion, isBundle) + .map(EsptoolBundleMapper.INSTANCE::entityToDto); + } + @Transactional public void updateAllSelectedToFalseExcept(final long id) { this.esptoolExecutableRepository.updateAllSelectedToFalseExcept(id); @@ -47,8 +54,12 @@ public Optional findByIsSelectedToTrue() { .map(EsptoolBundleMapper.INSTANCE::entityToDto); } - public Optional findByAbsolutePathEsptoolAndEsptoolVersion(String absolutePathEsptool, String esptoolVersion) { - return this.esptoolExecutableRepository.findByAbsolutePathEsptoolAndEsptoolVersion(absolutePathEsptool, esptoolVersion) + public void deleteById(final long id) { + this.esptoolExecutableRepository.deleteById(id); + } + + public Optional findByAbsolutePathEsptoolAndIsBundle(String absolutePathEsptool, boolean isBundle) { + return this.esptoolExecutableRepository.findByAbsolutePathEsptoolAndIsBundle(absolutePathEsptool, isBundle) .map(EsptoolBundleMapper.INSTANCE::entityToDto); } diff --git a/src/main/java/com/esp/espflow/util/EspFlowConstants.java b/src/main/java/com/esp/espflow/util/EspFlowConstants.java index 23b237e..ea4e39a 100644 --- a/src/main/java/com/esp/espflow/util/EspFlowConstants.java +++ b/src/main/java/com/esp/espflow/util/EspFlowConstants.java @@ -108,6 +108,7 @@ public class EspFlowConstants { public static final String STEP2 = "step2"; public static final String STEP3 = "step3"; public static final String SETTINGS = "settings"; + public static final String VAR_LUMO_PRIMARY_COLOR_10_PCT = "var(--lumo-primary-color-10pct)"; } diff --git a/src/main/java/com/esp/espflow/util/MakeExecutable.java b/src/main/java/com/esp/espflow/util/MakeExecutable.java index 407b406..b4be447 100644 --- a/src/main/java/com/esp/espflow/util/MakeExecutable.java +++ b/src/main/java/com/esp/espflow/util/MakeExecutable.java @@ -25,14 +25,11 @@ default boolean makeExecutable(final Path esptoolPath) { Files.setPosixFilePermissions(esptoolPath, permissions); if (Files.isExecutable(esptoolPath.toAbsolutePath())) { - //log.info("esptool bundle is executable"); return true; } else { - //log.info("Error when setting permissions in the esptool executable {}", esptoolPath); return false; } } catch (IOException ex) { - //log.info("Error makeTheBundleExecutable() {}", ex.getMessage()); return false; } } diff --git a/src/main/java/com/esp/espflow/views/settings/SettingsEsptoolHomePathContent.java b/src/main/java/com/esp/espflow/views/settings/SettingsEsptoolHomePathContent.java index c9e63f6..e0008f2 100644 --- a/src/main/java/com/esp/espflow/views/settings/SettingsEsptoolHomePathContent.java +++ b/src/main/java/com/esp/espflow/views/settings/SettingsEsptoolHomePathContent.java @@ -24,16 +24,21 @@ import com.vaadin.flow.component.upload.Upload; import com.vaadin.flow.component.upload.UploadI18N; import com.vaadin.flow.component.upload.receivers.FileBuffer; +import com.vaadin.flow.server.Command; import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.annotation.UIScope; import com.vaadin.flow.theme.lumo.LumoUtility; import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.StringUtils; import org.vaadin.olli.ClipboardHelper; import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.time.Duration; import java.util.Arrays; import java.util.Objects; @@ -46,7 +51,8 @@ import static com.esp.espflow.util.EspFlowConstants.JAVA_IO_USER_HOME_DIR_OS; /** - * - No guardar misma entidad con el mismo path, casi, falta aƱadir otro parametro + * - No guardar misma entidad con el mismo path con misma version + * - Obtener la version del esptool del executable cargado * * @author rub'n */ @@ -67,6 +73,7 @@ public class SettingsEsptoolHomePathContent extends Layout implements CreateCust private final SvgIcon copySvgButton = SvgFactory.createCopyButtonFromSvg(); private final ClipboardHelper clipboardHelper = new ClipboardHelper(); private final Sinks.Many publishEsptoolVersionEvent; + private String overlay; @PostConstruct public void init() { @@ -84,40 +91,57 @@ private void initListeners() { final String fileName = JAVA_IO_USER_HOME_DIR_OS.concat(CUSTOM_ESPTOOL).concat(event.getFileName()); this.createCustomDirectory(buffer, JAVA_IO_USER_HOME_DIR_OS.concat(CUSTOM_ESPTOOL), event.getFileName()); log.info("Esptool custom path addSucceededListener {}", fileName); - - //TODO obtener la version del estool.py subida - this.esptoolService.showEsptoolVersion() + final EsptoolExecutableDto esptoolBundleDto = EsptoolExecutableDto.builder() + .name(ESPTOOL) + .absolutePathEsptool(fileName) + .isBundle(false) + .esptoolVersion(StringUtils.EMPTY) + .isSelected(false) + .build(); + EsptoolExecutableDto savedEsptoolBundleDto = this.esptoolExecutableServiceImpl.save(esptoolBundleDto); + this.esptoolService.showEsptoolVersion(fileName, false) .subscribe(esptoolVersion -> { - this.esptoolExecutableServiceImpl.findByAbsolutePathEsptoolAndEsptoolVersion(fileName, esptoolVersion) - .ifPresentOrElse(entityPresent -> { - this.comboBoxEsptoolHome.getUI().ifPresent(ui -> { - ui.access(() -> { - ConfirmDialogBuilder.showInformation("This version already exists " + fileName); + if (!esptoolVersion.contains(ESPTOOL_PY_NOT_FOUND)) { + this.esptoolExecutableServiceImpl.findByEsptoolVersionWithBundle(esptoolVersion, false) + .ifPresentOrElse(present -> { + this.executeCommandFromCombo(() -> { + ConfirmDialogBuilder.showInformation("The version " + esptoolVersion + " exists"); }); - }); - }, () -> { - final EsptoolExecutableDto esptoolBundleDto = EsptoolExecutableDto.builder() - .id(null) - .name(ESPTOOL) - .absolutePathEsptool(fileName) - .isBundle(false) - .esptoolVersion(esptoolVersion) - .isSelected(false) - .build(); - this.esptoolExecutableServiceImpl.save(esptoolBundleDto); - this.comboBoxEsptoolHome.getUI().ifPresent(ui -> { - ui.access(() -> { + }, () -> { + this.executeCommandFromCombo(() -> { + final EsptoolExecutableDto entityToUpdate = EsptoolExecutableDto.builder() + .id(savedEsptoolBundleDto.id()) + .name(ESPTOOL) + .absolutePathEsptool(esptoolBundleDto.absolutePathEsptool()) + .isBundle(false) + .esptoolVersion(esptoolVersion) + .isSelected(false) + .build(); + this.esptoolExecutableServiceImpl.save(entityToUpdate); this.comboBoxEsptoolHome.setItems(this.esptoolExecutableServiceImpl.findAll()); + int overlayLength = esptoolVersion.concat(esptoolBundleDto.absolutePathEsptool()).length(); + this.overlay = overlayLength + "px"; + //FIXME recalculate the width more precisely + this.comboBoxEsptoolHome.getStyle().set("--vaadin-combo-box-overlay-width", "400px"); }); }); - }); - }); - + } else { + this.executeCommandFromCombo(() -> { + ConfirmDialogBuilder.showWarning(event.getFileName() + ", It is not a valid esptool executable"); + this.esptoolExecutableServiceImpl.deleteById(savedEsptoolBundleDto.id()); + this.comboBoxEsptoolHome.setItems(this.esptoolExecutableServiceImpl.findAll()); + try { + Files.deleteIfExists(Path.of(savedEsptoolBundleDto.absolutePathEsptool())); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } + }); //this.clipboardHelper.setContent(comboBoxEsptoolHome.getValue()); //this.copyButton.setTooltipText(comboBoxEsptoolHome.getValue()); }); - this.clipboardHelper.wrap(this.copyButton); this.copyButton.setIcon(this.copySvgButton); this.copyButton.addClickListener(event -> { @@ -136,7 +160,8 @@ private void initListeners() { this.comboBoxEsptoolHome.setPrefixComponent(SvgFactory.createIconFromSvg(EXECUTABLE_ICON_SVG, "20px", null)); this.comboBoxEsptoolHome.setItemLabelGenerator(EsptoolExecutableDto::displayAbsoluteEsptoolPathForCombo); this.comboBoxEsptoolHome.setRenderer(EsptoolExecutableDto.rendererExecutableIcon()); - this.comboBoxEsptoolHome.getStyle().set("--vaadin-combo-box-overlay-width", "350px"); + //this.comboBoxEsptoolHome.getStyle().set("--vaadin-input-field-border-width", "1px"); + //this.comboBoxEsptoolHome.getStyle().set("--vaadin-input-field-border-color", VAR_LUMO_PRIMARY_COLOR_10_PCT); this.comboBoxEsptoolHome.addValueChangeListener(esptoolDtoItem -> { if (Objects.nonNull(esptoolDtoItem.getValue())) { final EsptoolExecutableDto item = esptoolDtoItem.getValue(); @@ -168,10 +193,8 @@ private void initListeners() { .build(); this.esptoolExecutableServiceImpl.save(updatedEntity); this.publishEsptoolVersionEvent.tryEmitNext(new EsptoolVersionEvent(updatedEntityAgain.esptoolVersion())); - this.comboBoxEsptoolHome.getUI().ifPresent(ui -> { - ui.access(() -> { - this.comboBoxEsptoolHome.setHelperText(updatedEntityAgain.esptoolVersion()); - }); + this.executeCommandFromCombo(() -> { + this.comboBoxEsptoolHome.setHelperText(updatedEntityAgain.esptoolVersion()); }); }); }); @@ -179,6 +202,17 @@ private void initListeners() { }); } + /** + * Simple utility + * + * @param command + */ + public void executeCommandFromCombo(Command command) { + this.comboBoxEsptoolHome.getUI().ifPresent(ui -> { + ui.access(command); + }); + } + /** * @return A {@link Layout} */ @@ -239,7 +273,6 @@ public void configureUploadButton() { } /** - * * @param comboBoxEsptoolPath */ private void setEsptoolPyVersion(UI ui, ComboBox comboBoxEsptoolPath) { @@ -263,6 +296,7 @@ private void setEsptoolPyVersion(UI ui, ComboBox comboBoxE ui.access(() -> { publishEsptoolVersionEvent.tryEmitNext(new EsptoolVersionEvent(espToolVersion)); this.comboBoxEsptoolHome.setItems(this.esptoolExecutableServiceImpl.findAll()); + this.comboBoxEsptoolHome.getStyle().set("--vaadin-combo-box-overlay-width", overlay); this.esptoolExecutableServiceImpl.findByIsSelectedToTrue() .ifPresent(dtoIfPresent -> { comboBoxEsptoolPath.setValue(dtoIfPresent);