Windows-Client mit funktionierender Fyne-GUI und Rotor-Startcode
This commit is contained in:
parent
c9e3ba052a
commit
3a85b17422
3 changed files with 134 additions and 29 deletions
|
|
@ -23,10 +23,11 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"image/color"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/app"
|
"fyne.io/fyne/v2/app"
|
||||||
"fyne.io/fyne/v2/theme"
|
"fyne.io/fyne/v2/theme"
|
||||||
"image/color"
|
|
||||||
|
|
||||||
"git.lang-dieter.de/rs2322tcp/internal/gui"
|
"git.lang-dieter.de/rs2322tcp/internal/gui"
|
||||||
"git.lang-dieter.de/rs2322tcp/internal/version"
|
"git.lang-dieter.de/rs2322tcp/internal/version"
|
||||||
|
|
@ -113,11 +114,6 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Das technische Client-System wird nach dem Erzeugen des Fensters
|
|
||||||
// asynchron gestartet. Dadurch bleibt die GUI auch während des
|
|
||||||
// Verbindungsaufbaus sofort sichtbar und bedienbar.
|
|
||||||
guiApplication.Start()
|
|
||||||
|
|
||||||
// SetOnClosed gehört zum Fyne-Fenster, nicht zur Fyne-Anwendung.
|
// SetOnClosed gehört zum Fyne-Fenster, nicht zur Fyne-Anwendung.
|
||||||
//
|
//
|
||||||
// Beim Schließen des Hauptfensters wird die technische Client-
|
// Beim Schließen des Hauptfensters wird die technische Client-
|
||||||
|
|
@ -129,6 +125,16 @@ func main() {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// ShowAndRun zeigt das Fenster und startet den Fyne-Eventloop.
|
// Zuerst das GUI-Fenster erzeugen und anzeigen.
|
||||||
guiApplication.ShowAndRun()
|
//
|
||||||
}
|
// Dadurch wird ein möglicher Fehler beim Start von Fyne/GLFW erkannt,
|
||||||
|
// bevor die technische Client-Kommunikation gestartet wird.
|
||||||
|
guiApplication.Window().Show()
|
||||||
|
|
||||||
|
// Erst nachdem das Fenster erfolgreich erzeugt wurde, wird das
|
||||||
|
// technische Client-System asynchron gestartet.
|
||||||
|
guiApplication.Start()
|
||||||
|
|
||||||
|
// Den Fyne-Eventloop starten.
|
||||||
|
application.Run()
|
||||||
|
}
|
||||||
|
|
@ -11,8 +11,8 @@
|
||||||
* Beschreibung:
|
* Beschreibung:
|
||||||
* Windows-spezifische Erzeugung eines verwalteten virtuellen rs2322tcp-Ports.
|
* Windows-spezifische Erzeugung eines verwalteten virtuellen rs2322tcp-Ports.
|
||||||
*
|
*
|
||||||
* Der konfigurierte virtuelle COM-Port wird über die bereits vorhandene
|
* Der konfigurierte virtuelle COM-Port wird einmal geöffnet und anschließend
|
||||||
* serielle Infrastruktur geöffnet.
|
* über dasselbe Handle für Lese- und Schreiboperationen verwendet.
|
||||||
* ============================================================================
|
* ============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -36,6 +36,9 @@ import (
|
||||||
// The visible COM port is provided by the platform-specific PortPath()
|
// The visible COM port is provided by the platform-specific PortPath()
|
||||||
// implementation. The actual COM-port pair configuration is managed
|
// implementation. The actual COM-port pair configuration is managed
|
||||||
// externally by the Windows virtual COM-port driver.
|
// externally by the Windows virtual COM-port driver.
|
||||||
|
//
|
||||||
|
// The COM port is opened exactly once. The resulting handle is used for
|
||||||
|
// parallel read and write operations.
|
||||||
func openVirtualPort(
|
func openVirtualPort(
|
||||||
manager *VirtualPortManager,
|
manager *VirtualPortManager,
|
||||||
number int,
|
number int,
|
||||||
|
|
@ -59,7 +62,7 @@ func openVirtualPort(
|
||||||
StopBits: bugserial.OneStopBit,
|
StopBits: bugserial.OneStopBit,
|
||||||
}
|
}
|
||||||
|
|
||||||
serial, err := bugserial.Open(portPath, mode)
|
port, err := bugserial.Open(portPath, mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
"open virtual serial port %s: %w",
|
"open virtual serial port %s: %w",
|
||||||
|
|
@ -71,7 +74,7 @@ func openVirtualPort(
|
||||||
virtualPort := NewVirtualPort(
|
virtualPort := NewVirtualPort(
|
||||||
portPath,
|
portPath,
|
||||||
&windowsSerial{
|
&windowsSerial{
|
||||||
port: serial,
|
port: port,
|
||||||
path: portPath,
|
path: portPath,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,9 @@
|
||||||
* Windows-spezifische Implementierung der virtuellen seriellen Schnittstelle
|
* Windows-spezifische Implementierung der virtuellen seriellen Schnittstelle
|
||||||
* über go.bug.st/serial.
|
* über go.bug.st/serial.
|
||||||
*
|
*
|
||||||
* Der konfigurierte COM-Port wird direkt geöffnet. Die Zuordnung eines
|
* Ein COM-Port wird unter Windows nur einmal geöffnet. Dasselbe Handle wird
|
||||||
* virtuellen COM-Port-Paares erfolgt außerhalb des rs2322tcp-Clients.
|
* parallel für Lese- und Schreiboperationen verwendet. Damit kann eine
|
||||||
|
* Goroutine blockierend lesen, während eine andere Goroutine Daten schreibt.
|
||||||
* ============================================================================
|
* ============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -30,9 +31,11 @@ import (
|
||||||
// windowsSerial
|
// windowsSerial
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// windowsSerial implements VirtualSerial using a Windows COM port.
|
// windowsSerial implements VirtualSerial using one Windows COM-port handle
|
||||||
|
// for both reading and writing.
|
||||||
type windowsSerial struct {
|
type windowsSerial struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
|
||||||
port bugserial.Port
|
port bugserial.Port
|
||||||
path string
|
path string
|
||||||
}
|
}
|
||||||
|
|
@ -51,10 +54,10 @@ func (p *windowsSerial) Path() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Read / Write
|
// Read
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Read reads raw bytes from the COM port.
|
// Read reads raw bytes from the Windows COM-port handle.
|
||||||
func (p *windowsSerial) Read(b []byte) (int, error) {
|
func (p *windowsSerial) Read(b []byte) (int, error) {
|
||||||
if p == nil {
|
if p == nil {
|
||||||
return 0, fmt.Errorf("virtual serial port is nil")
|
return 0, fmt.Errorf("virtual serial port is nil")
|
||||||
|
|
@ -62,16 +65,41 @@ func (p *windowsSerial) Read(b []byte) (int, error) {
|
||||||
|
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
port := p.port
|
port := p.port
|
||||||
|
path := p.path
|
||||||
p.mu.Unlock()
|
p.mu.Unlock()
|
||||||
|
|
||||||
if port == nil {
|
if port == nil {
|
||||||
return 0, fmt.Errorf("virtual serial port is closed")
|
return 0, fmt.Errorf("virtual serial port is closed")
|
||||||
}
|
}
|
||||||
|
|
||||||
return port.Read(b)
|
n, err := port.Read(b)
|
||||||
|
|
||||||
|
if n > 0 {
|
||||||
|
fmt.Printf(
|
||||||
|
"WINDOWS SERIAL RX [%s]: %d Bytes\n% X\n",
|
||||||
|
path,
|
||||||
|
n,
|
||||||
|
b[:n],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(
|
||||||
|
"WINDOWS SERIAL RX FEHLER [%s]: nach %d Bytes: %v\n",
|
||||||
|
path,
|
||||||
|
n,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes raw bytes to the COM port.
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Write
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Write writes raw bytes to the Windows COM-port handle.
|
||||||
func (p *windowsSerial) Write(b []byte) (int, error) {
|
func (p *windowsSerial) Write(b []byte) (int, error) {
|
||||||
if p == nil {
|
if p == nil {
|
||||||
return 0, fmt.Errorf("virtual serial port is nil")
|
return 0, fmt.Errorf("virtual serial port is nil")
|
||||||
|
|
@ -79,20 +107,67 @@ func (p *windowsSerial) Write(b []byte) (int, error) {
|
||||||
|
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
port := p.port
|
port := p.port
|
||||||
|
path := p.path
|
||||||
p.mu.Unlock()
|
p.mu.Unlock()
|
||||||
|
|
||||||
if port == nil {
|
if port == nil {
|
||||||
return 0, fmt.Errorf("virtual serial port is closed")
|
return 0, fmt.Errorf("virtual serial port is closed")
|
||||||
}
|
}
|
||||||
|
|
||||||
return port.Write(b)
|
fmt.Printf(
|
||||||
|
"WINDOWS SERIAL TX [%s]: %d Bytes\n% X\n",
|
||||||
|
path,
|
||||||
|
len(b),
|
||||||
|
b,
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Printf(
|
||||||
|
"WINDOWS SERIAL TX [%s]: Rufe port.Write() auf ...\n",
|
||||||
|
path,
|
||||||
|
)
|
||||||
|
|
||||||
|
n, err := port.Write(b)
|
||||||
|
|
||||||
|
fmt.Printf(
|
||||||
|
"WINDOWS SERIAL TX [%s]: port.Write() zurückgekehrt: %d von %d Bytes\n",
|
||||||
|
path,
|
||||||
|
n,
|
||||||
|
len(b),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(
|
||||||
|
"WINDOWS SERIAL TX FEHLER [%s]: %v\n",
|
||||||
|
path,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != len(b) {
|
||||||
|
fmt.Printf(
|
||||||
|
"WINDOWS SERIAL TX UNVOLLSTÄNDIG [%s]: %d von %d Bytes\n",
|
||||||
|
path,
|
||||||
|
n,
|
||||||
|
len(b),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
fmt.Printf(
|
||||||
|
"WINDOWS SERIAL TX ERFOLGREICH [%s]: %d Bytes\n",
|
||||||
|
path,
|
||||||
|
n,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Close
|
// Close
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Close closes the Windows COM port.
|
// Close closes the Windows COM-port handle.
|
||||||
func (p *windowsSerial) Close() error {
|
func (p *windowsSerial) Close() error {
|
||||||
if p == nil {
|
if p == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -100,15 +175,36 @@ func (p *windowsSerial) Close() error {
|
||||||
|
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
|
|
||||||
if p.port == nil {
|
|
||||||
p.mu.Unlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
port := p.port
|
port := p.port
|
||||||
|
path := p.path
|
||||||
|
|
||||||
p.port = nil
|
p.port = nil
|
||||||
|
|
||||||
p.mu.Unlock()
|
p.mu.Unlock()
|
||||||
|
|
||||||
return port.Close()
|
if port == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf(
|
||||||
|
"WINDOWS SERIAL [%s]: Schließe COM-Port ...\n",
|
||||||
|
path,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := port.Close(); err != nil {
|
||||||
|
fmt.Printf(
|
||||||
|
"WINDOWS SERIAL [%s]: Fehler beim Schließen des COM-Ports: %v\n",
|
||||||
|
path,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf(
|
||||||
|
"WINDOWS SERIAL [%s]: COM-Port geschlossen.\n",
|
||||||
|
path,
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue