evcc-io/charger/evsemaster/connection.go

66 lines
2 KiB
Go

package evsemaster
import (
"net"
"github.com/evcc-io/evcc/util"
)
// Connection holds per-device credentials and routes sends through the shared listener.
// Multiple Connection instances with different serials can coexist; the Listener
// routes incoming packets to each by serial number.
type Connection struct {
lst *Listener
serial string
password string
recv chan<- *ReceivedPacket // channel passed to Subscribe, used to identify on Unsubscribe
}
// NewConnection creates a Connection for a device identified by serial and password.
func NewConnection(log *util.Logger, serial, password string) (*Connection, error) {
lst, err := Instance(log)
if err != nil {
return nil, err
}
return &Connection{lst: lst, serial: serial, password: password}, nil
}
// Send packs a command with device credentials and sends it to the given EVSE address.
func (c *Connection) Send(cmd uint16, payload []byte, addr *net.UDPAddr) error {
pkt := &Packet{
Serial: c.serial,
Password: c.password,
Command: cmd,
Payload: payload,
}
buf, err := pkt.Pack()
if err != nil {
return err
}
return c.lst.Send(buf, addr)
}
// Subscribe registers ch to receive all packets from this device's serial.
func (c *Connection) Subscribe(ch chan<- *ReceivedPacket) {
c.recv = ch
c.lst.Subscribe(c.serial, ch)
}
// Reclaim registers ch only if no subscriber currently holds the slot.
// Used on keepalive ticks so the long-running instance does not displace
// a temporary validate instance that is still active.
func (c *Connection) Reclaim(ch chan<- *ReceivedPacket) {
c.recv = ch
c.lst.Reclaim(c.serial, ch)
}
// Unsubscribe removes this connection's subscription only if its channel is
// still the active one, so a stale unsubscribe cannot displace a newer subscriber.
func (c *Connection) Unsubscribe() {
c.lst.Unsubscribe(c.serial, c.recv)
}
// Addr gets or sets the last known EVSE address for this device.
func (c *Connection) Addr(addr *net.UDPAddr) *net.UDPAddr {
return c.lst.Addr(c.serial, c.password, addr)
}