feat: Denkovi USB 8-relay board (FT245 D2XX bit-bang)
Third relay device alongside WebSwitch and KMTronic. Despite enumerating as a COM port, this board is driven via FTDI D2XX synchronous bit-bang (one byte = 8 relays, bit 0 = relay 1), not serial ASCII — so we load ftd2xx.dll at runtime (no CGO) and call FT_OpenEx/FT_SetBitMode/FT_Write, addressing the board by its FTDI serial (e.g. DAE0006K), exactly like the vendor tool. Windows-only (stub elsewhere); ListDenkoviDevices enumerates connected serials for the picker. Wired into relaydev (Count/Status/Set), app.go (deviceDriver/relayCountFor/type whitelist + ListDenkoviDevices binding), and the Station device editor (new type + FTDI-serial field with Detect). Untested on hardware; bit order / on-polarity may need a flip after a live test.
This commit is contained in:
@@ -11397,7 +11397,7 @@ func boolStr(b bool) string {
|
||||
// StationDevice is one configured relay board for the Station Control tab.
|
||||
type StationDevice struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"` // "webswitch" | "kmtronic"
|
||||
Type string `json:"type"` // "webswitch" | "kmtronic" | "denkovi"
|
||||
Name string `json:"name"`
|
||||
Host string `json:"host"`
|
||||
User string `json:"user,omitempty"` // KMTronic HTTP auth (blank = none)
|
||||
@@ -11407,18 +11407,31 @@ type StationDevice struct {
|
||||
|
||||
// relayCountFor returns a device type's fixed relay count.
|
||||
func relayCountFor(typ string) int {
|
||||
if typ == "kmtronic" {
|
||||
switch typ {
|
||||
case "kmtronic", "denkovi":
|
||||
return 8
|
||||
default:
|
||||
return 5 // webswitch 1216H
|
||||
}
|
||||
return 5 // webswitch 1216H
|
||||
}
|
||||
|
||||
// deviceDriver builds the wire driver for a configured device.
|
||||
func deviceDriver(d StationDevice) relaydev.Device {
|
||||
if d.Type == "kmtronic" {
|
||||
switch d.Type {
|
||||
case "kmtronic":
|
||||
return relaydev.NewKMTronic(d.Host, d.User, d.Pass)
|
||||
case "denkovi":
|
||||
// Host carries the FTDI serial number (e.g. "DAE0006K"), not a hostname.
|
||||
return relaydev.NewDenkovi(d.Host)
|
||||
default:
|
||||
return relaydev.NewWebswitch(d.Host)
|
||||
}
|
||||
return relaydev.NewWebswitch(d.Host)
|
||||
}
|
||||
|
||||
// ListDenkoviDevices returns the FTDI serial numbers of connected Denkovi/FTDI
|
||||
// boards, for the settings picker. Windows-only (FTDI D2XX).
|
||||
func (a *App) ListDenkoviDevices() ([]string, error) {
|
||||
return relaydev.ListDenkovi()
|
||||
}
|
||||
|
||||
// GetStationDevices returns the configured relay boards (without live state).
|
||||
@@ -11444,7 +11457,10 @@ func (a *App) SaveStationDevices(devs []StationDevice) error {
|
||||
return fmt.Errorf("db not initialized")
|
||||
}
|
||||
for i := range devs {
|
||||
if devs[i].Type != "kmtronic" {
|
||||
switch devs[i].Type {
|
||||
case "kmtronic", "denkovi", "webswitch":
|
||||
// known type — keep
|
||||
default:
|
||||
devs[i].Type = "webswitch"
|
||||
}
|
||||
if strings.TrimSpace(devs[i].ID) == "" {
|
||||
|
||||
Reference in New Issue
Block a user