From a9a074602dedff8b0d0e3bb8b50eeb36d17081cb Mon Sep 17 00:00:00 2001 From: Gregor Riepl Date: Mon, 8 Feb 2021 13:04:30 +0100 Subject: [PATCH] Use a queue to process bus messages --- power/logic_psu.sch | 245 +++++++++++++++++++++++----------- power/matemat_power-cache.lib | 42 ++++++ uncanny/can.go | 200 ++++++++++++++++----------- uncanny/cmd/uncanny/main.go | 18 ++- uncanny/server.go | 46 +++---- 5 files changed, 366 insertions(+), 185 deletions(-) diff --git a/power/logic_psu.sch b/power/logic_psu.sch index 05f43f5..6f29cbf 100644 --- a/power/logic_psu.sch +++ b/power/logic_psu.sch @@ -580,24 +580,22 @@ Wire Wire Line $Comp L Connector_Generic:Conn_01x02 J6 U 1 1 50F5BE5A -P 1200 2850 +P 850 2850 AR Path="/50F5BE5A" Ref="J6" Part="1" AR Path="/50FF13A8/50F5BE5A" Ref="J6" Part="1" -F 0 "J6" V 1150 2850 50 0000 C CNN -F 1 "B3_Wago" V 1250 2850 40 0000 C CNN -F 2 "TerminalBlock_WAGO:TerminalBlock_WAGO_236-402_1x02_P5.00mm_45Degree" H 1200 2850 60 0001 C CNN -F 3 "" H 1200 2850 60 0001 C CNN -F 4 "FAR 1283527" H 1200 2850 60 0001 C CNN "Reference" -F 5 "0,84" H 1200 2850 60 0001 C CNN "prix" - 1 1200 2850 +F 0 "J6" V 800 2850 50 0000 C CNN +F 1 "B3_Wago" V 900 2850 40 0000 C CNN +F 2 "TerminalBlock_WAGO:TerminalBlock_WAGO_236-402_1x02_P5.00mm_45Degree" H 850 2850 60 0001 C CNN +F 3 "" H 850 2850 60 0001 C CNN +F 4 "FAR 1283527" H 850 2850 60 0001 C CNN "Reference" +F 5 "0,84" H 850 2850 60 0001 C CNN "prix" + 1 850 2850 -1 0 0 -1 $EndComp Wire Wire Line - 1550 2850 1400 2850 + 1550 2850 1450 2850 Wire Wire Line - 1400 2950 2700 2950 -Wire Wire Line - 1850 2850 2200 2850 + 1850 2850 1950 2850 Wire Wire Line 3350 3150 3350 3450 Wire Wire Line @@ -796,22 +794,19 @@ F 3 "" H 2700 3600 50 0001 C CNN 1 2700 3600 1 0 0 -1 $EndComp -Connection ~ 9500 1750 Wire Wire Line 9500 1750 9700 1750 Wire Wire Line 9500 1950 9700 1950 -Wire Wire Line - 9500 1750 9500 1950 $Comp L power:+12V #PWR0175 U 1 1 60094D63 -P 9500 1750 -F 0 "#PWR0175" H 9500 1600 50 0001 C CNN -F 1 "+12V" H 9515 1923 50 0000 C CNN -F 2 "" H 9500 1750 50 0001 C CNN -F 3 "" H 9500 1750 50 0001 C CNN - 1 9500 1750 +P 9500 1550 +F 0 "#PWR0175" H 9500 1400 50 0001 C CNN +F 1 "+12V" H 9515 1723 50 0000 C CNN +F 2 "" H 9500 1550 50 0001 C CNN +F 3 "" H 9500 1550 50 0001 C CNN + 1 9500 1550 1 0 0 -1 $EndComp Wire Wire Line @@ -829,11 +824,6 @@ Wire Wire Line Connection ~ 9600 1650 Wire Wire Line 9600 1650 9700 1650 -Connection ~ 9500 1350 -Wire Wire Line - 9500 1550 9700 1550 -Wire Wire Line - 9500 1350 9500 1550 Wire Wire Line 9600 2150 9600 2050 $Comp @@ -880,102 +870,195 @@ PFET_DRAIN $Comp L Regulator_Linear:LM7805_TO220 U1 U 1 1 60125424 -P 7900 5750 -F 0 "U1" H 7900 5992 50 0000 C CNN -F 1 "LM7805" H 7900 5901 50 0000 C CNN -F 2 "Package_TO_SOT_SMD:SOT-223-3_TabPin2" H 7900 5975 50 0001 C CIN -F 3 "https://www.onsemi.cn/PowerSolutions/document/MC7800-D.PDF" H 7900 5700 50 0001 C CNN - 1 7900 5750 +P 2450 5050 +F 0 "U1" H 2450 5292 50 0000 C CNN +F 1 "LM7805" H 2450 5201 50 0000 C CNN +F 2 "Package_TO_SOT_SMD:SOT-223-3_TabPin2" H 2450 5275 50 0001 C CIN +F 3 "https://www.onsemi.cn/PowerSolutions/document/MC7800-D.PDF" H 2450 5000 50 0001 C CNN + 1 2450 5050 1 0 0 -1 $EndComp $Comp L power:+5V #PWR0176 U 1 1 601266A6 -P 8650 5750 -F 0 "#PWR0176" H 8650 5600 50 0001 C CNN -F 1 "+5V" H 8665 5923 50 0000 C CNN -F 2 "" H 8650 5750 50 0001 C CNN -F 3 "" H 8650 5750 50 0001 C CNN - 1 8650 5750 +P 3200 5050 +F 0 "#PWR0176" H 3200 4900 50 0001 C CNN +F 1 "+5V" H 3215 5223 50 0000 C CNN +F 2 "" H 3200 5050 50 0001 C CNN +F 3 "" H 3200 5050 50 0001 C CNN + 1 3200 5050 1 0 0 -1 $EndComp $Comp L power:+12V #PWR0177 U 1 1 60126C51 -P 7250 5750 -F 0 "#PWR0177" H 7250 5600 50 0001 C CNN -F 1 "+12V" H 7265 5923 50 0000 C CNN -F 2 "" H 7250 5750 50 0001 C CNN -F 3 "" H 7250 5750 50 0001 C CNN - 1 7250 5750 +P 1800 5050 +F 0 "#PWR0177" H 1800 4900 50 0001 C CNN +F 1 "+12V" H 1815 5223 50 0000 C CNN +F 2 "" H 1800 5050 50 0001 C CNN +F 3 "" H 1800 5050 50 0001 C CNN + 1 1800 5050 1 0 0 -1 $EndComp $Comp L Device:CP C? U 1 1 6012703D -P 8650 5900 +P 3200 5200 AR Path="/6012703D" Ref="C?" Part="1" AR Path="/50FF13A8/6012703D" Ref="C7" Part="1" -F 0 "C7" H 8700 6200 50 0000 L CNN -F 1 "10u" V 8800 5850 50 0000 L CNN -F 2 "Capacitor_THT:CP_Radial_D5.0mm_P2.50mm" H 8650 5900 60 0001 C CNN -F 3 "" H 8650 5900 60 0001 C CNN -F 4 "RS703-7396" H 8650 5900 60 0001 C CNN "Reference" -F 5 "0.864" H 8650 5900 60 0001 C CNN "prix" - 1 8650 5900 +F 0 "C7" H 3250 5500 50 0000 L CNN +F 1 "10u" V 3350 5150 50 0000 L CNN +F 2 "Capacitor_THT:CP_Radial_D5.0mm_P2.50mm" H 3200 5200 60 0001 C CNN +F 3 "" H 3200 5200 60 0001 C CNN +F 4 "RS703-7396" H 3200 5200 60 0001 C CNN "Reference" +F 5 "0.864" H 3200 5200 60 0001 C CNN "prix" + 1 3200 5200 1 0 0 -1 $EndComp $Comp L Device:C C? U 1 1 6012763F -P 8200 5900 +P 2750 5200 AR Path="/6012763F" Ref="C?" Part="1" AR Path="/50FF13A8/6012763F" Ref="C6" Part="1" -F 0 "C6" H 8350 6100 50 0000 L CNN -F 1 "100n" H 8350 6000 50 0000 L CNN -F 2 "Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder" H 8550 5900 60 0001 C CNN -F 3 "" H 8200 5900 60 0001 C CNN - 1 8200 5900 +F 0 "C6" H 2900 5400 50 0000 L CNN +F 1 "100n" H 2900 5300 50 0000 L CNN +F 2 "Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder" H 3100 5200 60 0001 C CNN +F 3 "" H 2750 5200 60 0001 C CNN + 1 2750 5200 1 0 0 -1 $EndComp Wire Wire Line - 8200 5750 8650 5750 -Connection ~ 8200 5750 + 2750 5050 3200 5050 +Connection ~ 2750 5050 Wire Wire Line - 8650 6050 8200 6050 -Connection ~ 7900 6050 + 3200 5350 2750 5350 +Connection ~ 2450 5350 Wire Wire Line - 7900 6050 7250 6050 -Connection ~ 8200 6050 + 2450 5350 1800 5350 +Connection ~ 2750 5350 Wire Wire Line - 8200 6050 7900 6050 + 2750 5350 2450 5350 Wire Wire Line - 7250 5750 7600 5750 -Connection ~ 7250 5750 -Connection ~ 8650 5750 + 1800 5050 2150 5050 +Connection ~ 1800 5050 +Connection ~ 3200 5050 $Comp L Device:C C? U 1 1 60127A01 -P 7250 5900 +P 1800 5200 AR Path="/60127A01" Ref="C?" Part="1" AR Path="/50FF13A8/60127A01" Ref="C5" Part="1" -F 0 "C5" H 7400 6100 50 0000 L CNN -F 1 "100n" H 7400 6000 50 0000 L CNN -F 2 "Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder" H 7600 5900 60 0001 C CNN -F 3 "" H 7250 5900 60 0001 C CNN - 1 7250 5900 +F 0 "C5" H 1950 5400 50 0000 L CNN +F 1 "330n" H 1950 5300 50 0000 L CNN +F 2 "Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder" H 2150 5200 60 0001 C CNN +F 3 "" H 1800 5200 60 0001 C CNN + 1 1800 5200 1 0 0 -1 $EndComp $Comp L power:GND #PWR0179 U 1 1 600EBFC5 -P 7250 6050 -F 0 "#PWR0179" H 7250 5800 50 0001 C CNN -F 1 "GND" H 7255 5877 50 0000 C CNN -F 2 "" H 7250 6050 50 0001 C CNN -F 3 "" H 7250 6050 50 0001 C CNN - 1 7250 6050 +P 1800 5350 +F 0 "#PWR0179" H 1800 5100 50 0001 C CNN +F 1 "GND" H 1805 5177 50 0000 C CNN +F 2 "" H 1800 5350 50 0001 C CNN +F 3 "" H 1800 5350 50 0001 C CNN + 1 1800 5350 1 0 0 -1 $EndComp -Connection ~ 7250 6050 +Connection ~ 1800 5350 +$Comp +L power:+5V #PWR? +U 1 1 60130758 +P 9500 1950 +F 0 "#PWR?" H 9500 1800 50 0001 C CNN +F 1 "+5V" H 9515 2123 50 0000 C CNN +F 2 "" H 9500 1950 50 0001 C CNN +F 3 "" H 9500 1950 50 0001 C CNN + 1 9500 1950 + 1 0 0 -1 +$EndComp +Wire Wire Line + 9500 1550 9700 1550 +Wire Wire Line + 9500 1550 9500 1750 +Connection ~ 9500 1550 +$Comp +L power:LINE #PWR? +U 1 1 6013AC53 +P 1200 2250 +F 0 "#PWR?" H 1200 2100 50 0001 C CNN +F 1 "LINE" H 1215 2423 50 0000 C CNN +F 2 "" H 1200 2250 50 0001 C CNN +F 3 "" H 1200 2250 50 0001 C CNN + 1 1200 2250 + 1 0 0 -1 +$EndComp +$Comp +L Device:Polyfuse F? +U 1 1 6013BA9D +P 1700 2700 +F 0 "F?" V 1475 2700 50 0000 C CNN +F 1 "2A" V 1566 2700 50 0000 C CNN +F 2 "" H 1750 2500 50 0001 L CNN +F 3 "~" H 1700 2700 50 0001 C CNN + 1 1700 2700 + 0 1 1 0 +$EndComp +Wire Wire Line + 1850 2700 1950 2700 +Wire Wire Line + 1950 2700 1950 2850 +Connection ~ 1950 2850 +Wire Wire Line + 1950 2850 2200 2850 +Wire Wire Line + 1550 2700 1450 2700 +Wire Wire Line + 1450 2700 1450 2850 +Connection ~ 1450 2850 +$Comp +L Device:Jumper JP? +U 1 1 60146B55 +P 1200 2550 +F 0 "JP?" V 1154 2677 50 0000 L CNN +F 1 "AC" V 1245 2677 50 0000 L CNN +F 2 "" H 1200 2550 50 0001 C CNN +F 3 "~" H 1200 2550 50 0001 C CNN + 1 1200 2550 + 0 1 1 0 +$EndComp +Wire Wire Line + 1050 2850 1200 2850 +Connection ~ 1200 2850 +Wire Wire Line + 1200 2850 1450 2850 +$Comp +L Device:Jumper JP? +U 1 1 6014CA6B +P 1200 3250 +F 0 "JP?" V 1246 3162 50 0000 R CNN +F 1 "AC" V 1155 3162 50 0000 R CNN +F 2 "" H 1200 3250 50 0001 C CNN +F 3 "~" H 1200 3250 50 0001 C CNN + 1 1200 3250 + 0 -1 -1 0 +$EndComp +Wire Wire Line + 1050 2950 1200 2950 +Connection ~ 1200 2950 +Wire Wire Line + 1200 2950 2700 2950 +$Comp +L power:NEUT #PWR? +U 1 1 60152DC7 +P 1200 3550 +F 0 "#PWR?" H 1200 3400 50 0001 C CNN +F 1 "NEUT" H 1215 3723 50 0000 C CNN +F 2 "" H 1200 3550 50 0001 C CNN +F 3 "" H 1200 3550 50 0001 C CNN + 1 1200 3550 + -1 0 0 1 +$EndComp $EndSCHEMATC diff --git a/power/matemat_power-cache.lib b/power/matemat_power-cache.lib index 5b234c9..e506c55 100644 --- a/power/matemat_power-cache.lib +++ b/power/matemat_power-cache.lib @@ -220,6 +220,28 @@ X ~ 2 0 -150 50 U 50 50 1 1 P ENDDRAW ENDDEF # +# Device_Jumper +# +DEF Device_Jumper JP 0 30 Y N 1 F N +F0 "JP" 0 150 50 H V C CNN +F1 "Device_Jumper" 0 -80 50 H V C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +$FPLIST + SolderJumper* + Jumper* + TestPoint*2Pads* + TestPoint*Bridge* +$ENDFPLIST +DRAW +A 0 -26 125 1426 373 0 1 0 N -98 50 99 50 +C -100 0 35 0 1 0 N +C 100 0 35 0 1 0 N +X 1 1 -300 0 165 R 50 50 0 1 P +X 2 2 300 0 165 L 50 50 0 1 P +ENDDRAW +ENDDEF +# # Device_L # DEF Device_L L 0 40 N N 1 F N @@ -243,6 +265,26 @@ X 2 2 0 -150 50 U 50 50 1 1 P ENDDRAW ENDDEF # +# Device_Polyfuse +# +DEF Device_Polyfuse F 0 0 N Y 1 F N +F0 "F" -100 0 50 V V C CNN +F1 "Device_Polyfuse" 100 0 50 V V C CNN +F2 "" 50 -200 50 H I L CNN +F3 "" 0 0 50 H I C CNN +$FPLIST + *polyfuse* + *PTC* +$ENDFPLIST +DRAW +S -30 100 30 -100 0 1 10 N +P 2 0 1 0 0 100 0 -100 N +P 4 0 1 0 -60 100 -60 60 60 -60 60 -100 N +X ~ 1 0 150 50 D 50 50 1 1 P +X ~ 2 0 -150 50 U 50 50 1 1 P +ENDDRAW +ENDDEF +# # Device_Q_NPN_BCE # DEF Device_Q_NPN_BCE Q 0 0 Y N 1 F N diff --git a/uncanny/can.go b/uncanny/can.go index 4ea4f80..2b696ef 100644 --- a/uncanny/can.go +++ b/uncanny/can.go @@ -7,8 +7,12 @@ import ( "github.com/brutella/can" ) +const queueSize = 10 + type Can struct { bus *can.Bus + queue chan func() + swstate FeedbackMessage dispstate int } @@ -20,112 +24,154 @@ func NewCan(intf string) (*Can, error) { } can := &Can{ bus: bus, + queue: make(chan func(), queueSize), dispstate: -1, } bus.Subscribe(can) return can, nil } -func (c *Can) Start() { - go func() { - // send the init sequence, but (hopefully) defer until after we start listening - // FIXME this is inherently racy :( - go c.initialize() - // ConnectAndPublish will block, so we'll just leave the Printf hanging here - log.Printf("CAN bus shut down: %v", c.bus.ConnectAndPublish()) - }() +func (c *Can) Start() error { + go c.process() + log.Printf("Starting bus listener") + return c.bus.ConnectAndPublish() } -func (c *Can) Stop() { - c.bus.Disconnect() +func (c *Can) process() { + running := true + log.Printf("Starting processing queue") + for running { + select { + case fn, ok := <-c.queue: + if ok { + fn() + } else { + running = false + } + } + } + for range c.queue {} + log.Printf("Processing queue shut down") +} + +func (c *Can) Stop() error { + log.Printf("Shutting down processing queue and bus listener") + close(c.queue) + return c.bus.Disconnect() } func (c *Can) Handle(frame can.Frame) { - log.Printf("Got CAN frame to 0x%08x", frame.ID) - typ, obj, err := DecodeMessage(frame) - if err != nil { - if err == UnsupportedMessageType { - log.Printf("Unsupported message type: 0x%08x", frame.ID) - } else { - log.Printf("Cannot decode message: %v", err) - } - } else { - switch typ { - case MessageTypeFeedback: - log.Printf("Got feedback message: %+v", obj.(FeedbackMessage)) - log.Printf("Data: 0x%02x 0x%02x", frame.Data[0], frame.Data[1]) - c.swstate = obj.(FeedbackMessage) - // when all end switches are off: send stop command - if !c.swstate.EndD && !c.swstate.EndE && !c.swstate.EndF && !c.swstate.EndG && !c.swstate.EndH { - log.Printf("All end switches off, stopping dispenser") - c.Cancel() + c.queue <- func() { + log.Printf("Got CAN frame to 0x%08x", frame.ID) + typ, obj, err := DecodeMessage(frame) + if err != nil { + if err == UnsupportedMessageType { + log.Printf("Unsupported message type: 0x%08x", frame.ID) + } else { + log.Printf("Cannot decode message: %v", err) + } + } else { + switch typ { + case MessageTypeFeedback: + log.Printf("Got feedback message: %+v", obj.(FeedbackMessage)) + log.Printf("Data: 0x%02x 0x%02x", frame.Data[0], frame.Data[1]) + c.swstate = obj.(FeedbackMessage) + // when all end switches are off: send stop command + if !c.swstate.EndD && !c.swstate.EndE && !c.swstate.EndF && !c.swstate.EndG && !c.swstate.EndH { + log.Printf("All end switches off, stopping dispenser") + c.Cancel() + } + case MessageTypeFeedbackRequest: + // ignore + case MessageTypePower: + log.Printf("Got power message: %+v", obj.(PowerMessage)) + // ignore + case MessageTypePowerRequest: + // ignore + case MessageTypeDispense: + log.Printf("Got dispense message: %+v", obj.(DispenseMessage)) + c.dispstate = obj.(DispenseMessage).Slot + case MessageTypeAuto: + // ignore } - case MessageTypeFeedbackRequest: - // ignore - case MessageTypePower: - log.Printf("Got power message: %+v", obj.(PowerMessage)) - // ignore - case MessageTypePowerRequest: - // ignore - case MessageTypeDispense: - log.Printf("Got dispense message: %+v", obj.(DispenseMessage)) - c.dispstate = obj.(DispenseMessage).Slot - case MessageTypeAuto: - // ignore } } } func (c *Can) IsEmpty(slot int) bool { - switch (slot) { - case 0: - return c.swstate.EmptyD - case 1: - return c.swstate.EmptyE - case 2: - return c.swstate.EmptyF - case 3: - return c.swstate.EmptyG - case 4: - return c.swstate.EmptyH + ret := make(chan bool) + c.queue <- func() { + switch (slot) { + case 0: + ret <- c.swstate.EmptyD + case 1: + ret <- c.swstate.EmptyE + case 2: + ret <- c.swstate.EmptyF + case 3: + ret <- c.swstate.EmptyG + case 4: + ret <- c.swstate.EmptyH + } + ret <- false } - return false + return <-ret } func (c *Can) IsDispensing(slot int) bool { - switch (slot) { - case 0: - return c.swstate.EndD - case 1: - return c.swstate.EndE - case 2: - return c.swstate.EndF - case 3: - return c.swstate.EndG - case 4: - return c.swstate.EndH + ret := make(chan bool) + c.queue <- func() { + switch (slot) { + case 0: + ret <- c.swstate.EndD + case 1: + ret <- c.swstate.EndE + case 2: + ret <- c.swstate.EndF + case 3: + ret <- c.swstate.EndG + case 4: + ret <- c.swstate.EndH + } + ret <- false } - return false + return <-ret } func (c *Can) ActiveDispenser() int { - return c.dispstate + ret := make(chan int) + c.queue <- func() { + ret <- c.dispstate + } + return <- ret } -func (c *Can) Dispense(slot int) error { - log.Printf("Starting dispense on slot %d", slot) - return c.bus.Publish(DispenseMessage{slot}.Encode()) +func (c *Can) Dispense(slot int) { + c.queue <- func() { + log.Printf("Starting dispense on slot %d", slot) + err := c.bus.Publish(DispenseMessage{slot}.Encode()) + if err != nil { + log.Printf("Error sending dispense command: %v", err) + } + } } -func (c *Can) Cancel() error { - log.Printf("Stopping dispense") - return c.bus.Publish(DispenseMessage{DispenseSlotOff}.Encode()) +func (c *Can) Cancel() { + c.queue <- func() { + log.Printf("Stopping dispense") + err := c.bus.Publish(DispenseMessage{DispenseSlotOff}.Encode()) + if err != nil { + log.Printf("Error sending stop command: %v", err) + } + } } -func (c *Can) initialize() { - log.Printf("Initializing") - // enable automatic status updates - c.bus.Publish(AutoMessage{true}.Encode()) - c.bus.Publish(RequestFeedbackMessage()) - c.bus.Publish(RequestPowerMessage()) +func (c *Can) Initialize() { + c.queue <- func() { + log.Printf("Initializing devices") + // enable automatic status updates + c.bus.Publish(AutoMessage{true}.Encode()) + c.bus.Publish(RequestFeedbackMessage()) + c.bus.Publish(RequestPowerMessage()) + } } diff --git a/uncanny/cmd/uncanny/main.go b/uncanny/cmd/uncanny/main.go index bdb88b5..f2475e0 100644 --- a/uncanny/cmd/uncanny/main.go +++ b/uncanny/cmd/uncanny/main.go @@ -4,6 +4,7 @@ import ( "flag" "git.kabelsalat.ch/seto/matemat/uncanny" "log" + "sync" ) const ( @@ -21,7 +22,20 @@ func main() { if err != nil { log.Fatal(err) } - server := uncanny.NewServer(can) + server := uncanny.NewServer(can, addr) can.Start() - log.Fatal(server.ListenAndServe(addr)) + wg := sync.WaitGroup{} + wg.Add(2) + go func() { + log.Printf("Server exited: %v", server.Start()) + wg.Done() + can.Stop() + }() + go func() { + log.Printf("Bus listener exited: %v", can.Start()) + wg.Done() + server.Stop() + }() + wg.Wait() + log.Printf("Shut down") } diff --git a/uncanny/server.go b/uncanny/server.go index bc1035d..99019b4 100644 --- a/uncanny/server.go +++ b/uncanny/server.go @@ -15,15 +15,20 @@ const ( type Server struct { *http.ServeMux + srv *http.Server can *Can } -func NewServer(can *Can) *Server { +func NewServer(can *Can, addr string) *Server { ret := &Server{ ServeMux: http.NewServeMux(), can: can, + srv: &http.Server{ + Addr: addr, + }, } ret.registerHandlers() + ret.srv.Handler = ret return ret } @@ -39,17 +44,10 @@ func (s *Server) registerHandlers() { log.Printf("Invalid slot number: %d", slot) http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) } else { - err = s.can.Dispense(int(slot)) - if err != nil { - log.Printf("Error sending dispense command: %v", err) - rw.Header().Set("Content-Type", "text/plain") - rw.WriteHeader(http.StatusServiceUnavailable) - fmt.Fprintf(rw, "%d error", slot) - } else { - rw.Header().Set("Content-Type", "text/plain") - rw.WriteHeader(http.StatusOK) - fmt.Fprintf(rw, "%d dispense", slot) - } + s.can.Dispense(int(slot)) + rw.Header().Set("Content-Type", "text/plain") + rw.WriteHeader(http.StatusOK) + fmt.Fprintf(rw, "%d dispensing", slot) } } else { log.Printf("Mismatched path: %s", r.URL.Path) @@ -57,17 +55,10 @@ func (s *Server) registerHandlers() { } }) s.HandleFunc("/stop", func(rw http.ResponseWriter, r *http.Request) { - err := s.can.Cancel() - if err != nil { - log.Printf("Error sending stop command: %v", err) - rw.Header().Set("Content-Type", "text/plain") - rw.WriteHeader(http.StatusServiceUnavailable) - fmt.Fprintf(rw, "error") - } else { - rw.Header().Set("Content-Type", "text/plain") - rw.WriteHeader(http.StatusOK) - fmt.Fprintf(rw, "stopped") - } + s.can.Cancel() + rw.Header().Set("Content-Type", "text/plain") + rw.WriteHeader(http.StatusOK) + fmt.Fprintf(rw, "stopping") }) s.HandleFunc("/level/", func(rw http.ResponseWriter, r *http.Request) { if matched, _ := path.Match("/level/[0-9]*", r.URL.Path); matched { @@ -117,6 +108,11 @@ func (s *Server) registerHandlers() { }) } -func (s *Server) ListenAndServe(addr string) error { - return http.ListenAndServe(addr, s) +func (s *Server) Start() error { + log.Printf("Listening on %v", s.srv.Addr) + return s.srv.ListenAndServe() +} + +func (s *Server) Stop() error { + return s.srv.Close() }