Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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)
Beispiel #4
0
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
Beispiel #5
0
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',
    }
Beispiel #6
0
 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)
Beispiel #7
0
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
Beispiel #8
0
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
Beispiel #9
0
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