def test_sample_data(self): sampleJson = json.loads(TEST_SAMPLE1) sample = Sample() sample.fromJson(sampleJson) self.assertEqual(sampleJson['s']['t'], sample.tick) sampleCount = len(sampleJson['s']['meta']) self.assertEqual(sampleCount, len(sample.metas.channel_metas)) self.assertEqual(sampleCount, len(sample.samples)) metaJson = sampleJson["s"]["meta"] sampleIndex = 0 for m in metaJson: self.assertEqual(m['nm'], sample.samples[sampleIndex].channelMeta.name) self.assertEqual(m['ut'], sample.samples[sampleIndex].channelMeta.units) self.assertEqual(m['sr'], sample.samples[sampleIndex].channelMeta.sampleRate) sampleIndex += 1 sampleIndex = 0 dataJson = sampleJson['s']['d'] for sampleItem in sample.samples: value = dataJson[sampleIndex] self.assertEqual(value, sampleItem.value) sampleIndex += 1
def test_mixed_listeners(self): def listener3(value): self.listenerVal3 = value def listener4(value): self.listenerVal4 = value sample = Sample() metaRpm = ChannelMeta(name='RPM') metaEngineTemp = ChannelMeta(name='EngineTemp') sample.channel_metas = [metaRpm, metaEngineTemp] sample.samples = [SampleValue(1111, metaRpm)] dataBus = DataBus() dataBus.addChannelListener('RPM', listener3) dataBus.addChannelListener('EngineTemp', listener4) dataBus.update_samples(sample) dataBus.notify_listeners(None) #ensure we don't set the wrong listener self.assertEqual(self.listenerVal3, 1111) self.assertEqual(self.listenerVal4, None) sample.samples = [SampleValue(1111, metaRpm), SampleValue(199, metaEngineTemp)] dataBus.update_samples(sample) dataBus.notify_listeners(None) #ensure we don't affect unrelated channels self.assertEqual(self.listenerVal3, 1111) self.assertEqual(self.listenerVal4, 199)
def test_no_listener(self): sample = Sample() meta = ChannelMeta(name='EngineTemp') sample.channel_metas = [meta] sample.samples = [SampleValue(200, meta)] dataBus = DataBus() dataBus.update_samples(sample) dataBus.notify_listeners(None)
def test_update_value(self): dataBus = DataBus() sample = Sample() meta = ChannelMeta(name='RPM') sample.channel_metas = [meta] sample.samples = [SampleValue(1234, meta)] dataBus.update_samples(sample) dataBus.notify_listeners(None) value = dataBus.getData('RPM') self.assertEqual(value, 1234)
def test_listener(self): def listener(value): self.listenerVal0 = value sample = Sample() meta = ChannelMeta(name='RPM') sample.channel_metas = [meta] sample.samples = [SampleValue(1111, meta)] dataBus = DataBus() dataBus.addChannelListener('RPM', listener) dataBus.update_samples(sample) dataBus.notify_listeners(None) self.assertEqual(self.listenerVal0, 1111)
def __init__(self, **kwargs): super(DataBusPump, self).__init__(**kwargs) self._rc_api = None self._data_bus = None self.sample = Sample() self._sample_event = Event() self._poll = Event() self._sample_thread = None self._meta_is_stale_counter = 0 self.rc_capabilities = None self._should_run = False self._running = False self._starting = False self._auto_streaming_supported = False self._current_view = None self._is_recording = False
class DataBusPump(object): """Responsible for dispatching raw JSON API messages into a format the DataBus can consume. Attempts to detect asynchronous messaging mode, where messages are streamed to the DataBusPump. If Async mode not detected, a polling thread is created to simulate this. """ _rc_api = None _data_bus = None sample = Sample() _sample_event = Event() _running = Event() _sample_thread = None _meta_is_stale_counter = 0 def __init__(self, **kwargs): super(DataBusPump, self).__init__(**kwargs) def startDataPump(self, data_bus, rc_api): if self._sample_thread == None: self._rc_api = rc_api self._data_bus = data_bus rc_api.addListener('s', self.on_sample) rc_api.addListener('meta', self.on_meta) self._running.set() self._sample_thread = Thread(target=self.sample_worker) self._sample_thread.daemon = True self._sample_thread.start() else: #we're already running, refresh channel meta data self.meta_is_stale() def on_meta(self, meta_json): metas = self.sample.metas metas.fromJson(meta_json.get('meta')) self._data_bus.update_channel_meta(metas) self._meta_is_stale_counter = 0 def on_sample(self, sample_json): sample = self.sample dataBus = self._data_bus try: sample.fromJson(sample_json) dataBus.update_samples(sample) if sample.updated_meta: dataBus.update_channel_meta(sample.metas) self._sample_event.set() except SampleMetaException: #this is to prevent repeated sample meta requests self._request_meta_handler() def _request_meta_handler(self): if self._meta_is_stale_counter <= 0: Logger.info('DataBusPump: Sample Meta is stale, requesting meta') self._meta_is_stale_counter = SAMPLES_TO_WAIT_FOR_META self.request_meta() else: self._meta_is_stale_counter -= 1 def stopDataPump(self): self._running.clear() self._sample_thread.join() def meta_is_stale(self): self.request_meta() def request_meta(self): self._rc_api.get_meta() def sample_worker(self): rc_api = self._rc_api sample_event = self._sample_event Logger.info('DataBusPump: DataBus Sampler Starting') sample_event.clear() if sample_event.wait(SAMPLE_POLL_TEST_TIMEOUT) == True: Logger.info('DataBusPump: Async sampling detected') else: Logger.info('DataBusPump: Synchronous sampling mode enabled') while self._running.is_set(): try: #the timeout here is designed to be longer than the streaming rate of #RaceCapture. If we don't get an asynchronous sample, then we will timeout #and request a sample anyway. rc_api.sample() sample_event.wait(SAMPLE_POLL_EVENT_TIMEOUT) sample_event.clear() sleep(SAMPLE_POLL_INTERVAL_TIMEOUT) except Exception as e: sleep(SAMPLE_POLL_EXCEPTION_RECOVERY) Logger.error('DataBusPump: Exception in sample_worker: ' + str(e)) finally: sample_event.clear() Logger.info('DataBusPump: DataBus Sampler Exiting') safe_thread_exit()
class DataBusPump(object): """Responsible for dispatching raw JSON API messages into a format the DataBus can consume. Attempts to detect asynchronous messaging mode, where messages are streamed to the DataBusPump. If Async mode not detected, a polling thread is created to simulate this. """ _rc_api = None _data_bus = None sample = Sample() _sample_event = Event() _running = Event() _sample_thread = None _meta_is_stale_counter = 0 def __init__(self, **kwargs): super(DataBusPump, self).__init__(**kwargs) def start(self, data_bus, rc_api, streaming_supported): if self._running.is_set(): # since we're already running, simply # request updated metadata self.meta_is_stale() return self._rc_api = rc_api self._data_bus = data_bus rc_api.addListener('s', self.on_sample) rc_api.addListener('meta', self.on_meta) self._running.set() # Only BT supports auto-streaming data, the rest we have to poll if not streaming_supported: t = Thread(target=self.sample_worker) t.start() self._sample_thread = t def stop(self): self._running.clear() try: if self._sample_thread is not None: self._sample_thread.join() except Exception as e: Logger.warning( 'DataBusPump: Failed to join sample_worker: {}'.format(e)) def on_meta(self, meta_json): metas = self.sample.metas metas.fromJson(meta_json.get('meta')) self._data_bus.update_channel_meta(metas) self._meta_is_stale_counter = 0 def on_sample(self, sample_json): sample = self.sample dataBus = self._data_bus try: sample.fromJson(sample_json) if sample.updated_meta: dataBus.update_channel_meta(sample.metas) dataBus.update_samples(sample) self._sample_event.set() except SampleMetaException: # this is to prevent repeated sample meta requests self._request_meta_handler() def _request_meta_handler(self): if self._meta_is_stale_counter <= 0: Logger.info('DataBusPump: Sample Meta is stale, requesting meta') self._meta_is_stale_counter = SAMPLES_TO_WAIT_FOR_META self.request_meta() else: self._meta_is_stale_counter -= 1 def stopDataPump(self): self._running.clear() self._sample_thread.join() def meta_is_stale(self): self.request_meta() def request_meta(self): self._rc_api.get_meta() def sample_worker(self): rc_api = self._rc_api Logger.info('DataBusPump: sample_worker starting') while self._running.is_set(): try: rc_api.sample() sleep(SAMPLE_POLL_INTERVAL_TIMEOUT) except Exception as e: Logger.error('DataBusPump: Exception in sample_worker: ' + str(e)) sleep(SAMPLE_POLL_EXCEPTION_RECOVERY) Logger.info('DataBusPump: sample_worker exiting') safe_thread_exit()