def apply_settings(self, section): # Initialise controls = self.camera.get_controls() self.camera.start_video_capture() # Read all camera controls defined in the config file for setting in _settings_map: value = get_config_option(self.config, section, setting) if value is not None: asi_control_name, asi_setting_name = _settings_map[setting] default_value = controls[asi_control_name]['DefaultValue'] control_type = getattr(zwoasi, asi_setting_name) logger.debug('set control value %s (%s) to %s', setting, asi_setting_name, value) if value == 'auto': self.camera.set_control_value(control_type, default_value, auto=True) else: # Cast value to same type as default_value self.camera.set_control_value(control_type, type(default_value)(value), auto=False) image_type = get_config_option(self.config, section, 'image_type') if image_type is not None: logger.debug('set image type to %s', image_type) self.camera.set_image_type( getattr(zwoasi, 'ASI_IMG_' + image_type.upper()))
def get_next_file(self, section): while True: pattern = get_config_option(self.config, section, 'images') files = glob.glob(pattern) if not files: # raise Exception('no files matched %s', pattern) yield None for f in sorted(files): yield f
def apply_settings(self, section): # Stop any previous recordings self.stop_recording() self.use_video_port = get_config_option(self.config, section, 'use_video_port', get='getboolean') if self.use_video_port: self.splitter_port = get_config_option(self.config, section, 'splitter_port', 0, get='getint') # Fractions framerate = get_config_option(self.config, section, 'framerate') if framerate is not None: logger.debug('setting framerate=%s', str(framerate)) self.camera.framerate = fraction_or_float(framerate) # Booleans for k in ('hflip', 'image_denoise', 'vflip', 'video_denoise'): val = get_config_option(self.config, section, k, get='getboolean') if val is not None: logger.debug('setting %s=%s', k, 'true' if val else 'false') setattr(self.camera, k, val) # Ints for k in ('brightness', 'contrast', 'exposure_compensation', 'iso', 'rotation', 'saturation', 'sensor_mode', 'sharpness', 'shutter_speed'): val = get_config_option(self.config, section, k, get='getint') if val is not None: logger.debug('setting %s=%d', k, val) setattr(self.camera, k, val) # Strings for k in ('awb_mode', 'drc_strength', 'exposure_mode', 'meter_mode', 'resolution', 'still_stats'): val = get_config_option(self.config, section, k) if val is not None: logger.debug('setting %s=%s', k, val) setattr(self.camera, k, val) awb_gains = get_config_option(self.config, section, 'awb_gains') if awb_gains: awb_gains = awb_gains.split() if len(awb_gains) == 1: self.camera.awb_gains = fraction_or_float(awb_gains[0]) else: # awb_gains = (Fraction(*map(int, awb_gains[0])), Fraction(*map(int, awb_gains[0]))) self.camera.awb_gains = (fraction_or_float(awb_gains[0]), fraction_or_float(awb_gains[1])) if self.use_video_port: self.camera.start_recording(NullStream(), format='rgb', splitter_port=self.splitter_port + 1)
def run_camera(forced_schedule): global config global camera global sampling_interval # This should be called after dropping root privileges because # it uses safe_eval to convert strings to numbers or # lists (not guaranteed safe!) #camera = cameralogger.get_camera(config) #cameralogger.init_camera(camera, config) camera_type = config.get('camera', 'type') logger.debug('camera type: %s', camera_type) Camera = getattr( importlib.import_module('cameralogger.' + camera_type.lower()), 'Camera') camera = Camera(config) camera_settings = cameralogger.get_config_option(config, 'camera', 'settings') if camera_settings: camera.apply_settings(camera_settings) signal.signal(signal.SIGTERM, stop_handler) signal.signal(signal.SIGINT, stop_handler) try: get_log_file_for_time(time.time(), log_filename) logger.info('Starting sampling thread') do_every(camera, config, forced_schedule, cameralogger.process_tasks) while take_images: time.sleep(2) # Wait until all other threads have (or should have) # completed try: sampling_interval_lock.acquire(True) si = sampling_interval finally: sampling_interval_lock.release() for n in range(int(round(si)) + 1): if threading.activeCount() == 1: break time.sleep(1) except (KeyboardInterrupt, SystemExit): raise except Exception: get_log_file_for_time(time.time(), log_filename) logger.error(traceback.format_exc()) time.sleep(5)
def do_every(camera, config, forced_schedule, worker_func, iterations=0): global sampling_interval if iterations != 1: # Identify current operating condition to find the actions to do and sampling interval schedule, schedule_info = cameralogger.get_schedule( config, forced_schedule) logger.info('using schedule %s', schedule) logger.info('schedule info: %s', repr(schedule_info)) # Schedule the next worker thread. Aim to start at the next # multiple of sampling interval. Take current time, add 1.25 # of the interval and then find the nearest # multiple. Calculate delay required. now = time.time() interval = cameralogger.get_config_option( config, schedule, 'sampling_interval', fallback_section='common', default=default_sampling_interval, get='getfloat') delay = round_to(now + (1.25 * interval), interval) - now # Avoid lockups by many threads piling up. Impose a minimum delay if delay < 0.1: delay = 0.1 t = threading.Timer(delay, do_every, [ camera, config, forced_schedule, worker_func, 0 if iterations == 0 else iterations - 1 ]) t.daemon = True t.start() # Check if the schedule has changed, if so apply any new settings. To access last_schedule and camera # the camera_lock must be acquired if config.has_option(schedule, 'camera_settings'): if camera_lock.acquire(False): try: global last_schedule logger.debug('camera_lock: acquired lock') if schedule != last_schedule: settings_section = config.get(schedule, 'camera_settings') if not config.has_section(settings_section): logger.error( 'cannot apply camera settings for schedule %s: section %s does not exist', schedule, settings_section) raise Exception('missing section %s' % settings_section) if last_schedule is not None and settings_section == config.get( last_schedule, 'camera_settings'): # No action needed logger.debug( 'schedule changed but camera settings unchanged' ) else: logger.debug( 'schedule changed, applying new settings for %s from section %s', schedule, settings_section) camera.apply_settings(settings_section) last_schedule = schedule # Update last, after settings have been applied finally: camera_lock.release() logging.debug('camera_lock: released lock') else: logger.error('camera_lock: could not acquire lock') # Update the global sampling_interval so that cancel_sampling_threads knows how long to wait. # This could be attempted by multiple capture threads so must use a lock. Don't wait for the lock to be # available. if sampling_interval_lock.acquire(False): try: logger.debug('sampling_interval_lock: acquired lock') sampling_interval = interval finally: logging.debug('sampling_interval_lock: released lock') sampling_interval_lock.release() else: logger.error('sampling_interval_lock: could not acquire lock') try: worker_func(camera, config, schedule, schedule_info) except (KeyboardInterrupt, SystemExit): raise except Exception: get_log_file_for_time(time.time(), log_filename) logger.error(traceback.format_exc())