package udp import ( "bytes" "encoding/binary" "fmt" "strings" "hamlog/internal/applog" ) // WSJT-X Halt Tx (message type 8) — "stop transmitting". // // The same two things the Halt Tx button and the Enable Tx toggle do in the // application's own window: // // Halt Tx type 8 // id utf8 the target application's own id // auto_tx_only bool false = stop the transmission NOW // true = let this over finish, then stop auto-Tx // // Both are useful and they are not the same operation. Stopping mid-over is what // you want when you have called the wrong station or realised the frequency is // occupied; finishing the over first is what you want when the QSO is complete // and cutting the transmission would leave the other end waiting for a report // that never lands. const wsjtMsgHaltTx = 8 // EncodeHaltTx builds the datagram. autoTxOnly false halts immediately. func EncodeHaltTx(programID string, autoTxOnly bool) []byte { var b bytes.Buffer _ = binary.Write(&b, binary.BigEndian, uint32(wsjtMagic)) _ = binary.Write(&b, binary.BigEndian, uint32(2)) // schema 2 — what every current sender speaks _ = binary.Write(&b, binary.BigEndian, uint32(wsjtMsgHaltTx)) writeQString(&b, programID) var auto uint8 if autoTxOnly { auto = 1 } _ = binary.Write(&b, binary.BigEndian, auto) return b.Bytes() } // SendHaltTx tells one decoding application to stop transmitting. // // Routed by PROGRAM ID and answered back to the address that instance's packets // arrive from, exactly like SendReply: two receivers can share one multicast // group, and halting the 20 m instance because the 6 m one is transmitting would // be worse than doing nothing. func (m *Manager) SendHaltTx(programID string, autoTxOnly bool) error { if strings.TrimSpace(programID) == "" { return fmt.Errorf("no application id — cannot tell which receiver to halt") } m.mu.Lock() servers := make([]*Server, 0, len(m.inbound)) for _, s := range m.inbound { servers = append(servers, s) } m.mu.Unlock() for _, s := range servers { conn, addr := s.replyTarget(programID) if conn == nil || addr == nil { continue } if _, err := conn.WriteToUDP(EncodeHaltTx(programID, autoTxOnly), addr); err != nil { return fmt.Errorf("send halt to %s at %s: %w", programID, addr, err) } applog.Printf("udp: halt tx sent to %s at %s (auto_tx_only=%v)", programID, addr, autoTxOnly) return nil } return fmt.Errorf("no packet has arrived from %q yet — nothing to halt", programID) }