Init commit
This commit is contained in:
41
src/main/java/guru/dead/icf320/MainApplication.java
Normal file
41
src/main/java/guru/dead/icf320/MainApplication.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package guru.dead.icf320;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class MainApplication extends Application {
|
||||
|
||||
private MainController controller;
|
||||
|
||||
@Override
|
||||
public void start(Stage stage) throws IOException {
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(MainApplication.class.getResource("home-view.fxml"));
|
||||
Parent root = fxmlLoader.load();
|
||||
controller = fxmlLoader.getController();
|
||||
controller.setStage(stage);
|
||||
|
||||
Scene scene = new Scene(root, 725, 360);
|
||||
scene.getStylesheets().add(getClass().getResource("styles.css").toExternalForm());
|
||||
|
||||
stage.getIcons().add(new Image(MainApplication.class.getResource("icon.png").toExternalForm()));
|
||||
stage.setTitle("ICOM IC-F320");
|
||||
stage.setScene(scene);
|
||||
stage.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(){
|
||||
System.out.println("Stage is closing");
|
||||
controller.exitApplication();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
launch();
|
||||
}
|
||||
}
|
287
src/main/java/guru/dead/icf320/MainController.java
Normal file
287
src/main/java/guru/dead/icf320/MainController.java
Normal file
@@ -0,0 +1,287 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
26
src/main/java/guru/dead/icf320/RawDataController.java
Normal file
26
src/main/java/guru/dead/icf320/RawDataController.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package guru.dead.icf320;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.TextArea;
|
||||
|
||||
public class RawDataController extends SerialController {
|
||||
|
||||
@FXML
|
||||
private TextArea textInput;
|
||||
|
||||
public void onPushButtonClick(ActionEvent actionEvent) {
|
||||
if (getSelectedPort() == null || !getSelectedPort().isOpen()) {
|
||||
log("ERROR", "Please select a valid COM port.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
String inputData = textInput.getText();
|
||||
if (inputData.isEmpty()) {
|
||||
log("ERROR", "Please enter some data.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sendData(inputData);
|
||||
}
|
||||
}
|
57
src/main/java/guru/dead/icf320/SerialController.java
Normal file
57
src/main/java/guru/dead/icf320/SerialController.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package guru.dead.icf320;
|
||||
|
||||
import com.fazecast.jSerialComm.SerialPort;
|
||||
import javafx.scene.control.TextArea;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class SerialController {
|
||||
private OutputStream outputStream;
|
||||
private SerialPort selectedPort;
|
||||
|
||||
private TextArea outputA;
|
||||
|
||||
protected void sendData(String inputData) {
|
||||
try {
|
||||
if (selectedPort.isOpen()) {
|
||||
outputStream = selectedPort.getOutputStream();
|
||||
|
||||
byte[] binaryData = hexStringToByteArray(inputData);
|
||||
|
||||
outputStream.write(binaryData);
|
||||
|
||||
log("DEBUG", "Data sent: " + binaryData.length + "\n");
|
||||
} else {
|
||||
log("ERROR", "Port closed =(\n");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log("ERROR", "Error occurred: " + e.getMessage() + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] hexStringToByteArray(String hexString) {
|
||||
int len = hexString.length();
|
||||
byte[] data = new byte[(len + 1) / 2];
|
||||
for (int i = 0, j = 0; i < len; i += 2, j++) {
|
||||
data[j] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
|
||||
+ Character.digit(hexString.charAt(i + 1), 16));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public void log(String type, String message) {
|
||||
outputA.appendText("[" + type + "] " + message + "\n");
|
||||
}
|
||||
|
||||
public void setOutputA(TextArea outputA) {
|
||||
this.outputA = outputA;
|
||||
}
|
||||
|
||||
public void setSelectedPort(SerialPort selectedPort) {
|
||||
this.selectedPort = selectedPort;
|
||||
}
|
||||
public SerialPort getSelectedPort() {
|
||||
return selectedPort;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user