github.com/martinohmann/rfoutlet@v1.2.1-0.20220707195255-8a66aa411105/internal/outlet/switch.go (about) 1 package outlet 2 3 import ( 4 "fmt" 5 6 "github.com/martinohmann/rfoutlet/pkg/gpio" 7 "github.com/sirupsen/logrus" 8 ) 9 10 var log = logrus.WithField("component", "outlet") 11 12 // Switcher defines the interface for an outlet switcher. 13 type Switcher interface { 14 // Switch switches an outlet to the desired state. 15 Switch(outlet *Outlet, state State) error 16 } 17 18 // Switch switches outlets by sending out codes using an gpio transmitter. 19 type Switch struct { 20 Transmitter gpio.CodeTransmitter 21 } 22 23 // NewSwitch creates a new *Switch. 24 func NewSwitch(transmitter gpio.CodeTransmitter) *Switch { 25 return &Switch{ 26 Transmitter: transmitter, 27 } 28 } 29 30 // Switch switches an outlet to the provided state. 31 func (s *Switch) Switch(o *Outlet, state State) error { 32 if o.Protocol < 1 || o.Protocol > len(gpio.DefaultProtocols) { 33 return fmt.Errorf("protocol %d does not exist", o.Protocol) 34 } 35 36 proto := gpio.DefaultProtocols[o.Protocol-1] 37 38 code := o.getCodeForState(state) 39 40 log.WithFields(logrus.Fields{ 41 "outletID": o.ID, 42 "outletState": o.GetState(), 43 "desiredState": state, 44 "protocol": o.Protocol, 45 "pulseLength": o.PulseLength, 46 }).Debugf("transmitting code %d", code) 47 48 s.Transmitter.Transmit(code, proto, o.PulseLength) 49 o.SetState(state) 50 51 return nil 52 } 53 54 // FakeSwitch can be used in tests, 55 type FakeSwitch struct { 56 // Err is the error that should be returned by Switch. If non-nil, the 57 // state of any passed in *Outlet will not be altered. 58 Err error 59 } 60 61 // Switch implements Switcher. 62 // 63 // It will only set the outlet state or return the configured error. 64 func (s *FakeSwitch) Switch(outlet *Outlet, state State) error { 65 if s.Err != nil { 66 return s.Err 67 } 68 69 outlet.SetState(state) 70 71 return nil 72 }