last
This commit is contained in:
@@ -67,7 +67,7 @@ func NewDeviceManager(cfg *config.Config, hub *Hub) *DeviceManager {
|
|||||||
return &DeviceManager{
|
return &DeviceManager{
|
||||||
config: cfg,
|
config: cfg,
|
||||||
hub: hub,
|
hub: hub,
|
||||||
updateInterval: 200 * time.Millisecond, // Update status every second
|
updateInterval: 1 * time.Second, // Update status every second
|
||||||
stopChan: make(chan struct{}),
|
stopChan: make(chan struct{}),
|
||||||
freqThreshold: 25000, // 25 kHz default
|
freqThreshold: 25000, // 25 kHz default
|
||||||
autoTrackEnabled: true, // Enabled by default
|
autoTrackEnabled: true, // Enabled by default
|
||||||
@@ -130,7 +130,9 @@ func (dm *DeviceManager) Initialize() error {
|
|||||||
motorsMoving := dm.ultrabeamMotorsMoving
|
motorsMoving := dm.ultrabeamMotorsMoving
|
||||||
dm.ultrabeamStateMu.RUnlock()
|
dm.ultrabeamStateMu.RUnlock()
|
||||||
// Block transmit if motors are moving
|
// Block transmit if motors are moving
|
||||||
return motorsMoving == 0
|
allowed := motorsMoving == 0
|
||||||
|
log.Printf("FlexRadio PTT check: motorsMoving=%d, transmit=%v", motorsMoving, allowed)
|
||||||
|
return allowed
|
||||||
})
|
})
|
||||||
|
|
||||||
// Set callback for immediate frequency changes (no waiting for update cycle)
|
// Set callback for immediate frequency changes (no waiting for update cycle)
|
||||||
@@ -363,12 +365,26 @@ func (dm *DeviceManager) updateStatus() {
|
|||||||
dm.ultrabeamMotorsMoving = ubStatus.MotorsMoving
|
dm.ultrabeamMotorsMoving = ubStatus.MotorsMoving
|
||||||
dm.ultrabeamStateMu.Unlock()
|
dm.ultrabeamStateMu.Unlock()
|
||||||
|
|
||||||
// Log motor state changes
|
// Proactively update FlexRadio interlock when motor state changes
|
||||||
if previousMotors != ubStatus.MotorsMoving {
|
if previousMotors != ubStatus.MotorsMoving {
|
||||||
if ubStatus.MotorsMoving > 0 {
|
if ubStatus.MotorsMoving > 0 {
|
||||||
log.Printf("Ultrabeam: Motors STARTED (bitmask=%d)", ubStatus.MotorsMoving)
|
log.Printf("Ultrabeam: Motors STARTED (bitmask=%d)", ubStatus.MotorsMoving)
|
||||||
|
// PROACTIVELY block transmit - don't wait for PTT_REQUESTED
|
||||||
|
log.Printf("DEBUG: About to call ForceInterlockState(false), flexRadio=%v", dm.flexRadio != nil)
|
||||||
|
if dm.flexRadio != nil {
|
||||||
|
dm.flexRadio.ForceInterlockState(false)
|
||||||
|
} else {
|
||||||
|
log.Printf("DEBUG: FlexRadio is nil, cannot force interlock")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Ultrabeam: Motors STOPPED")
|
log.Printf("Ultrabeam: Motors STOPPED")
|
||||||
|
// PROACTIVELY allow transmit again
|
||||||
|
log.Printf("DEBUG: About to call ForceInterlockState(true), flexRadio=%v", dm.flexRadio != nil)
|
||||||
|
if dm.flexRadio != nil {
|
||||||
|
dm.flexRadio.ForceInterlockState(true)
|
||||||
|
} else {
|
||||||
|
log.Printf("DEBUG: FlexRadio is nil, cannot force interlock")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -467,6 +483,7 @@ func (dm *DeviceManager) updateStatus() {
|
|||||||
if dm.hub != nil {
|
if dm.hub != nil {
|
||||||
dm.hub.BroadcastStatusUpdate(status)
|
dm.hub.BroadcastStatusUpdate(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dm *DeviceManager) GetStatus() *SystemStatus {
|
func (dm *DeviceManager) GetStatus() *SystemStatus {
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ type Client struct {
|
|||||||
|
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
reader *bufio.Reader
|
reader *bufio.Reader
|
||||||
connMu sync.Mutex
|
connMu sync.Mutex // For connection management
|
||||||
|
writeMu sync.Mutex // For writing to connection (separate from reads)
|
||||||
|
|
||||||
interlockID string
|
interlockID string
|
||||||
interlockName string
|
interlockName string
|
||||||
@@ -144,10 +145,15 @@ func (c *Client) getNextSeq() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) sendCommand(cmd string) (string, error) {
|
func (c *Client) sendCommand(cmd string) (string, error) {
|
||||||
c.connMu.Lock()
|
// Use writeMu instead of connMu to avoid blocking on messageLoop reads
|
||||||
defer c.connMu.Unlock()
|
c.writeMu.Lock()
|
||||||
|
defer c.writeMu.Unlock()
|
||||||
|
|
||||||
if c.conn == nil {
|
c.connMu.Lock()
|
||||||
|
conn := c.conn
|
||||||
|
c.connMu.Unlock()
|
||||||
|
|
||||||
|
if conn == nil {
|
||||||
return "", fmt.Errorf("not connected")
|
return "", fmt.Errorf("not connected")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,10 +162,12 @@ func (c *Client) sendCommand(cmd string) (string, error) {
|
|||||||
|
|
||||||
log.Printf("FlexRadio TX: %s", strings.TrimSpace(fullCmd))
|
log.Printf("FlexRadio TX: %s", strings.TrimSpace(fullCmd))
|
||||||
|
|
||||||
_, err := c.conn.Write([]byte(fullCmd))
|
_, err := conn.Write([]byte(fullCmd))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
c.connMu.Lock()
|
||||||
c.conn = nil
|
c.conn = nil
|
||||||
c.reader = nil
|
c.reader = nil
|
||||||
|
c.connMu.Unlock()
|
||||||
return "", fmt.Errorf("failed to send command: %w", err)
|
return "", fmt.Errorf("failed to send command: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,6 +223,7 @@ func (c *Client) messageLoop() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("FlexRadio RX: %s", line)
|
||||||
c.handleMessage(line)
|
c.handleMessage(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,7 +334,7 @@ func (c *Client) handleStatus(msg string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) handleInterlockState(state string, _ map[string]string) {
|
func (c *Client) handleInterlockState(state string, statusMap map[string]string) {
|
||||||
log.Printf("FlexRadio: Interlock state changed to: %s", state)
|
log.Printf("FlexRadio: Interlock state changed to: %s", state)
|
||||||
|
|
||||||
c.statusMu.Lock()
|
c.statusMu.Lock()
|
||||||
@@ -410,3 +419,32 @@ func (c *Client) GetStatus() (*Status, error) {
|
|||||||
|
|
||||||
return &status, nil
|
return &status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForceInterlockState proactively sends ready/not_ready to the radio
|
||||||
|
// This is used when external conditions change (e.g., antenna motors start/stop)
|
||||||
|
func (c *Client) ForceInterlockState(allowed bool) {
|
||||||
|
c.interlockMu.RLock()
|
||||||
|
interlockID := c.interlockID
|
||||||
|
c.interlockMu.RUnlock()
|
||||||
|
|
||||||
|
if interlockID == "" {
|
||||||
|
log.Println("FlexRadio: No interlock ID, cannot force state")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if allowed {
|
||||||
|
log.Println("FlexRadio: PROACTIVE - Sending ready (motors stopped)")
|
||||||
|
c.sendCommand(fmt.Sprintf("interlock ready %s", interlockID))
|
||||||
|
// Update state immediately for UI
|
||||||
|
c.statusMu.Lock()
|
||||||
|
c.lastStatus.InterlockState = InterlockStateReady
|
||||||
|
c.statusMu.Unlock()
|
||||||
|
} else {
|
||||||
|
log.Println("FlexRadio: PROACTIVE - Sending not_ready (motors moving)")
|
||||||
|
c.sendCommand(fmt.Sprintf("interlock not_ready %s", interlockID))
|
||||||
|
// Update state immediately for UI
|
||||||
|
c.statusMu.Lock()
|
||||||
|
c.lastStatus.InterlockState = InterlockStateNotReady
|
||||||
|
c.statusMu.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user