set default tab to help. add beep keys.

This commit is contained in:
legop3
2025-12-08 13:57:27 -05:00
parent 161929e280
commit 6580de08d4
20 changed files with 254 additions and 21 deletions
+12
View File
@@ -28,6 +28,7 @@ type inboundMessage struct {
Servo *servoPayload `json:"servo,omitempty"`
TTS *ttsPayload `json:"tts,omitempty"`
NightVision *nightVisionPayload `json:"nightVision,omitempty"`
Song *songPayload `json:"song,omitempty"`
}
type driveDirectPayload struct {
@@ -67,6 +68,17 @@ type nightVisionPayload struct {
Action string `json:"action"`
}
type songPayload struct {
Slot *int `json:"slot,omitempty"`
Notes []songNote `json:"notes"`
Loop bool `json:"loop,omitempty"`
}
type songNote struct {
Note int `json:"note"`
Duration int `json:"duration"`
}
type ackMessage struct {
Type string `json:"type"`
ID string `json:"id"`
+23
View File
@@ -95,3 +95,26 @@ func (s *SerialAdapter) SendRaw(raw []byte) error {
func (s *SerialAdapter) SeekDock() error {
return s.write([]byte{143})
}
func (s *SerialAdapter) PlaySong(slot int, notes []songNote) error {
if len(notes) == 0 {
return fmt.Errorf("song requires at least one note")
}
if len(notes) > 16 {
return fmt.Errorf("song supports up to 16 notes, got %d", len(notes))
}
if slot < 0 || slot > 4 {
return fmt.Errorf("song slot must be 0-4")
}
payload := []byte{140, byte(slot), byte(len(notes))}
for _, n := range notes {
note := clampInt(n.Note, 31, 127)
duration := clampInt(n.Duration, 1, 255)
payload = append(payload, byte(note), byte(duration))
}
if err := s.write(payload); err != nil {
return err
}
return s.write([]byte{141, byte(slot)})
}
+5
View File
@@ -56,3 +56,8 @@ func (s *SerialAdapter) SeekDock() error {
s.log.Printf("[dummy] seek dock")
return nil
}
func (s *SerialAdapter) PlaySong(slot int, notes []songNote) error {
s.log.Printf("[dummy] play song slot=%d notes=%v", slot, notes)
return nil
}
+6
View File
@@ -161,6 +161,12 @@ func (c *WSClient) dispatch(ctx context.Context, msg *inboundMessage) error {
return fmt.Errorf("night vision disabled")
}
return c.nightVision.HandleAction(msg.NightVision.Action)
case msg.Song != nil:
slot := 0
if msg.Song.Slot != nil {
slot = clampInt(*msg.Song.Slot, 0, 4)
}
return c.adapter.PlaySong(slot, msg.Song.Notes)
default:
return fmt.Errorf("unsupported command type: %s", msg.Type)
}