icf300/src/main/java/guru/dead/icf320/MainController.java
2023-08-10 00:59:08 +03:00

287 lines
10 KiB
Java

package guru.dead.icf320;
import com.fazecast.jSerialComm.SerialPortTimeoutException;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import com.fazecast.jSerialComm.SerialPort;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.application.Platform;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextArea;
import javafx.stage.FileChooser;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.controlsfx.glyphfont.FontAwesome;
import org.controlsfx.glyphfont.GlyphFont;
import org.controlsfx.glyphfont.GlyphFontRegistry;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class MainController extends SerialController {
@FXML
public MenuItem cloneRawItem;
@FXML
private Label welcomeText;
@FXML
private Menu comPortMenu;
@FXML
private Menu settingsReadTime;
private MenuItem selectedReadTime;
private MenuItem selectedPortItem;
private InputStream inputStream;
@FXML
private TextArea outputArea;
private Stage stage;
FileChooser fileChooser = new FileChooser();
int readTime = 20;
private ScheduledExecutorService executor;
@FXML
private void initialize() {
fillComPortMenu();
fillSettingsReadTime();
outputArea.setEditable(false);
setOutputA(outputArea);
fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter("Icom files", "*.ICF")
);
}
public void setStage(Stage stage) {
this.stage = stage;
}
@FXML
private void onCloneRawItemClick(ActionEvent event) {
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("rawData-view.fxml")); // TODO: Make factory
Parent root = fxmlLoader.load();
RawDataController newController = fxmlLoader.getController();
newController.setSelectedPort(getSelectedPort());
newController.setOutputA(outputArea);
Stage newStage = new Stage();
newStage.setTitle("Send Raw Data");
newStage.initModality(Modality.APPLICATION_MODAL);
newStage.initStyle(StageStyle.UTILITY);
Scene newScene = new Scene(root, 580, 280);
newScene.getStylesheets().add(getClass().getResource("styles.css").toExternalForm());
newStage.setScene(newScene);
newStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
private void fillComPortMenu() {
comPortMenu.getItems().clear();
System.out.println("Filling COM port menu");
GlyphFont fontAwesome = GlyphFontRegistry.font("FontAwesome");
SerialPort[] portNames = SerialPort.getCommPorts();
MenuItem menuItemRefresh = new MenuItem("Refresh");
menuItemRefresh.setOnAction(event -> fillComPortMenu());
menuItemRefresh.setGraphic(fontAwesome.create(FontAwesome.Glyph.REFRESH));
comPortMenu.getItems().add(menuItemRefresh);
MenuItem menuItemClosePort = new MenuItem("Close Port");
menuItemClosePort.setOnAction(this::onCloseButtonClick);
menuItemClosePort.setGraphic(fontAwesome.create(FontAwesome.Glyph.POWER_OFF));
comPortMenu.getItems().add(menuItemClosePort);
for (SerialPort port : portNames) {
MenuItem menuItem = new MenuItem(port.getDescriptivePortName());
menuItem.setOnAction(event -> onPortMenuItemClick(event, port));
comPortMenu.getItems().add(menuItem);
}
}
private void fillSettingsReadTime() {
MenuItem menuItem = new MenuItem("20");
menuItem.setOnAction(event -> onReadTimeSet(event, 20));
settingsReadTime.getItems().add(menuItem);
menuItem = new MenuItem("50");
menuItem.setOnAction(event -> onReadTimeSet(event, 50));
settingsReadTime.getItems().add(menuItem);
menuItem = new MenuItem("100");
menuItem.setOnAction(event -> onReadTimeSet(event, 100));
settingsReadTime.getItems().add(menuItem);
menuItem = new MenuItem("250");
menuItem.setOnAction(event -> onReadTimeSet(event, 250));
settingsReadTime.getItems().add(menuItem);
menuItem = new MenuItem("500");
menuItem.setOnAction(event -> onReadTimeSet(event, 500));
settingsReadTime.getItems().add(menuItem);
}
private void onReadTimeSet(ActionEvent event, int time) {
if (selectedReadTime != null) {
selectedReadTime.getStyleClass().remove("menu-item-active");
selectedReadTime.setGraphic(null);
}
MenuItem clickedMenuItem = (MenuItem) event.getSource();
clickedMenuItem.getStyleClass().add("menu-item-active");
clickedMenuItem.setGraphic(GlyphFontRegistry.font("FontAwesome").create(FontAwesome.Glyph.CHECK));
selectedReadTime = clickedMenuItem;
readTime = time;
log("DEBUG", "Read Port time set: " + readTime + "\n");
}
private void onPortMenuItemClick(ActionEvent event, SerialPort port) {
setSelectedPort(port);
welcomeText.setText(getSelectedPort().getSystemPortName() + " " + getSelectedPort().getDescriptivePortName());
if (getSelectedPort().openPort()) {
log("INFO", "Port opened successfully.\n");
getSelectedPort().setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 100, 0);
inputStream = getSelectedPort().getInputStream();
executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(this::readDataFromPort, 0, readTime, TimeUnit.MILLISECONDS);
if (selectedPortItem != null) {
selectedPortItem.getStyleClass().remove("menu-item-active");
selectedPortItem.setGraphic(null);
}
MenuItem clickedMenuItem = (MenuItem) event.getSource();
clickedMenuItem.getStyleClass().add("menu-item-active");
clickedMenuItem.setGraphic(GlyphFontRegistry.font("FontAwesome").create(FontAwesome.Glyph.CHECK));
selectedPortItem = clickedMenuItem;
} else {
log("ERROR", "Failed to open port.\n");
if (selectedPortItem != null) {
selectedPortItem.getStyleClass().remove("menu-item-active");
selectedPortItem.setGraphic(null);
}
}
}
private void readDataFromPort() {
try {
byte[] buffer = new byte[4096];
int numBytes;
try {
numBytes = inputStream.read(buffer);
} catch (SerialPortTimeoutException e) {
return;
}
if (numBytes > 1) {
System.out.println("Read " + numBytes + " bytes.");
String receivedData = filterData(new String(buffer, 0, numBytes));
Platform.runLater(() -> {
outputArea.appendText(receivedData);
outputArea.appendText("\n");
});
}
} catch (Exception e) {
//e.printStackTrace();
log("ERROR", "Error occurred: " + e.getMessage() + "\n");
}
}
private String filterData(String string) {
string = string.replaceAll("[^\\x00-\\x7F]", "").replaceAll("Icom Inc.", "");
if (string.length() == 40) {
string = string.substring(0, string.length() - 2);
}
return string;
}
@FXML
protected void onExitClick(ActionEvent event) {
exitApplication();
}
public void exitApplication() {
System.out.println("Stage is closing!!");
if (getSelectedPort() != null && getSelectedPort().isOpen()) {
getSelectedPort().closePort();
welcomeText.setText("Select COM port");
}
if (executor != null && !executor.isShutdown()) {
executor.shutdown();
}
Platform.exit();
}
public void onCloseButtonClick(ActionEvent actionEvent) {
if (getSelectedPort() != null && getSelectedPort().isOpen()) {
getSelectedPort().closePort();
log("INFO", "Port closed!\n");
if (selectedPortItem != null) {
selectedPortItem.getStyleClass().remove("menu-item-active");
selectedPortItem.setGraphic(null);
}
welcomeText.setText("Select COM port");
} else {
log("DEBUG", "Port is already closed!\n");
}
if (executor != null && !executor.isShutdown()) {
executor.shutdown();
} else {
System.out.println("Executor is already shutdown!");
}
}
public void onClearButtonClick(ActionEvent actionEvent) {
outputArea.clear();
}
@FXML
public void cloneReadItem(ActionEvent actionEvent) {
if (getSelectedPort() == null || !getSelectedPort().isOpen()) {
log("ERROR", "Please select a valid COM port.\n");
return;
}
sendData("FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEEEEFE020550000FDFEFEEEEFFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEEEEFE0205500FEFEFEFEFEEEEFE020550000FD00FDFEFEEFEEE1205502007368697070696E67202020202020202049432D463331302023353220202020200000000F010200FDFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEEEEFE220550200FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEEEEFE220550200FDFDFEFEEFEE");
}
public void onOpenItemClick(ActionEvent actionEvent) {
File selectedFile = fileChooser.showOpenDialog(stage);
if(!selectedFile.canRead()) {
log("ERROR", "Cannot read file: " + selectedFile.getName() + "\n");
return;
}
try {
String fileContent = Files.readString(selectedFile.toPath());
outputArea.appendText(fileContent + "\n");
} catch (IOException e) {
log("ERROR", "Error occurred: " + e.getMessage() + "\n");
}
}
}