feat: radio duplex/offset/tone control + tune_repeater
This commit is contained in:
@@ -156,3 +156,51 @@ class Radio:
|
|||||||
def squelch_open(self):
|
def squelch_open(self):
|
||||||
data = self.transact(civ.CMD_METER, bytes([civ.SUB_SQL_STATUS])).data
|
data = self.transact(civ.CMD_METER, bytes([civ.SUB_SQL_STATUS])).data
|
||||||
return bool(data[1]) if len(data) > 1 else False
|
return bool(data[1]) if len(data) > 1 else False
|
||||||
|
|
||||||
|
# ---- repeater config (candidate commands; verify live) ----------------
|
||||||
|
def set_duplex(self, direction):
|
||||||
|
"""direction: '+', '-', or 'simplex'."""
|
||||||
|
code = {"+": civ.DUP_PLUS, "-": civ.DUP_MINUS,
|
||||||
|
"simplex": civ.DUP_SIMPLEX}.get(direction)
|
||||||
|
if code is None:
|
||||||
|
raise ValueError(f"bad duplex {direction!r}")
|
||||||
|
return self._command(civ.CMD_DUPLEX, bytes([code]))
|
||||||
|
|
||||||
|
def set_offset(self, hz):
|
||||||
|
return self._command(civ.CMD_OFFSET, civ.offset_to_bcd(hz))
|
||||||
|
|
||||||
|
def get_offset(self):
|
||||||
|
return civ.bcd_to_offset(self.transact(civ.CMD_OFFSET).data)
|
||||||
|
|
||||||
|
def set_tone(self, hz):
|
||||||
|
return self._command(civ.CMD_TONE_PARAM,
|
||||||
|
bytes([civ.SUB_RPT_TONE]) + civ.tone_to_bcd(hz))
|
||||||
|
|
||||||
|
def get_tone(self):
|
||||||
|
return civ.bcd_to_tone(self.transact(civ.CMD_TONE_PARAM,
|
||||||
|
bytes([civ.SUB_RPT_TONE])).data[1:])
|
||||||
|
|
||||||
|
def set_tone_on(self, on):
|
||||||
|
return self._command(civ.CMD_TONE_SWITCH,
|
||||||
|
bytes([civ.SUB_TONE_ENC, 0x01 if on else 0x00]))
|
||||||
|
|
||||||
|
def tune_repeater(self, rec):
|
||||||
|
"""Apply a normalized record: freq -> duplex/offset -> tone.
|
||||||
|
Returns (steps, errors): each step True/False; errors keyed by step."""
|
||||||
|
steps, errors = {}, {}
|
||||||
|
|
||||||
|
def attempt(name, fn):
|
||||||
|
try:
|
||||||
|
fn(); steps[name] = True
|
||||||
|
except (CIVError, ValueError, OSError) as e:
|
||||||
|
steps[name] = False; errors[name] = str(e)
|
||||||
|
|
||||||
|
attempt("freq", lambda: self.set_frequency(int(round(rec["output_mhz"] * 1e6))))
|
||||||
|
duplex = rec.get("duplex", "simplex")
|
||||||
|
attempt("duplex", lambda: self.set_duplex(duplex))
|
||||||
|
if duplex != "simplex":
|
||||||
|
attempt("offset", lambda: self.set_offset(int(round(rec.get("offset_mhz", 0) * 1e6))))
|
||||||
|
if rec.get("tone_mode") == "ctcss" and rec.get("tone_hz"):
|
||||||
|
attempt("tone_freq", lambda: self.set_tone(rec["tone_hz"]))
|
||||||
|
attempt("tone_on", lambda: self.set_tone_on(True))
|
||||||
|
return steps, errors
|
||||||
|
|||||||
Reference in New Issue
Block a user