Better CAN message naming, added display support

This commit is contained in:
Gregor Riepl 2021-05-04 23:52:43 +02:00
parent 0107ee5129
commit bdaa925100
2 changed files with 137 additions and 53 deletions

View file

@ -13,7 +13,7 @@ type Can struct {
bus *can.Bus bus *can.Bus
queue chan func() queue chan func()
swstate FeedbackMessage swstate FeedbackStatus
dispstate int dispstate int
} }
@ -72,27 +72,23 @@ func (c *Can) Handle(frame can.Frame) {
} }
} else { } else {
switch typ { switch typ {
case MessageTypeFeedback: case MessageTypeFeedbackStatus:
log.Printf("Got feedback message: %+v", obj.(FeedbackMessage)) log.Printf("Got feedback status message: %+v", obj.(FeedbackStatus))
log.Printf("Data: 0x%02x 0x%02x", frame.Data[0], frame.Data[1]) log.Printf("Data: 0x%02x 0x%02x", frame.Data[0], frame.Data[1])
c.swstate = obj.(FeedbackMessage) c.swstate = obj.(FeedbackStatus)
// when all end switches are open (i.e. true): send stop command // when all end switches are open (i.e. true): send stop command
if c.swstate.EndD && c.swstate.EndE && c.swstate.EndF && c.swstate.EndG && c.swstate.EndH { if c.swstate.EndD && c.swstate.EndE && c.swstate.EndF && c.swstate.EndG && c.swstate.EndH {
log.Printf("All end switches off, stopping dispenser") log.Printf("All end switches off, stopping dispenser")
c.Cancel() c.Cancel()
} }
case MessageTypeFeedbackRequest: case MessageTypePowerStatus:
// ignore log.Printf("Got power status message: %+v", obj.(PowerStatus))
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 // ignore
case MessageTypeDispenseCommand:
log.Printf("Got dispense command message: %+v", obj.(DispenseCommand))
c.dispstate = obj.(DispenseCommand).Slot
case MessageTypeDisplayStatus:
log.Printf("Got display status message: %+v", obj.(DisplayStatus))
} }
} }
} }
@ -149,7 +145,7 @@ func (c *Can) ActiveDispenser() int {
func (c *Can) Dispense(slot int) { func (c *Can) Dispense(slot int) {
c.queue <- func() { c.queue <- func() {
log.Printf("Starting dispense on slot %d", slot) log.Printf("Starting dispense on slot %d", slot)
err := c.bus.Publish(DispenseMessage{slot}.Encode()) err := c.bus.Publish(DispenseCommand{slot}.Encode())
if err != nil { if err != nil {
log.Printf("Error sending dispense command: %v", err) log.Printf("Error sending dispense command: %v", err)
} }
@ -159,7 +155,7 @@ func (c *Can) Dispense(slot int) {
func (c *Can) Cancel() { func (c *Can) Cancel() {
c.queue <- func() { c.queue <- func() {
log.Printf("Stopping dispense") log.Printf("Stopping dispense")
err := c.bus.Publish(DispenseMessage{DispenseSlotOff}.Encode()) err := c.bus.Publish(DispenseCommand{DispenseSlotOff}.Encode())
if err != nil { if err != nil {
log.Printf("Error sending stop command: %v", err) log.Printf("Error sending stop command: %v", err)
} }
@ -170,8 +166,9 @@ func (c *Can) Initialize() {
c.queue <- func() { c.queue <- func() {
log.Printf("Initializing devices") log.Printf("Initializing devices")
// enable automatic status updates // enable automatic status updates
c.bus.Publish(AutoMessage{true}.Encode()) c.bus.Publish(AutoCommand{true}.Encode())
c.bus.Publish(RequestFeedbackMessage()) c.bus.Publish(EncodeFeedbackRequest())
c.bus.Publish(RequestPowerMessage()) c.bus.Publish(EncodePowerRequest())
c.bus.Publish(EncodeDisplayRequest())
} }
} }

View file

@ -44,6 +44,9 @@ const uint8_t can_msg_power_dispense_slot3 = CAN_MSG_POWER_DISPENSE_SLOT3;
const uint8_t can_msg_power_dispense_slot4 = CAN_MSG_POWER_DISPENSE_SLOT4; const uint8_t can_msg_power_dispense_slot4 = CAN_MSG_POWER_DISPENSE_SLOT4;
const uint8_t can_msg_power_dispense_slot5 = CAN_MSG_POWER_DISPENSE_SLOT5; const uint8_t can_msg_power_dispense_slot5 = CAN_MSG_POWER_DISPENSE_SLOT5;
const uint8_t can_msg_display_status = CAN_MSG_DISPLAY_STATUS;
const uint8_t can_msg_display_cmd = CAN_MSG_DISPLAY_CMD;
const uint16_t can_msg_auto_status = CAN_MSG_AUTO_STATUS; const uint16_t can_msg_auto_status = CAN_MSG_AUTO_STATUS;
const uint8_t can_msg_auto_status_disable = CAN_MSG_AUTO_STATUS_DISABLE; const uint8_t can_msg_auto_status_disable = CAN_MSG_AUTO_STATUS_DISABLE;
const uint8_t can_msg_auto_status_enable = CAN_MSG_AUTO_STATUS_ENABLE; const uint8_t can_msg_auto_status_enable = CAN_MSG_AUTO_STATUS_ENABLE;
@ -64,12 +67,15 @@ var (
type MessageType int type MessageType int
const ( const (
MessageTypeInvalid MessageType = iota MessageTypeInvalid MessageType = iota
MessageTypeFeedback MessageTypeFeedbackStatus
MessageTypeFeedbackRequest MessageTypeFeedbackRequest
MessageTypePower MessageTypePowerStatus
MessageTypePowerRequest MessageTypePowerRequest
MessageTypeDispense MessageTypeDispenseCommand
MessageTypeAuto MessageTypeDisplayStatus
MessageTypeDisplayRequest
MessageTypeDisplayCommand
MessageTypeAutoCommand
) )
// DecodeMessage decodes a CAN frame and returns an appropriate message // DecodeMessage decodes a CAN frame and returns an appropriate message
@ -83,26 +89,34 @@ const (
func DecodeMessage(frame can.Frame) (MessageType, interface{}, error) { func DecodeMessage(frame can.Frame) (MessageType, interface{}, error) {
switch frame.ID { switch frame.ID {
case uint32(C.can_msg_feedback_status): case uint32(C.can_msg_feedback_status):
msg, err := DecodeFeedbackMessage(frame) msg, err := DecodeFeedbackStatus(frame)
return MessageTypeFeedback, msg, err return MessageTypeFeedbackStatus, msg, err
case uint32(C.can_msg_feedback_status) | can.MaskRtr: case uint32(C.can_msg_feedback_status) | can.MaskRtr:
return MessageTypeFeedbackRequest, nil, nil return MessageTypeFeedbackRequest, nil, nil
case uint32(C.can_msg_power_status): case uint32(C.can_msg_power_status):
msg, err := DecodePowerMessage(frame) msg, err := DecodePowerStatus(frame)
return MessageTypePower, msg, err return MessageTypePowerStatus, msg, err
case uint32(C.can_msg_power_status) | can.MaskRtr: case uint32(C.can_msg_power_status) | can.MaskRtr:
return MessageTypePowerRequest, nil, nil return MessageTypePowerRequest, nil, nil
case uint32(C.can_msg_power_dispense): case uint32(C.can_msg_power_dispense):
msg, err := DecodeDispenseMessage(frame) msg, err := DecodeDispenseCommand(frame)
return MessageTypeDispense, msg, err return MessageTypeDispenseCommand, msg, err
case uint32(C.can_msg_display_status):
msg, err := DecodeDisplayStatus(frame)
return MessageTypeDisplayStatus, msg, err
case uint32(C.can_msg_display_status) | can.MaskRtr:
return MessageTypeDisplayRequest, nil, nil
case uint32(C.can_msg_display_cmd):
msg, err := DecodeDisplayCommand(frame)
return MessageTypeDisplayCommand, msg, err
case uint32(C.can_msg_auto_status): case uint32(C.can_msg_auto_status):
msg, err := DecodeAutoMessage(frame) msg, err := DecodeAutoCommand(frame)
return MessageTypeAuto, msg, err return MessageTypeAutoCommand, msg, err
} }
return MessageTypeInvalid, nil, UnsupportedMessageType return MessageTypeInvalid, nil, UnsupportedMessageType
} }
type FeedbackMessage struct { type FeedbackStatus struct {
EndD bool EndD bool
EndE bool EndE bool
EndF bool EndF bool
@ -116,14 +130,14 @@ type FeedbackMessage struct {
ResetSw bool ResetSw bool
} }
func RequestFeedbackMessage() can.Frame { func EncodeFeedbackRequest() can.Frame {
return can.Frame{ return can.Frame{
ID: uint32(C.can_msg_feedback_status) | can.MaskRtr, ID: uint32(C.can_msg_feedback_status) | can.MaskRtr,
} }
} }
func DecodeFeedbackMessage(frame can.Frame) (FeedbackMessage, error) { func DecodeFeedbackStatus(frame can.Frame) (FeedbackStatus, error) {
var ret FeedbackMessage var ret FeedbackStatus
if frame.ID != uint32(C.can_msg_feedback_status) { if frame.ID != uint32(C.can_msg_feedback_status) {
return ret, InvalidMessageID return ret, InvalidMessageID
} }
@ -144,8 +158,8 @@ func DecodeFeedbackMessage(frame can.Frame) (FeedbackMessage, error) {
return ret, nil return ret, nil
} }
func (f FeedbackMessage) Encode() can.Frame { func (f FeedbackStatus) Encode() can.Frame {
data := [8]uint8{} var data [8]uint8
if f.EndD { if f.EndD {
data[int(C.can_msg_feedback_status_field_end_d)] |= uint8(C.can_msg_feedback_status_bit_end_d) data[int(C.can_msg_feedback_status_field_end_d)] |= uint8(C.can_msg_feedback_status_bit_end_d)
} }
@ -186,18 +200,18 @@ func (f FeedbackMessage) Encode() can.Frame {
} }
} }
type PowerMessage struct { type PowerStatus struct {
Bits int Bits int
} }
func RequestPowerMessage() can.Frame { func EncodePowerRequest() can.Frame {
return can.Frame{ return can.Frame{
ID: uint32(C.can_msg_power_status) | can.MaskRtr, ID: uint32(C.can_msg_power_status) | can.MaskRtr,
} }
} }
func DecodePowerMessage(frame can.Frame) (PowerMessage, error) { func DecodePowerStatus(frame can.Frame) (PowerStatus, error) {
var ret PowerMessage var ret PowerStatus
if frame.ID != uint32(C.can_msg_power_status) { if frame.ID != uint32(C.can_msg_power_status) {
return ret, InvalidMessageID return ret, InvalidMessageID
} }
@ -208,8 +222,8 @@ func DecodePowerMessage(frame can.Frame) (PowerMessage, error) {
return ret, nil return ret, nil
} }
func (f PowerMessage) Encode() can.Frame { func (f PowerStatus) Encode() can.Frame {
data := [8]uint8{} var data [8]uint8
data[0] = uint8(f.Bits >> 8) data[0] = uint8(f.Bits >> 8)
data[1] = uint8(f.Bits) data[1] = uint8(f.Bits)
return can.Frame{ return can.Frame{
@ -221,12 +235,12 @@ func (f PowerMessage) Encode() can.Frame {
const DispenseSlotOff int = -1 const DispenseSlotOff int = -1
type DispenseMessage struct { type DispenseCommand struct {
Slot int Slot int
} }
func DecodeDispenseMessage(frame can.Frame) (DispenseMessage, error) { func DecodeDispenseCommand(frame can.Frame) (DispenseCommand, error) {
var ret DispenseMessage var ret DispenseCommand
if frame.ID != uint32(C.can_msg_power_dispense) { if frame.ID != uint32(C.can_msg_power_dispense) {
return ret, InvalidMessageID return ret, InvalidMessageID
} }
@ -250,8 +264,8 @@ func DecodeDispenseMessage(frame can.Frame) (DispenseMessage, error) {
return ret, nil return ret, nil
} }
func (f DispenseMessage) Encode() can.Frame { func (f DispenseCommand) Encode() can.Frame {
data := [8]uint8{} var data [8]uint8
switch f.Slot { switch f.Slot {
case DispenseSlotOff: case DispenseSlotOff:
data[0] = uint8(C.can_msg_power_dispense_off) data[0] = uint8(C.can_msg_power_dispense_off)
@ -273,12 +287,85 @@ func (f DispenseMessage) Encode() can.Frame {
} }
} }
type AutoMessage struct { type DisplayStatus struct {
Buttons []bool
}
func EncodeDisplayRequest() can.Frame {
return can.Frame{
ID: uint32(C.can_msg_display_status) | can.MaskRtr,
}
}
func DecodeDisplayStatus(frame can.Frame) (DisplayStatus, error) {
var ret DisplayStatus
if frame.ID != uint32(C.can_msg_display_status) {
return ret, InvalidMessageID
}
if frame.Length != 1 {
return ret, InvalidMessageLength
}
ret.Buttons = make([]bool, 8)
for i := uint(0); i < 8; i++ {
ret.Buttons[i] = frame.Data[0] & (1 << i) != 0;
}
return ret, nil
}
func (f DisplayStatus) Encode() can.Frame {
var data [8]uint8
for i := uint(0); i < 8; i++ {
if f.Buttons[i] {
data[0] |= (1 << i)
}
}
return can.Frame{
ID: uint32(C.can_msg_display_status),
Length: 1,
Data: data,
}
}
type DisplayCommand struct {
Command int
Data []byte
}
func DecodeDisplayCommand(frame can.Frame) (DisplayCommand, error) {
var ret DisplayCommand
if frame.ID != uint32(C.can_msg_display_cmd) {
return ret, InvalidMessageID
}
if frame.Length < 1 {
return ret, InvalidMessageLength
}
ret.Command = int(frame.Data[0])
ret.Data = make([]byte, frame.Length - 1)
copy(ret.Data, frame.Data[1:frame.Length-1])
return ret, nil
}
func (f DisplayCommand) Encode() can.Frame {
data := [8]uint8{}
data[0] = uint8(f.Command)
length := len(f.Data)
if length > 7 {
length = 7
}
copy(data[1:], f.Data[:length])
return can.Frame{
ID: uint32(C.can_msg_display_cmd),
Length: 1,
Data: data,
}
}
type AutoCommand struct {
AutoUpdate bool AutoUpdate bool
} }
func DecodeAutoMessage(frame can.Frame) (AutoMessage, error) { func DecodeAutoCommand(frame can.Frame) (AutoCommand, error) {
var ret AutoMessage var ret AutoCommand
if frame.ID != uint32(C.can_msg_auto_status) { if frame.ID != uint32(C.can_msg_auto_status) {
return ret, InvalidMessageID return ret, InvalidMessageID
} }
@ -292,7 +379,7 @@ func DecodeAutoMessage(frame can.Frame) (AutoMessage, error) {
return ret, nil return ret, nil
} }
func (f AutoMessage) Encode() can.Frame { func (f AutoCommand) Encode() can.Frame {
data := [8]uint8{} data := [8]uint8{}
if f.AutoUpdate { if f.AutoUpdate {
data[0] = uint8(C.can_msg_auto_status_enable) data[0] = uint8(C.can_msg_auto_status_enable)