Better CAN message naming, added display support
This commit is contained in:
parent
0107ee5129
commit
bdaa925100
2 changed files with 137 additions and 53 deletions
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue