initial commit
This commit is contained in:
82
controller/relay/relay.go
Normal file
82
controller/relay/relay.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package relay
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// CH341 serial relay protocol (LCUS-type modules on /dev/ttyUSBx).
|
||||
//
|
||||
// Command format:
|
||||
// ON: 0xA0 <channel> 0x01 <checksum>
|
||||
// OFF: 0xA0 <channel> 0x00 <checksum>
|
||||
// checksum = (0xA0 + channel + state) & 0xFF
|
||||
|
||||
type Relay struct {
|
||||
devicePath string
|
||||
channel byte
|
||||
baud int
|
||||
}
|
||||
|
||||
func New(devicePath string, channel, baud int) *Relay {
|
||||
return &Relay{
|
||||
devicePath: devicePath,
|
||||
channel: byte(channel),
|
||||
baud: baud,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Relay) Set(on bool) error {
|
||||
f, err := os.OpenFile(r.devicePath, os.O_RDWR|unix.O_NOCTTY, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("relay open %s: %w", r.devicePath, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fd := int(f.Fd())
|
||||
if err := configureSerial(fd, r.baud); err != nil {
|
||||
return fmt.Errorf("relay serial config: %w", err)
|
||||
}
|
||||
|
||||
var state byte
|
||||
if on {
|
||||
state = 0x01
|
||||
}
|
||||
|
||||
checksum := (0xA0 + r.channel + state) & 0xFF
|
||||
cmd := []byte{0xA0, r.channel, state, checksum}
|
||||
|
||||
if _, err := f.Write(cmd); err != nil {
|
||||
return fmt.Errorf("relay write: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Relay) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func configureSerial(fd, baud int) error {
|
||||
baudRate, ok := baudRates[baud]
|
||||
if !ok {
|
||||
return fmt.Errorf("unsupported baud rate: %d", baud)
|
||||
}
|
||||
|
||||
var t unix.Termios
|
||||
t.Cflag = unix.CS8 | unix.CLOCAL | unix.CREAD | baudRate
|
||||
t.Cc[unix.VMIN] = 1
|
||||
t.Cc[unix.VTIME] = 0
|
||||
|
||||
return unix.IoctlSetTermios(fd, unix.TCSETS, &t)
|
||||
}
|
||||
|
||||
var baudRates = map[int]uint32{
|
||||
9600: unix.B9600,
|
||||
19200: unix.B19200,
|
||||
38400: unix.B38400,
|
||||
57600: unix.B57600,
|
||||
115200: unix.B115200,
|
||||
}
|
||||
Reference in New Issue
Block a user