def register_picture(object_name: str) -> None: # object_name example: 'tank_id-sample/sample_camera_id/2020/01/01/00_00_00.jpg' object_name_elements = object_name.split('/') camera_id = object_name_elements[1] # sample_camera_id year = object_name_elements[2] # 2020 month = object_name_elements[3] # 01 day = object_name_elements[4] # 01 file_name = object_name_elements[5] # 00_00_00.jpg target_dir_path = f'{AMS_ROOT_PATH}/pictures/{camera_id}/{year}/{month}' target_file_path = f'{target_dir_path}/{day}.json' # make new directory make_new_dir = make_dir(target_dir_path) if make_new_dir: logger(INFO, f'make new directory: {target_dir_path}', True) target_day_pictures = {'pictures': []} if is_exist_file(target_file_path): target_day_pictures = get_json_file(target_file_path) # register new picture target_day_pictures['pictures'].append(file_name) set_json_file( file_path = target_file_path, data = target_day_pictures ) return
def create_camera(name: str, camera_device_id: int, timer: list, resolution: dict, trimming: dict) -> None: cameras = get_camera_config() tank_id = get_config_item('TANK_ID') camera_id = generate_camera_id(tank_id) new_camera = { 'camera_id': camera_id, 'name': name, 'camera_device_id': camera_device_id, 'resolution': { 'x': resolution['x'], 'y': resolution['y'], }, 'timer': list(timer), 'trimming': { 'top': trimming['top'], 'bottom': trimming['bottom'], 'left': trimming['left'], 'right': trimming['right'], }, 'latest_picture_url': '' } cameras.append(new_camera) set_camera_config(cameras) logger( INFO, 'Create new camera 📸\n' + json.dumps(new_camera), True, False ) return
def ams_logger(req, log_level: str, notification: bool = False): message = flask_logger_message( method=req.method, path=req.path, data=req.data.decode(), remote_addr=req.remote_addr, user_agent=req.user_agent, ) logger(log_level, message, notification)
def update_camera( camera_id: str, name: str, camera_device_id: int, resolution: dict, timer: list, trimming: dict ) -> None: cameras = get_camera_config() updated_camera = { 'camera_id': camera_id, 'name': name, 'camera_device_id': camera_device_id, 'resolution': { 'x': resolution['x'], 'y': resolution['y'], }, 'timer': list(timer), 'trimming': { 'top': trimming['top'], 'bottom': trimming['bottom'], 'left': trimming['left'], 'right': trimming['right'], }, 'latest_picture_url': '' } for camera in cameras: if camera['camera_id'] == camera_id: camera['name'] = name camera['camera_device_id'] = camera_device_id camera['resolution'] = resolution camera['timer'] = timer camera['trimming'] = trimming updated_camera['latest_picture_url'] = camera['latest_picture_url'] set_camera_config(cameras) logger( INFO, f'Update camera 📸\ncamera_id = {camera_id}\n' + json.dumps(updated_camera), True, False ) return
def get_album_exist_years(camera_id: str) -> dict: taeget_path = '/'.join([AMS_ROOT_PATH, 'pictures', camera_id]) try: list_ = ls(taeget_path) except FileNotFoundError: logger( ERROR, f'camera not found. camera_id = {camera_id}', True, False ) raise CameraNotFound return { 'camera_id': camera_id, 'list': sorted(list_), 'type': 'year', }
def __init__(self): super(Service_Module, self).__init__() load_database = load_db() self.sc_session: scoped_session = load_database.get_scoped_session() tb_scopes.make_default_scopes(service_module=self) self.logger = logger(service_module=self) self.settings = settings(service_module=self) self.callback_listener: web_listener = web_listener( service_module=self) self.callback_listener.start() self.images = image_serve(service_module=self) self.scheduler = Scheduler_service() self.characters = character_manager(service_module=self) assert isinstance(self.sc_session, scoped_session) assert isinstance(self.logger, logger) assert isinstance(self.settings, settings) assert isinstance(self.callback_listener, web_listener) assert isinstance(self.images, image_serve) assert isinstance(self.scheduler, Scheduler_service)
def camera_request( host: str, port: int, cameras: list, resolution: dict, camera_warm_up_time: float, aws: dict = {}, mqtt: dict = {}, ) -> None: request_json = { 'cameras': [ { 'objectName': camera['object_name'], 'topic': camera['topic'], 'trimming': { 'top': camera['trimming']['top'], 'bottom': camera['trimming']['bottom'], 'left': camera['trimming']['left'], 'right': camera['trimming']['right'], }, } for camera in cameras ], 'resolution': { 'x': resolution['x'], 'y': resolution['y'], }, 'cameraWarmUpTime': camera_warm_up_time, 'uploader': {} } if aws != {}: request_json['uploader']['aws'] = { 'accessKeyId': aws['aws_access_key_id'], 'secretAccessKey': aws['aws_secret_access_key'], 's3Bucket': aws['s3_bucket'], 'region': aws['region'], } if mqtt != {}: request_json['uploader']['mqtt'] = { 'host': mqtt['host'], 'port': mqtt['port'], 'userName': mqtt['user_name'], 'password': mqtt['password'], 'retain': mqtt['retain'], } # request to camera api server try: res = requests.post( url = f'http://{host}:{port}/picture', json = request_json ) except requests.exceptions.RequestException: logger(ERROR, 'camera is not running', True) raise CameraServerNotRunningError except Exception: logger(FATAL, '[camera.request] Unknown Error', True) raise UnknownError status_code = res.status_code # error response from camera api if status_code != 200: response_json = json.loads(res.text) error_text = f'Status code from camera: {status_code}\n' error_text += res.text logger(ERROR, error_text, True) if response_json['error'] == 'S3UploadFailedError': raise S3UploadFailedError elif response_json['error'] == 'MqttNotAuthorisedError': raise MqttNotAuthorisedError elif response_json['error'] == 'MqttNoRouteToHostError': raise MqttNoRouteToHostError else: raise UnknownError return
def take_pictures(camera_id_list: list) -> None: if len(camera_id_list) == 0: return config = get_config_items([ 'TANK_ID', 'MQTT', 'CAMERA' ]) camera_device_config = get_camera_device_config() # camera_device一覧と、今回撮影するカメラが紐づいた配列request_camera_devicesを作成 """ example request_camera_devices = [ { 'camera_device_id': 1, 'host': CAMERA_HOST, 'port': CAMERA_PORT, 'cameras': [ { 'camera_id', 'name': 'sump_sub_box', 'camera_device_id' 'resolution': {'x': 1700, 'y': 1024}, 'trimming': {'bottom': 750, 'left': 1000, 'right': 1300, 'top': 620}, 'timer': [{'hour': 10, 'minute': 0}, {'hour': 12, 'minute': 0}, {'hour': 18, 'minute': 0}], 'latest_picture_url': 'https://hoge.cloudfront.net/tank_id-sample/fuga/2020/08/16/12_05_10.jpg', 'object_name': 'tank_id-sample/camera_id_hoge/2020/09/22/14_15_51.jpg', 'latest_picture_topic': 'tank/tank_id-sample/camera_id_hoge/latest_picture' } ] } ] """ request_camera_devices = [] # camera_device_configのスキーマにcamerasフィールドを追加したものをrequest_camera_devicesとする for camera_device in camera_device_config: camera_device['cameras'] = [] request_camera_devices.append(camera_device) # 今回撮影するcamera_id全てに対して以下を行う for camera_id in camera_id_list: camera = get_camera_config_by_id(camera_id) # cameraが存在しない場合はエラー if camera == {}: logger( WARN, 'Camera not found.\n' + f'camera_id = {camera_id}', True, False ) raise CameraNotFound # cameraにobject_nameを追加 object_name = generate_object_name( tank_id = config['TANK_ID'], camera_id = camera['camera_id'], ext = 'jpg' ) camera['object_name'] = object_name # cameraにpublish用のtopicを追加 latest_picture_topic = get_publish_topics()['CAMERA_LATEST_PICTURE'] # camera_idをtopicに反映 camera['latest_picture_topic'] = latest_picture_topic.format(camera_id = camera['camera_id']) # cameraが指定するcamera_device_idのcamera_deviceのところに追加 __append_camera_to_camera_device( camera_devices = request_camera_devices, camera = camera ) # 対象のcamera_deviceに対して以下を行う for request_camera_device in request_camera_devices: # 撮影したいカメラがない場合は次へ if len(request_camera_device['cameras']) == 0: continue # take a picture camera_request( host = request_camera_device['host'], port = request_camera_device['port'], cameras = [ { 'object_name': camera['object_name'], 'topic': camera['latest_picture_topic'], 'trimming': camera['trimming'], } for camera in request_camera_device['cameras'] ], resolution = request_camera_device['cameras'][0]['resolution'], # TODO resolution はcamera deviceごとに設定するのが理想 仮でcameraの先頭のresolutionを利用する camera_warm_up_time = config['CAMERA']['CAMERA_WARM_UP_TIME'], aws = { 'aws_access_key_id': config['CAMERA']['AWS_ACCESS_KEY_ID'], 'aws_secret_access_key': config['CAMERA']['AWS_SECRET_ACCESS_KEY'], 's3_bucket': config['CAMERA']['S3_BUCKET'], 'region': config['CAMERA']['REGION'], }, mqtt = { 'host': config['MQTT']['MQTT_BROKER'], 'port': config['MQTT']['MQTT_BROKER_PORT'], 'user_name': config['MQTT']['MQTT_BROKER_USERNAME'], 'password': config['MQTT']['MQTT_BROKER_PASSWORD'], 'retain': False, # TODO this is true } ) # 以降撮影後の処理 # 撮影した画像のURL(logger用) picture_urls = [] # 撮影した画像それぞれに対して、latest_pictureを登録、アルバム用ディレクトリに追加する処理を行う for camera in request_camera_device['cameras']: picture_url = config['CAMERA']['PICTURE_URL'] + '/' + camera['object_name'] picture_urls.append(picture_url) # 撮影した画像のURLをconfigのlatest_picture_urlに登録 add_latest_picture_url( camera_id = camera['camera_id'], url = picture_url ) # picturesディレクトリに追加 register_picture(camera['object_name']) logger( INFO, 'Take a tank picture 📸\n' + f'pictures: {picture_urls}', True, False ) return
def main() -> None: # AMS Start! logger(INFO, 'AMS start.') logger(DEBUG, 'Welcome to AMS!') BOOT_AA = get_boot_ascii_art() logger(INFO, BOOT_AA) # set initial device state logger(INFO, 'set initial device states ...') set_init_device_state() logger(DEBUG, 'OK.') # network connection check logger(INFO, 'Network connection check start') timer = timeout_time_generator(default=0.5, default_repeat_times=20, r=2, th=60) no_network_connection = True while no_network_connection: logger(INFO, 'Not connected to the Internet. Please wait ...') no_network_connection = not connected_to_internet( url=NETWORK_CONNECT_CHECK_URL, timeout=NETWORK_CONNECT_CHECK_INTERVAL, ) time.sleep(timer.__next__()) logger(DEBUG, 'OK.') # local AMS server logger(INFO, 'running local ams server ...', True) subprocess.Popen(f'cd {AMS_LOCAL_SERVER_PATH}; python3 app.py', shell=True) logger(DEBUG, 'OK') # open subscriber logger(INFO, 'running subscriber ...', True) subprocess.Popen(['python3', SUBSCRIBER_PATH]) logger(DEBUG, 'OK') # AMS start successfully logger(INFO, 'AMS start successfully!🎉🎉', True, True) # open sensor manager logger(INFO, 'running sensor manager ...', True) while True: try: publish_sensor_data() except Exception as e: error_message = ''.join( traceback.TracebackException.from_exception(e).format()) post_slack_by_type( text=error_message, type_=SLACK_NOTIFICATION_TYPE['ERROR'], ) print(error_message) pass