def test_no_tick(): interface = Mock() interface.gpio = Mock() interface.gpio.write_pin = Mock() d = Display(interface=interface) d.auto_disable_display = False d.tick() assert interface.gpio.write_pin.assert_not_called() is None
def test_no_tick(self): interface = Mock() interface.gpio = Mock() interface.gpio.write_pin = Mock() display = Display(interface=interface) display.auto_disable_display = False display.tick() assert interface.gpio.write_pin.assert_not_called() is None
def test_tick(self): interface = Mock() interface.gpio = Mock() interface.gpio.write_pin = Mock() display = Display(interface=interface) display.auto_disable_display = True active = display.is_active(Display.convert_to_minutes(time.strftime("%H:%M"))) display.tick() if active: assert interface.gpio.write_pin.assert_called_once_with(display.pin, 1) is None else: assert interface.gpio.write_pin.assert_called_once_with(display.pin, 0) is None
def test_tick(): interface = Mock() interface.gpio = Mock() interface.gpio.write_pin = Mock() d = Display(interface=interface) d.auto_disable_display = True active = d.is_active(Display.convert_to_minutes(time.strftime("%H:%M"))) d.tick() if active: assert interface.gpio.write_pin.assert_called_once_with(d.pin, 1) is None else: assert interface.gpio.write_pin.assert_called_once_with(d.pin, 0) is None
class WeatherVane(object): def __init__(self, *args, **configuration): self.old_weatherdata = None self.args = args self.configuration = configuration self.interface = WeatherVaneInterface(*args, **configuration) self.display = Display(self.interface, **configuration['display']) logging.info("Using " + str(self.interface)) self.wd = None self.counter = 0 self.interval = configuration['interval'] self.sleep_time = configuration['sleep-time'] self.start_collection_time = datetime.datetime.now() self.end_collection_time = datetime.datetime.now() self.reached = False def test_mode(self): """ Test mode is used to output a predicable sequence of bytes to the output pins. The program will send 3 bytes every second to the pins. - Byte 1: an increasing counter (modulo 255) - Byte 2: a decreasing counter (idem) - Byte 3: switches between 0x55 and 0xAA """ logging.info("Starting test mode") interface = TestInterface(channel=0, frequency=25000) counter = 0 while True: counter += 1 if counter % 2: test = 0x55 else: test = 0xAA data = [counter % 255, (255 - counter) % 255, test] interface.send(data) time.sleep(1) def check_selected_station(self, selected_station): """Check if another station is selected and change it when it has Determine whether the selected station has changed on the interface. If it has changed, then immediately start using data from this new station and return the id of the newly selected station. In the config-file you can specify a list of stations where data may be collected from. You can choose the specific station by also specifying on or more pins on the raspberry that together form a bitwise number. E.g you want to select one of four stations. You will need to specify 2 pins on the raspberry (2**2) that select on of these four stations. If pin 0 is high and pin 1 is low, you will select station 2. If both pins are high, you will select station 3, etc. Side effect: reset counter to 0 if another station is selected @param selected_station: the currently used station @return: either the id of the new station or the id of the station already in use """ station_id = self.interface.selected_station if station_id != selected_station: # reset if a new station is selected self.counter = 0 logging.info("New station selected: {}".format(station_id)) return station_id def start_data_collection(self, pipe_end): """Side effect: reset counter to 0 @param pipe_end_1: @return: """ self.counter = 0 arguments = [pipe_end] arguments.extend(self.args) p = Process(target=fetch_weather_data, args=arguments, kwargs=self.configuration) p.start() logging.debug('Retrieving data') def send_data(self): if self.old_weatherdata: wd = self.interpolate(self.old_weatherdata, self.wd, self.interval) self.interface.send(wd) else: self.interface.send(self.wd) def retrieve_data(self, pipe_end_2): logging.info('Data available:') self.end_collection_time = datetime.datetime.now() self.reached = False logging.info('Data retrieval including parsing took {}'.format( self.end_collection_time - self.start_collection_time)) self.old_weatherdata, self.wd = self.wd, pipe_end_2.recv() logging.info(pprint.pformat(self.wd)) def start_data_collection_and_timer(self, pipe_end_1): self.start_collection_time = datetime.datetime.now() self.start_data_collection(pipe_end_1) def log_heartbeat(self): logging.debug('Heartbeat-{}'.format(self.counter)) def set_logger(self): weathervane_logger = logging.getLogger('') weathervane_logger.setLevel(logging.INFO) handler = logging.handlers.TimedRotatingFileHandler(filename="weathervane.log", when="midnight", interval=1, backupCount=7) formatter = logging.Formatter("%(asctime)s:%(levelname)s:%(module)s:%(message)s") handler.setFormatter(formatter) weathervane_logger.addHandler(handler) def interpolate(self, old_weatherdata, new_weatherdata, interval): if self.counter >= interval - 1: self.reached = True if new_weatherdata['error']: return new_weatherdata interpolated_wd = {} for key, old_value in list(old_weatherdata.items()): new_value = new_weatherdata.get(key, None) if not new_value: continue if key not in ['error', 'wind_direction', 'wind_direction', 'rain', 'barometric_trend'] and not self.reached: try: interpolated_value = float(old_value) + ( self.counter * (float(new_value) - float(old_value)) / interval) interpolated_wd[key] = interpolated_value except ValueError: interpolated_wd[key] = new_value except TypeError: interpolated_wd[key] = new_value else: interpolated_wd[key] = new_value return interpolated_wd def main(self): pipe_end_1, pipe_end_2 = Pipe() while True: self.display.tick() if (self.counter % 3) == 0: self.log_heartbeat() if (self.counter % self.interval) == 0: self.start_data_collection_and_timer(pipe_end_1) if pipe_end_2.poll(0): self.retrieve_data(pipe_end_2) if self.wd: self.send_data() self.counter += 1 time.sleep(self.sleep_time)
class WeatherVane(object): def __init__(self, *args, **configuration): self.old_weatherdata = None self.args = args self.configuration = configuration self.interface = WeatherVaneInterface(*args, **configuration) self.display = Display(self.interface, **configuration['display']) logging.info("Using " + str(self.interface)) self.wd = None self.counter = 0 self.interval = configuration['interval'] self.sleep_time = configuration['sleep-time'] self.start_collection_time = datetime.datetime.now() self.end_collection_time = datetime.datetime.now() self.reached = False def start_data_collection(self, pipe_end): """Side effect: reset counter to 0 @param pipe_end_1: @return: """ self.counter = 0 arguments = [pipe_end] arguments.extend(self.args) p = Process(target=fetch_weather_data, args=arguments, kwargs=self.configuration) p.start() logging.debug('Retrieving data') def send_data(self): if self.old_weatherdata: wd = self.interpolate(self.old_weatherdata, self.wd, self.interval) self.interface.send(wd) else: self.interface.send(self.wd) def retrieve_data(self, pipe_end_2): logging.info('Data available:') self.end_collection_time = datetime.datetime.now() self.reached = False logging.info('Data retrieval including parsing took {}'.format( self.end_collection_time - self.start_collection_time)) self.old_weatherdata, self.wd = self.wd, pipe_end_2.recv() logging.info(pprint.pformat(self.wd)) def start_data_collection_and_timer(self, pipe_end_1): self.start_collection_time = datetime.datetime.now() self.start_data_collection(pipe_end_1) def log_heartbeat(self): logging.debug('Heartbeat-{}'.format(self.counter)) def set_logger(self): weathervane_logger = logging.getLogger('') weathervane_logger.setLevel(logging.INFO) handler = logging.handlers.TimedRotatingFileHandler( filename="weathervane.log", when="midnight", interval=1, backupCount=7) formatter = logging.Formatter( "%(asctime)s:%(levelname)s:%(module)s:%(message)s") handler.setFormatter(formatter) weathervane_logger.addHandler(handler) def interpolate(self, old_weatherdata, new_weatherdata, interval): if self.counter >= interval - 1: self.reached = True if new_weatherdata['error']: return new_weatherdata interpolated_wd = {} for key, old_value in list(old_weatherdata.items()): new_value = new_weatherdata.get(key, None) if not new_value: continue if key not in [ 'error', 'winddirection', 'winddirection', 'rain', 'barometric_trend' ] and not self.reached: try: interpolated_value = float(old_value) + ( self.counter * (float(new_value) - float(old_value)) / interval) interpolated_wd[key] = interpolated_value except ValueError: interpolated_wd[key] = new_value except TypeError: interpolated_wd[key] = new_value else: interpolated_wd[key] = new_value return interpolated_wd def main(self): pipe_end_1, pipe_end_2 = Pipe() while True: self.display.tick() if (self.counter % 3) == 0: self.log_heartbeat() if (self.counter % self.interval) == 0: self.start_data_collection_and_timer(pipe_end_1) if pipe_end_2.poll(0): self.retrieve_data(pipe_end_2) if self.wd: self.send_data() self.counter += 1 time.sleep(self.sleep_time)