diff --git a/sats_receiver/gr_modules/modules.py b/sats_receiver/gr_modules/modules.py index d71ad98..b6c55e0 100644 --- a/sats_receiver/gr_modules/modules.py +++ b/sats_receiver/gr_modules/modules.py @@ -38,8 +38,6 @@ def __init__(self, self.resamp_gcd = resamp_gcd = math.gcd(bandwidth, samp_rate) - self.blocks_copy = gr.blocks.copy(gr.gr.sizeof_gr_complex) - self.blocks_copy.set_enabled(self.enabled) self.freqshifter = gr.blocks.rotator_cc(2 * math.pi * (main_tune - frequency) / samp_rate) self.resampler = gr.filter.rational_resampler_ccc( interpolation=bandwidth // resamp_gcd, @@ -50,7 +48,6 @@ def __init__(self, self.connect( self, - self.blocks_copy, self.freqshifter, self.resampler, self, @@ -58,7 +55,6 @@ def __init__(self, def set_enabled(self, enabled): self.enabled = enabled - self.blocks_copy.set_enabled(enabled) def set_freq_offset(self, new_freq: Union[int, float]): self.freqshifter.set_phase_inc(2 * math.pi * (self.main_tune - new_freq) / self.samp_rate) @@ -291,6 +287,7 @@ def start(self, observation_key: str): for decoder in self.decoders: decoder.set_observation_key(observation_key) decoder.start() + self.radio.set_enabled(1) def stop(self): if self.is_runned: @@ -539,7 +536,6 @@ def start(self): for r in self.recorders: r.start(observation_key) - r.radio.set_enabled(1) def stop(self): if self.is_runned: diff --git a/sats_receiver/gr_modules/receiver.py b/sats_receiver/gr_modules/receiver.py index f5d3af7..a7d139e 100644 --- a/sats_receiver/gr_modules/receiver.py +++ b/sats_receiver/gr_modules/receiver.py @@ -39,15 +39,15 @@ def __init__(self, up, config: Mapping): self.ltz = dateutil.tz.tzlocal() self.flow = [] - self.signal_src = gr.blocks.null_source(gr.gr.sizeof_gr_complex) + self.connector = self.signal_src = gr.blocks.null_source(gr.gr.sizeof_gr_complex) self.flow.append(self.signal_src) if self.dc_block: - self.blocks_correctiq = gr.blocks.correctiq() + self.connector = self.blocks_correctiq = gr.blocks.correctiq() self.flow.append(self.blocks_correctiq) if self.decimation > 1: - self.decim = gr.filter.rational_resampler_ccc(interpolation=1, decimation=self.decimation, taps=[]) + self.connector = self.decim = gr.filter.rational_resampler_ccc(interpolation=1, decimation=self.decimation, taps=[]) self.flow.append(self.decim) self.src_null_sink = gr.blocks.null_sink(gr.gr.sizeof_gr_complex) @@ -116,9 +116,9 @@ def update_config(self, config: Mapping, force=False): for sat_name in to_remove_sats: sat = self.satellites[sat_name] self.up.scheduler.cancel(*sat.events) + if sat.is_runned: + self.disconnect(self.connector, sat) sat.stop() - if self.is_runned: - self.disconnect(self.flow[-2], sat) del self.satellites[sat_name] for sat_name in to_create_sats: @@ -140,9 +140,9 @@ def update_config(self, config: Mapping, force=False): continue if self.calculate_pass(sat): - if self.is_runned: - self.connect(self.flow[-2], sat) self.satellites[sat.name] = sat + if sat.is_runned: + self.connect(self.connector, sat) if to_remove_sats or to_create_sats: self.unlock() @@ -266,16 +266,24 @@ def is_active(self) -> bool: return any(x.is_runned for x in self.satellites.values()) + def set_source(self, src): + if self.connector == self.signal_src: + self.connector = src + self.signal_src = self.flow[0] = src + def start(self, max_noutput_items=10000000): if self.enabled and not self.is_runned: self.log.info('START tune=%sHz samp_rate=%sHz gain=%s biast=%s', utils.num_disp(self.tune, 3), utils.num_disp(self.samp_rate, 3), self.gain, self.biast) + for sat in self.satellites.values(): + if sat.is_runned: + self.disconnect(self.connector, sat) + try: - self.signal_src = gr.soapy.source(f'driver={self.source}{self.serial and f",serial={self.serial}"}', - 'fc32', 1, '', '', [''], ['']) - self.flow[0] = self.signal_src + self.set_source(gr.soapy.source(f'driver={self.source}{self.serial and f",serial={self.serial}"}', + 'fc32', 1, '', '', [''], [''])) except RuntimeError as e: self.log.error('cannot start: %s', e) @@ -295,9 +303,9 @@ def start(self, max_noutput_items=10000000): self.soapy_apply(0) self.connect(*self.flow) - for sat in self.satellites.values(): - self.connect(self.flow[-2], sat) + if sat.is_runned: + self.connect(self.connector, sat) super(SatsReceiver, self).start(max_noutput_items) self.is_runned = True @@ -314,19 +322,41 @@ def stop(self, sched_clear=True): super(SatsReceiver, self).stop() self.disconnect(*self.flow) - from_disc = self.flow[-2] - self.signal_src = gr.blocks.null_source(gr.gr.sizeof_gr_complex) - self.flow[0] = self.signal_src + conn = self.connector + self.set_source(gr.blocks.null_source(gr.gr.sizeof_gr_complex)) for sat in self.satellites.values(): if sched_clear: self.up.scheduler.cancel(*sat.events) + if self.is_runned and sat.is_runned: + try: + self.disconnect(conn, sat) + sat.log.warning('stop %s', conn.name()) + except ValueError as e: + sat.log.warning('stop %s fail: %s', conn.name(), e) sat.stop() - if self.is_runned: - self.disconnect(from_disc, sat) self.is_runned = False + def sat_attach(self, sat: modules.Satellite): + self.lock() + self.connect(self.connector, sat) + sat.log.warning('attach %s', self.connector.name()) + sat.start() + self.unlock() + + def sat_detach(self, sat: modules.Satellite): + try: + self.lock() + if sat.is_runned: + self.disconnect(self.connector, sat) + sat.log.warning('detach %s', self.connector.name()) + except ValueError as e: + sat.log.warning('detach %s fail: %s', self.connector.name(), e) + finally: + self.unlock() + sat.stop() + def action(self): if self.is_active and not self.start(): for sat in self.satellites.values(): @@ -368,8 +398,8 @@ def calculate_pass(self, sat: modules.Satellite): if set_t < rise_t: rise_t = t sat.events = [ - None if sat.is_runned else self.up.scheduler.plan(rise_t, sat.start), - self.up.scheduler.plan(set_t, sat.stop), + None if sat.is_runned else self.up.scheduler.plan(rise_t, self.sat_attach, sat), + self.up.scheduler.plan(set_t, self.sat_detach, sat), self.up.scheduler.plan(set_tt, self.calculate_pass, sat) ] self.log.info('Sat `%s` planned on %s <-> %s',