mirror of https://github.com/ftl/tetra-pei
add commands to control the radio terminal
parent
a20458a904
commit
8d6b674382
@ -0,0 +1,68 @@
|
|||||||
|
package ctrl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ftl/tetra-pei/tetra"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetOperatingMode according to [PEI] 6.14.7.2
|
||||||
|
func SetOperatingMode(mode AIMode) string {
|
||||||
|
return fmt.Sprintf("AT+CTOM=%d", mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
var requestOperatingModeResponse = regexp.MustCompile(`^\+CTOM: (\d+)$`)
|
||||||
|
|
||||||
|
// RequestOperatingMode reads the current operating mode according to [PEI] 6.14.7.4
|
||||||
|
func RequestOperatingMode(ctx context.Context, requester tetra.Requester) (AIMode, error) {
|
||||||
|
responses, err := requester.Request(ctx, "AT+CTOM?")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if len(responses) < 1 {
|
||||||
|
return 0, fmt.Errorf("no response received")
|
||||||
|
}
|
||||||
|
response := strings.ToUpper(strings.TrimSpace(responses[0]))
|
||||||
|
parts := requestOperatingModeResponse.FindStringSubmatch(response)
|
||||||
|
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return 0, fmt.Errorf("unexpected response: %s", responses[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := strconv.Atoi(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return AIMode(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTalkgroup according to [PEI] 6.15.6.2
|
||||||
|
func SetTalkgroup(gtsi string) string {
|
||||||
|
return fmt.Sprintf("AT+CTGS=1,%s", gtsi)
|
||||||
|
}
|
||||||
|
|
||||||
|
var requestTalkgroupResponse = regexp.MustCompile(`^\+CTGS: .*,(\d+)$`)
|
||||||
|
|
||||||
|
// RequestTalkgroup reads the current talkgroup according to [PEI] 6.15.6.4
|
||||||
|
func RequestTalkgroup(ctx context.Context, requester tetra.Requester) (string, error) {
|
||||||
|
responses, err := requester.Request(ctx, "AT+CTGS?")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if len(responses) < 1 {
|
||||||
|
return "", fmt.Errorf("no response received")
|
||||||
|
}
|
||||||
|
response := strings.ToUpper(strings.TrimSpace(responses[0]))
|
||||||
|
parts := requestTalkgroupResponse.FindStringSubmatch(response)
|
||||||
|
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return "", fmt.Errorf("unexpected response: %s", responses[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts[1], nil
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package ctrl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AIModeByName returns the AIMode with the given name
|
||||||
|
func AIModeByName(name string) (AIMode, error) {
|
||||||
|
sanitized := strings.ToUpper(strings.TrimSpace(name))
|
||||||
|
result, ok := AIModesByName[sanitized]
|
||||||
|
if !ok {
|
||||||
|
return 0, fmt.Errorf("invalid operating mode %s", name)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AIMode represents an operating mode according to [PEI] 6.17.4
|
||||||
|
type AIMode byte
|
||||||
|
|
||||||
|
func (m AIMode) String() string {
|
||||||
|
for k, v := range AIModesByName {
|
||||||
|
if v == m {
|
||||||
|
return k
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "UNKNOWN"
|
||||||
|
}
|
||||||
|
|
||||||
|
// All supported operating modes
|
||||||
|
const (
|
||||||
|
TMO AIMode = iota
|
||||||
|
DMO
|
||||||
|
)
|
||||||
|
|
||||||
|
// AIModesByName maps all supported operating modes by their string representation
|
||||||
|
var AIModesByName = map[string]AIMode{
|
||||||
|
"TMO": TMO,
|
||||||
|
"DMO": DMO,
|
||||||
|
}
|
Loading…
Reference in New Issue