UART FIND_ME (client_id 0 = local ring, >0 = unicast), ESPNOW_FIND_ME payload, CLI/dashboard buttons per slave. Co-authored-by: Cursor <cursoragent@cursor.com>
219 lines
6.2 KiB
Go
219 lines
6.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"google.golang.org/protobuf/proto"
|
|
|
|
"powerpod/gotool/pb"
|
|
)
|
|
|
|
func (m *managedSerial) getVersion() (*pb.VersionResponse, error) {
|
|
payload, err := m.exchange(byte(pb.MessageType_VERSION), "VERSION")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return decodeVersionPayload(payload)
|
|
}
|
|
|
|
func (m *managedSerial) getVersionPoll() (*pb.VersionResponse, error) {
|
|
payload, err := m.exchangePoll(byte(pb.MessageType_VERSION), "VERSION")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return decodeVersionPayload(payload)
|
|
}
|
|
|
|
func (m *managedSerial) listClients() ([]*pb.ClientInfo, error) {
|
|
payload, err := m.exchange(byte(pb.MessageType_CLIENT_INFO), "CLIENT_INFO")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return decodeClientsPayload(payload)
|
|
}
|
|
|
|
func (m *managedSerial) listClientsPoll() ([]*pb.ClientInfo, error) {
|
|
payload, err := m.exchangePoll(byte(pb.MessageType_CLIENT_INFO), "CLIENT_INFO")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return decodeClientsPayload(payload)
|
|
}
|
|
|
|
func (m *managedSerial) AccelDeadzone(req *pb.AccelDeadzoneRequest) (*pb.AccelDeadzoneResponse, error) {
|
|
return m.accelDeadzoneVia(m.withPort, req)
|
|
}
|
|
|
|
func (m *managedSerial) AccelDeadzonePoll(req *pb.AccelDeadzoneRequest) (*pb.AccelDeadzoneResponse, error) {
|
|
return m.accelDeadzoneVia(m.withPortPoll, req)
|
|
}
|
|
|
|
func (m *managedSerial) accelDeadzoneVia(
|
|
portFn func(func(*serialPort) error) error,
|
|
req *pb.AccelDeadzoneRequest,
|
|
) (*pb.AccelDeadzoneResponse, error) {
|
|
var resp *pb.AccelDeadzoneResponse
|
|
err := portFn(func(sp *serialPort) error {
|
|
var e error
|
|
resp, e = sp.AccelDeadzone(req)
|
|
return e
|
|
})
|
|
return resp, err
|
|
}
|
|
|
|
func (m *managedSerial) EspnowUnicastTest(clientID, seq uint32) (*pb.EspNowUnicastTestResponse, error) {
|
|
var resp *pb.EspNowUnicastTestResponse
|
|
err := m.withPort(func(sp *serialPort) error {
|
|
var e error
|
|
resp, e = sp.EspnowUnicastTest(clientID, seq)
|
|
return e
|
|
})
|
|
return resp, err
|
|
}
|
|
|
|
func decodeVersionPayload(payload []byte) (*pb.VersionResponse, error) {
|
|
var msg pb.UartMessage
|
|
if err := proto.Unmarshal(payload[1:], &msg); err != nil {
|
|
return nil, fmt.Errorf("decode: %w", err)
|
|
}
|
|
if msg.GetType() != pb.MessageType_VERSION {
|
|
return nil, fmt.Errorf("unexpected type %v", msg.GetType())
|
|
}
|
|
ver := msg.GetVersionResponse()
|
|
if ver == nil {
|
|
return nil, fmt.Errorf("missing version_response")
|
|
}
|
|
return ver, nil
|
|
}
|
|
|
|
func decodeClientsPayload(payload []byte) ([]*pb.ClientInfo, error) {
|
|
var msg pb.UartMessage
|
|
if err := proto.Unmarshal(payload[1:], &msg); err != nil {
|
|
return nil, fmt.Errorf("decode: %w", err)
|
|
}
|
|
if msg.GetType() != pb.MessageType_CLIENT_INFO {
|
|
return nil, fmt.Errorf("unexpected type %v", msg.GetType())
|
|
}
|
|
info := msg.GetClientInfoResponse()
|
|
if info == nil {
|
|
return nil, fmt.Errorf("missing client_info_response")
|
|
}
|
|
return info.GetClients(), nil
|
|
}
|
|
|
|
func (s *serialPort) getVersion() (*pb.VersionResponse, error) {
|
|
payload, err := s.exchange(byte(pb.MessageType_VERSION), "VERSION")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return decodeVersionPayload(payload)
|
|
}
|
|
|
|
func (s *serialPort) listClients() ([]*pb.ClientInfo, error) {
|
|
payload, err := s.exchange(byte(pb.MessageType_CLIENT_INFO), "CLIENT_INFO")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return decodeClientsPayload(payload)
|
|
}
|
|
|
|
func (s *serialPort) accelDeadzone(req *pb.AccelDeadzoneRequest) (*pb.AccelDeadzoneResponse, error) {
|
|
msg := &pb.UartMessage{
|
|
Type: pb.MessageType_ACCEL_DEADZONE,
|
|
Payload: &pb.UartMessage_AccelDeadzoneRequest{
|
|
AccelDeadzoneRequest: req,
|
|
},
|
|
}
|
|
body, err := proto.Marshal(msg)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("encode: %w", err)
|
|
}
|
|
payload := append([]byte{byte(pb.MessageType_ACCEL_DEADZONE)}, body...)
|
|
respPayload, err := s.exchangePayload(payload, "ACCEL_DEADZONE")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var respMsg pb.UartMessage
|
|
if err := proto.Unmarshal(respPayload[1:], &respMsg); err != nil {
|
|
return nil, fmt.Errorf("decode: %w", err)
|
|
}
|
|
r := respMsg.GetAccelDeadzoneResponse()
|
|
if r == nil {
|
|
return nil, fmt.Errorf("missing accel_deadzone_response")
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func (s *serialPort) espnowUnicastTest(clientID, seq uint32) (*pb.EspNowUnicastTestResponse, error) {
|
|
req := &pb.EspNowUnicastTestRequest{ClientId: clientID, Seq: seq}
|
|
msg := &pb.UartMessage{
|
|
Type: pb.MessageType_ESPNOW_UNICAST_TEST,
|
|
Payload: &pb.UartMessage_EspnowUnicastTestRequest{
|
|
EspnowUnicastTestRequest: req,
|
|
},
|
|
}
|
|
body, err := proto.Marshal(msg)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("encode: %w", err)
|
|
}
|
|
payload := append([]byte{byte(pb.MessageType_ESPNOW_UNICAST_TEST)}, body...)
|
|
respPayload, err := s.exchangePayload(payload, "ESPNOW_UNICAST_TEST")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var respMsg pb.UartMessage
|
|
if err := proto.Unmarshal(respPayload[1:], &respMsg); err != nil {
|
|
return nil, fmt.Errorf("decode: %w", err)
|
|
}
|
|
r := respMsg.GetEspnowUnicastTestResponse()
|
|
if r == nil {
|
|
return nil, fmt.Errorf("missing espnow_unicast_test_response")
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func (m *managedSerial) FindMe(clientID uint32) error {
|
|
return m.withPort(func(sp *serialPort) error {
|
|
return runFindMeClient(sp, clientID)
|
|
})
|
|
}
|
|
|
|
func (s *serialPort) ledRingProgress(req *pb.LedRingProgressRequest) (*pb.LedRingProgressResponse, error) {
|
|
msg := &pb.UartMessage{
|
|
Type: pb.MessageType_LED_RING,
|
|
Payload: &pb.UartMessage_LedRingProgressRequest{
|
|
LedRingProgressRequest: req,
|
|
},
|
|
}
|
|
body, err := proto.Marshal(msg)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("encode: %w", err)
|
|
}
|
|
payload := append([]byte{byte(pb.MessageType_LED_RING)}, body...)
|
|
respPayload, err := s.exchangePayload(payload, "LED_RING")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var respMsg pb.UartMessage
|
|
if err := proto.Unmarshal(respPayload[1:], &respMsg); err != nil {
|
|
return nil, fmt.Errorf("decode: %w", err)
|
|
}
|
|
r := respMsg.GetLedRingProgressResponse()
|
|
if r == nil {
|
|
return nil, fmt.Errorf("missing led_ring_progress_response")
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func (s *serialPort) GetVersion() (*pb.VersionResponse, error) { return s.getVersion() }
|
|
|
|
func (s *serialPort) ListClients() ([]*pb.ClientInfo, error) { return s.listClients() }
|
|
|
|
func (s *serialPort) AccelDeadzone(req *pb.AccelDeadzoneRequest) (*pb.AccelDeadzoneResponse, error) {
|
|
return s.accelDeadzone(req)
|
|
}
|
|
|
|
func (s *serialPort) EspnowUnicastTest(clientID, seq uint32) (*pb.EspNowUnicastTestResponse, error) {
|
|
return s.espnowUnicastTest(clientID, seq)
|
|
}
|