feat: New Station Control, allow to control Webswitch 1216H or KMTronic

This commit is contained in:
2026-07-16 22:01:07 +02:00
parent c9fd1379e1
commit 829c236d6c
13 changed files with 1344 additions and 48 deletions
+101
View File
@@ -0,0 +1,101 @@
package relaydev
import (
"context"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
// The status parsers are the risky part; pin them against the documented wire
// formats using a stub HTTP server.
func TestWebswitchStatus(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !strings.HasPrefix(r.URL.Path, "/relaystate/get2/") {
t.Errorf("unexpected status path %q", r.URL.Path)
}
_, _ = w.Write([]byte("1,1\n2,0\n3,1\n4,0\n5,1\n"))
}))
defer srv.Close()
d := NewWebswitch(strings.TrimPrefix(srv.URL, "http://"))
st, err := d.Status(context.Background())
if err != nil {
t.Fatal(err)
}
want := []bool{true, false, true, false, true}
if len(st) != 5 {
t.Fatalf("got %d relays, want 5", len(st))
}
for i := range want {
if st[i] != want[i] {
t.Errorf("relay %d = %v, want %v", i+1, st[i], want[i])
}
}
}
func TestWebswitchSetURL(t *testing.T) {
var gotPath string
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gotPath = r.URL.Path
}))
defer srv.Close()
d := NewWebswitch(strings.TrimPrefix(srv.URL, "http://"))
if err := d.Set(context.Background(), 4, true); err != nil {
t.Fatal(err)
}
if gotPath != "/relaycontrol/on/4" {
t.Errorf("set path = %q, want /relaycontrol/on/4", gotPath)
}
_ = d.Set(context.Background(), 4, false)
}
func TestKMTronicStatus(t *testing.T) {
// relay0 reserved (ignored); relay7 + relay8 ON.
xmlBody := `<?xml version="1.0"?><response>` +
`<relay0>0</relay0><relay1>0</relay1><relay2>0</relay2><relay3>0</relay3>` +
`<relay4>0</relay4><relay5>0</relay5><relay6>0</relay6><relay7>1</relay7><relay8>1</relay8>` +
`</response>`
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/status.xml" {
t.Errorf("unexpected path %q", r.URL.Path)
}
_, _ = w.Write([]byte(xmlBody))
}))
defer srv.Close()
d := NewKMTronic(strings.TrimPrefix(srv.URL, "http://"), "", "")
st, err := d.Status(context.Background())
if err != nil {
t.Fatal(err)
}
if len(st) != 8 {
t.Fatalf("got %d relays, want 8", len(st))
}
if st[6] != true || st[7] != true {
t.Errorf("relay7/8 = %v/%v, want on/on", st[6], st[7])
}
for i := 0; i < 6; i++ {
if st[i] {
t.Errorf("relay %d unexpectedly on", i+1)
}
}
}
func TestKMTronicSetURL(t *testing.T) {
var gotPath string
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gotPath = r.URL.Path
}))
defer srv.Close()
d := NewKMTronic(strings.TrimPrefix(srv.URL, "http://"), "", "")
if err := d.Set(context.Background(), 8, true); err != nil {
t.Fatal(err)
}
if gotPath != "/FF0801" {
t.Errorf("set path = %q, want /FF0801", gotPath)
}
_ = d.Set(context.Background(), 1, false) // → /FF0100
}