up
This commit is contained in:
@@ -29,22 +29,16 @@ type Client struct {
|
|||||||
running bool
|
running bool
|
||||||
stopChan chan struct{}
|
stopChan chan struct{}
|
||||||
|
|
||||||
// Interlock
|
|
||||||
interlockID string // ID retourné par la radio (ex: "000000F4")
|
|
||||||
interlockName string // Nom de notre interlock
|
|
||||||
interlockMu sync.RWMutex // Protection pour l'ID
|
|
||||||
|
|
||||||
// Callbacks
|
// Callbacks
|
||||||
onFrequencyChange func(freqMHz float64)
|
onFrequencyChange func(freqMHz float64)
|
||||||
checkTransmitAllowed func() bool // Returns true if transmit allowed (motors not moving)
|
checkTransmitAllowed func() bool // Returns true if transmit allowed (motors not moving)
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(host string, port int, interlockName string) *Client {
|
func New(host string, port int) *Client {
|
||||||
return &Client{
|
return &Client{
|
||||||
host: host,
|
host: host,
|
||||||
port: port,
|
port: port,
|
||||||
interlockName: interlockName,
|
stopChan: make(chan struct{}),
|
||||||
stopChan: make(chan struct{}),
|
|
||||||
lastStatus: &Status{
|
lastStatus: &Status{
|
||||||
Connected: false,
|
Connected: false,
|
||||||
},
|
},
|
||||||
@@ -105,12 +99,6 @@ func (c *Client) Start() error {
|
|||||||
// Start message listener
|
// Start message listener
|
||||||
go c.messageLoop()
|
go c.messageLoop()
|
||||||
|
|
||||||
// Create interlock
|
|
||||||
log.Printf("FlexRadio: Creating interlock '%s'...", c.interlockName)
|
|
||||||
if err := c.createInterlock(); err != nil {
|
|
||||||
log.Printf("FlexRadio: Warning - failed to create interlock: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subscribe to slice updates for frequency tracking
|
// Subscribe to slice updates for frequency tracking
|
||||||
log.Println("FlexRadio: Subscribing to slice updates...")
|
log.Println("FlexRadio: Subscribing to slice updates...")
|
||||||
_, err := c.sendCommand("sub slice all")
|
_, err := c.sendCommand("sub slice all")
|
||||||
@@ -276,17 +264,6 @@ func (c *Client) handleResponse(msg string) {
|
|||||||
log.Printf("FlexRadio: Command error: status=%s, message=%s", status, msg)
|
log.Printf("FlexRadio: Command error: status=%s, message=%s", status, msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this is interlock create response (has data in 3rd part)
|
|
||||||
if len(parts) >= 3 && parts[2] != "" {
|
|
||||||
interlockID := parts[2]
|
|
||||||
|
|
||||||
c.interlockMu.Lock()
|
|
||||||
c.interlockID = interlockID
|
|
||||||
c.interlockMu.Unlock()
|
|
||||||
|
|
||||||
log.Printf("FlexRadio: ✅ Interlock created successfully with ID: %s", interlockID)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) handleStatus(msg string) {
|
func (c *Client) handleStatus(msg string) {
|
||||||
@@ -331,22 +308,6 @@ func (c *Client) handleStatus(msg string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for interlock PTT_REQUESTED
|
|
||||||
// Format: S0|interlock ... state=PTT_REQUESTED ...
|
|
||||||
if strings.Contains(msg, "interlock") {
|
|
||||||
if state, ok := statusMap["state"]; ok {
|
|
||||||
|
|
||||||
// Update status for UI
|
|
||||||
c.statusMu.Lock()
|
|
||||||
c.lastStatus.InterlockState = state
|
|
||||||
c.statusMu.Unlock()
|
|
||||||
|
|
||||||
if state == "PTT_REQUESTED" {
|
|
||||||
// PTT requested - we MUST respond within 500ms!
|
|
||||||
c.handlePTTRequest()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetStatus() (*Status, error) {
|
func (c *Client) GetStatus() (*Status, error) {
|
||||||
@@ -365,61 +326,3 @@ func (c *Client) GetStatus() (*Status, error) {
|
|||||||
|
|
||||||
return &status, nil
|
return &status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// createInterlock creates an interlock on the radio
|
|
||||||
func (c *Client) createInterlock() error {
|
|
||||||
// Format: interlock create type=ANT name=<name> serial=ShackMaster
|
|
||||||
// Type ANT = External antenna controller (state always controlled by us)
|
|
||||||
cmd := fmt.Sprintf("interlock create type=ANT name=%s serial=ShackMaster", c.interlockName)
|
|
||||||
|
|
||||||
log.Printf("FlexRadio: Sending interlock create command: %s", cmd)
|
|
||||||
|
|
||||||
_, err := c.sendCommand(cmd)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to send interlock create: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The response will be parsed in handleResponse()
|
|
||||||
// Format: R<seq>|0|<interlock_id> (ex: R21|0|000000F4)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// handlePTTRequest is called when FlexRadio sends PTT_REQUESTED
|
|
||||||
// We MUST respond within 500ms with ready or not_ready
|
|
||||||
func (c *Client) handlePTTRequest() {
|
|
||||||
|
|
||||||
c.interlockMu.RLock()
|
|
||||||
interlockID := c.interlockID
|
|
||||||
c.interlockMu.RUnlock()
|
|
||||||
|
|
||||||
if interlockID == "" {
|
|
||||||
log.Println("FlexRadio: No interlock ID, cannot respond to PTT request!")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if transmit is allowed via callback
|
|
||||||
allowed := true
|
|
||||||
if c.checkTransmitAllowed != nil {
|
|
||||||
allowed = c.checkTransmitAllowed()
|
|
||||||
}
|
|
||||||
|
|
||||||
if allowed {
|
|
||||||
cmd := fmt.Sprintf("interlock ready %s", interlockID)
|
|
||||||
c.sendCommand(cmd)
|
|
||||||
|
|
||||||
// Update status immediately for UI
|
|
||||||
c.statusMu.Lock()
|
|
||||||
c.lastStatus.InterlockState = InterlockStateReady
|
|
||||||
c.statusMu.Unlock()
|
|
||||||
} else {
|
|
||||||
log.Println("FlexRadio: Transmit BLOCKED - sending 'not_ready'")
|
|
||||||
cmd := fmt.Sprintf("interlock not_ready %s", interlockID)
|
|
||||||
c.sendCommand(cmd)
|
|
||||||
|
|
||||||
// Update status immediately for UI
|
|
||||||
c.statusMu.Lock()
|
|
||||||
c.lastStatus.InterlockState = InterlockStateNotReady
|
|
||||||
c.statusMu.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user