def test_bad_truew(self): for i in range(len(BAD_CRSE)): with self.assertLogs(logging.getLogger(), logging.WARNING): result = truew(crse=BAD_CRSE[i], cspd=BAD_CSPD[i], hd=BAD_HD[i], wdir=BAD_WDIR[i], wspd=BAD_WSPD[i], zlr=ZLR, wmis=WMIS) self.assertEqual(result, (None, None, None))
def test_truew(self): for i in range(len(CRSE)): (tdir, tspd, adir) = truew(crse=CRSE[i], cspd=CSPD[i], hd=HD[i], wdir=WDIR[i], wspd=WSPD[i], zlr=ZLR, wmis=WMIS) self.assertAlmostEqual(tdir, VALUES[i][0], delta=0.0001) self.assertAlmostEqual(tspd, VALUES[i][1], delta=0.0001) self.assertAlmostEqual(adir, VALUES[i][2], delta=0.0001)
def transform(self, value_dict, timestamp_dict=None): """Incorporate any useable fields in this record, and if it gives us a new true wind value, return the results.""" if not value_dict or type(value_dict) is not dict: logging.warning('Improper type for value dict: %s', type(value_dict)) return None if timestamp_dict and type(timestamp_dict) is not dict: logging.warning('Improper type for timestamp dict: %s', type(timestamp_dict)) return None update = False course_val = value_dict.get(self.course_field, None) speed_val = value_dict.get(self.speed_field, None) heading_val = value_dict.get(self.heading_field, None) wind_dir_val = value_dict.get(self.wind_dir_field, None) wind_speed_val = value_dict.get(self.wind_speed_field, None) if None in (course_val, speed_val, heading_val, wind_dir_val, wind_speed_val): logging.debug('Not all required values for true winds are present') return None # If we have timestamps, check our most recent timestamps against # what's passed in the dictionary. if not timestamp_dict: update = True else: new_course_val_time = timestamp_dict.get(self.course_field, 0) if new_course_val_time > self.course_val_time: self.course_val_time = new_course_val_time if not self.update_on_fields or \ self.course_field in self.update_on_fields: update = True new_speed_val_time = timestamp_dict.get(self.speed_field, 0) if new_speed_val_time > self.speed_val_time: self.speed_val_time = new_speed_val_time if not self.update_on_fields or \ self.speed_field in self.update_on_fields: update = True new_heading_val_time = timestamp_dict.get(self.heading_field, 0) if new_heading_val_time > self.heading_val_time: self.heading_val_time = new_heading_val_time if not self.update_on_fields or \ self.heading_field in self.update_on_fields: update = True new_wind_dir_val_time = timestamp_dict.get(self.wind_dir_field, 0) if new_wind_dir_val_time > self.wind_dir_val_time: self.wind_dir_val_time = new_wind_dir_val_time if not self.update_on_fields or \ self.wind_dir_field in self.update_on_fields: update = True new_wind_speed_val_time = timestamp_dict.get( self.wind_speed_field, 0) if new_wind_speed_val_time > self.wind_speed_val_time: self.wind_speed_val_time = new_wind_speed_val_time if not self.update_on_fields or \ self.wind_speed_field in self.update_on_fields: update = True # If we've not seen anything that updates fields that would # trigger a new true winds value, return None. if not update: return None speed_val *= self.convert_speed_factor wind_speed_val *= self.convert_wind_factor logging.info('Computing new true winds') (true_dir, true_speed, apparent_dir) = truew(crse=course_val, cspd=speed_val, hd=heading_val, wdir=wind_dir_val, zlr=self.zero_line_reference, wspd=wind_speed_val) logging.info('Got true winds: dir: %s, speed: %s, apparent_dir: %s', true_dir, true_speed, apparent_dir) if None in (true_dir, true_speed, apparent_dir): logging.info('Got invalid true winds') return None # If here, we've got a valid new true wind result return { self.true_dir_name: true_dir, self.true_speed_name: true_speed, self.apparent_dir_name: apparent_dir }
def transform(self, record): """Incorporate any useable fields in this record, and if it gives us a new true wind value, return the results.""" if record is None: return None # If we've got a list, hope it's a list of records. Recurse, # calling transform() on each of the list elements in order and # return the resulting list. if type(record) is list: results = [] for single_record in record: results.append(self.transform(single_record)) return results results = [] for das_record in to_das_record_list(record): # If they haven't specified specific fields we should wait for # before updates, plan to emit an update after every new record # we process. Otherwise, assume we're not going to update unless # we see one of the named fields. if not self.update_on_fields: update = True else: update = False timestamp = das_record.timestamp if not timestamp: logging.info('DASRecord is missing timestamp - skipping') continue # Get latest values for any of our fields fields = das_record.fields if self.course_field in fields: if timestamp >= self.course_val_time: self.course_val = fields.get(self.course_field) self.course_val_time = timestamp if self.course_field in self.update_on_fields: update = True if self.speed_field in fields: if timestamp >= self.speed_val_time: self.speed_val = fields.get(self.speed_field) self.speed_val *= self.convert_speed_factor self.speed_val_time = timestamp if self.speed_field in self.update_on_fields: update = True if self.heading_field in fields: if timestamp >= self.heading_val_time: self.heading_val = fields.get(self.heading_field) self.heading_val_time = timestamp if self.heading_field in self.update_on_fields: update = True if self.wind_dir_field in fields: if timestamp >= self.wind_dir_val_time: self.wind_dir_val = fields.get(self.wind_dir_field) self.wind_dir_val_time = timestamp if self.wind_dir_field in self.update_on_fields: update = True if self.wind_speed_field in fields: if timestamp >= self.wind_speed_val_time: self.wind_speed_val = fields.get(self.wind_speed_field) self.wind_speed_val *= self.convert_wind_factor self.wind_speed_val_time = timestamp if self.wind_speed_field in self.update_on_fields: update = True if None in (self.course_val, self.speed_val, self.heading_val, self.wind_dir_val, self.wind_speed_val): logging.debug( 'Not all required values for true winds are present: ' 'time: %s: %s: %s, %s: %s, %s: %s, %s: %s, %s: %s', timestamp, self.course_field, self.course_val, self.speed_field, self.speed_val, self.heading_field, self.heading_val, self.wind_dir_field, self.wind_dir_val, self.wind_speed_field, self.wind_speed_val) continue # If we've not seen anything that updates fields that would # trigger a new true winds value, skip rest of computation. if not update: logging.debug('No update needed') continue logging.debug('Computing new true winds') (true_dir, true_speed, apparent_dir) = truew(crse=self.course_val, cspd=self.speed_val, hd=self.heading_val, wdir=self.wind_dir_val, zlr=self.zero_line_reference, wspd=self.wind_speed_val) logging.debug( 'Got true winds: dir: %s, speed: %s, apparent_dir: %s', true_dir, true_speed, apparent_dir) if None in (true_dir, true_speed, apparent_dir): logging.info('Got invalid true winds') continue # If here, we've got a valid new true wind result true_wind_fields = { self.true_dir_name: true_dir, self.true_speed_name: true_speed, self.apparent_dir_name: apparent_dir } # Add in metadata if so specified and it's been long enough since # we last sent it. now = time.time() if self.metadata_interval and \ now - self.metadata_interval > self.last_metadata_send: metadata = {'fields': self._metadata()} self.last_metadata_send = now logging.debug('Emitting metadata: %s', pformat(metadata)) else: metadata = None results.append( DASRecord(timestamp=timestamp, fields=true_wind_fields, metadata=metadata)) return results
def transform(self, record): """Incorporate any useable fields in this record, and if it gives us a new true wind value, return it.""" if not record: return None if not type(record) is DASRecord: logging.warning('Improper format record: %s', record) return None update = False for field_name in record.fields: if field_name in self.course_fields: self.course_val = record.fields[field_name] elif field_name in self.speed_fields: self.speed_val = record.fields[ field_name] * self.convert_speed_factor elif field_name in self.heading_fields: self.heading_val = record.fields[field_name] elif field_name in self.wind_dir_fields: self.wind_dir_val = record.fields[field_name] elif field_name in self.wind_speed_fields: self.wind_speed_val = record.fields[ field_name] * self.convert_wind_factor if field_name in self.update_on_fields: update = True # If we've not seen anything that updates fields that would # trigger a new true winds value, return None. if not update: return None if self.course_val is None: logging.info('Still missing course_val') return None if self.speed_val is None: logging.info('Still missing speed_val') return None if self.heading_val is None: logging.info('Still missing heading_val') return None if self.wind_dir_val is None: logging.info('Still missing wind_dir_val') return None if self.wind_speed_val is None: logging.info('Still missing wind_speed_val') return None logging.info('Computing new true winds') (true_dir, true_speed, app_dir) = truew(crse=self.course_val, cspd=self.speed_val, hd=self.heading_val, wdir=self.wind_dir_val, zlr=self.zero_line_reference, wspd=self.wind_speed_val) logging.info('Got true winds: dir: %s, speed: %s, app_dir: %s', true_dir, true_speed, app_dir) if true_dir is None or true_speed is None or app_dir is None: logging.info('Got invalid true winds') return None # If here, we've got a valid new true wind result if self.output_nmea: new_record = '%s %s %g,%g,%g' % (self.data_id, time_str(record.timestamp), true_dir, true_speed, app_dir) else: new_record = DASRecord(data_id=self.data_id, timestamp=record.timestamp, fields={ 'TrueWindDir': true_dir, 'TrueWindSpeed': true_speed, 'ApparentWindDir': app_dir }) return new_record