Use a queue to process bus messages

This commit is contained in:
Gregor Riepl 2021-02-08 13:04:30 +01:00
parent 4447e89c5e
commit a9a074602d
5 changed files with 366 additions and 185 deletions

View file

@ -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

View file

@ -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

View file

@ -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,27 +24,44 @@ 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) {
c.queue <- func() {
log.Printf("Got CAN frame to 0x%08x", frame.ID)
typ, obj, err := DecodeMessage(frame)
if err != nil {
@ -74,58 +95,83 @@ func (c *Can) Handle(frame can.Frame) {
// ignore
}
}
}
}
func (c *Can) IsEmpty(slot int) bool {
ret := make(chan bool)
c.queue <- func() {
switch (slot) {
case 0:
return c.swstate.EmptyD
ret <- c.swstate.EmptyD
case 1:
return c.swstate.EmptyE
ret <- c.swstate.EmptyE
case 2:
return c.swstate.EmptyF
ret <- c.swstate.EmptyF
case 3:
return c.swstate.EmptyG
ret <- c.swstate.EmptyG
case 4:
return c.swstate.EmptyH
ret <- c.swstate.EmptyH
}
return false
ret <- false
}
return <-ret
}
func (c *Can) IsDispensing(slot int) bool {
ret := make(chan bool)
c.queue <- func() {
switch (slot) {
case 0:
return c.swstate.EndD
ret <- c.swstate.EndD
case 1:
return c.swstate.EndE
ret <- c.swstate.EndE
case 2:
return c.swstate.EndF
ret <- c.swstate.EndF
case 3:
return c.swstate.EndG
ret <- c.swstate.EndG
case 4:
return c.swstate.EndH
ret <- c.swstate.EndH
}
return false
ret <- 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 {
func (c *Can) Dispense(slot int) {
c.queue <- func() {
log.Printf("Starting dispense on slot %d", slot)
return c.bus.Publish(DispenseMessage{slot}.Encode())
err := c.bus.Publish(DispenseMessage{slot}.Encode())
if err != nil {
log.Printf("Error sending dispense command: %v", err)
}
}
}
func (c *Can) Cancel() error {
func (c *Can) Cancel() {
c.queue <- func() {
log.Printf("Stopping dispense")
return c.bus.Publish(DispenseMessage{DispenseSlotOff}.Encode())
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")
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())
}
}

View file

@ -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")
}

View file

@ -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 {
s.can.Dispense(int(slot))
rw.Header().Set("Content-Type", "text/plain")
rw.WriteHeader(http.StatusOK)
fmt.Fprintf(rw, "%d dispense", slot)
}
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 {
s.can.Cancel()
rw.Header().Set("Content-Type", "text/plain")
rw.WriteHeader(http.StatusOK)
fmt.Fprintf(rw, "stopped")
}
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()
}