Beispiel #1
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 #2
0
def post_slack_with_attachment(
    channel: str,
    username: str,
    text: str,
    icon_emoji: str,
    color: str,
    attachment_title: str,
    attachment_text: str,
    attachment_footer: str,
) -> None:
    post_data = {
        "channel":
        channel,
        "username":
        username,
        "text":
        text,
        "icon_emoji":
        icon_emoji,
        "attachments": [{
            "color": color,
            "author_name": attachment_title,
            "text": attachment_text,
            "footer": attachment_footer,
        }]
    }
    slack_webhook_url = get_config_item('SLACK')['WEBHOOK_URL']
    response = requests.post(slack_webhook_url, data=json.dumps(post_data))
Beispiel #3
0
def auto_feeder(pin: int) -> bool:
    """
    auto feeder

    Parameters
    ----------
    pin : int
        target gpio (BCM)
    
    Returns
    -------
    bool
        Auto feeding successful
    """
    is_running = gpio_read(pin)
    if is_running:
        return False

    AUTO_FEEDER_RUN_TIME = get_config_item('DEVICE')['AUTO_FEEDER_RUN_TIME']

    # auto feeder on
    gpio_write(pin, 1)
    try:
        publish_device_state()
    except:
        gpio_write(pin, 0)
        return False

    time.sleep(AUTO_FEEDER_RUN_TIME)
    # pump off
    gpio_write(pin, 0)
    publish_device_state()

    return True
Beispiel #4
0
def import_sensor_back_file(backup_file: list) -> None:
    MAX_SENSOR_NUMBER = get_config_item('MAX_SENSOR_NUMBER')

    if len(backup_file) != MAX_SENSOR_NUMBER:
        raise FormatInvalid('Device number invalid')

    # TODO Validation

    set_sensor_config(backup_file)
    return
Beispiel #5
0
def import_device_back_file(backup_file: list) -> None:
    MAX_DEVICE_NUMBER = get_config_item('MAX_DEVICE_NUMBER')

    if len(backup_file) != MAX_DEVICE_NUMBER:
        raise FormatInvalid('Device number invalid')

    # TODO Validation

    set_gpio_config(backup_file)
    return
Beispiel #6
0
def post_slack(channel: str, username: str, text: str,
               icon_emoji: str) -> None:

    post_data = {
        "channel": channel,
        "username": username,
        "text": text,
        "icon_emoji": icon_emoji
    }
    slack_webhook_url = get_config_item('SLACK')['WEBHOOK_URL']
    response = requests.post(slack_webhook_url, data=json.dumps(post_data))
Beispiel #7
0
def logger(log_level: str,
           message: str,
           require_slack: bool = False,
           mention_required: bool = False) -> None:

    prefix = log_message_prefix_generator(log_level)

    # stdout
    print('{colored_prefix} {message}'.format(colored_prefix=color_text(
        text=prefix, color=LOG_LEVEL[log_level]['COLOR']),
                                              message=message))

    # out to log file
    if LOG_LEVEL[log_level]['LEVEL'] >= MIN_FILE_OUTPUT_LEVEL:
        output_log_file(text=f'{prefix} {message}\n')

    # slack
    slack_notification = get_config_item('SLACK')['SLACK_NOTIFICATION']

    if require_slack and slack_notification:
        mention = ''
        if log_level == ERROR or log_level == FATAL or mention_required:
            mention = SLACK_MENTION_TYPE['CHANNEL']

        # Error handling is required in HTTP Request
        try:
            post_log_to_slack(
                pretext=mention,
                color=LOG_LEVEL[log_level]['SLACK_COLOR'],
                title=f'[{log_level}]',
                text=message,
                footer=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        except Exception as e:
            error_message = ''.join(
                traceback.TracebackException.from_exception(e).format())
            error_message += """
-----------------------------------------------
This message can not post to slack.

{message} 
-----------------------------------------------
""".format(message=message)
            logger(ERROR, error_message)
            add_unsent_message(
                log_level=log_level,
                message=message,
            )
            pass

    return
Beispiel #8
0
def post_log_to_slack(pretext: str, color: str, title: str, text: str,
                      footer: str) -> None:
    # get slack config from config
    slack_config = get_config_item('SLACK')
    # post slack with attachment
    post_slack_with_attachment(
        channel=slack_config['LOG']['CHANNEL'],
        username=slack_config['LOG']['USERNAME'],
        text=pretext,
        icon_emoji=slack_config['LOG']['ICON_EMOJI'],
        color=color,
        attachment_title=title,
        attachment_text=text,
        attachment_footer=footer,
    )
Beispiel #9
0
def post_slack_by_type(text: str, type_: str) -> None:

    slack_config = get_config_item('SLACK')

    if type_ == SLACK_NOTIFICATION_TYPE['NOTIFICATION']:
        post_slack(
            channel=slack_config['NOTIFICATION']['CHANNEL'],
            username=slack_config['NOTIFICATION']['USERNAME'],
            text=slack_config['NOTIFICATION']['MESSAGE_FORMAT'].format(
                message=text),
            icon_emoji=slack_config['NOTIFICATION']['ICON_EMOJI'],
        )

    elif type_ == SLACK_NOTIFICATION_TYPE['ERROR']:
        post_slack(
            channel=slack_config['ERROR']['CHANNEL'],
            username=slack_config['ERROR']['USERNAME'],
            text=slack_config['ERROR']['MESSAGE_FORMAT'].format(message=text),
            icon_emoji=slack_config['ERROR']['ICON_EMOJI'],
        )

    else:
        raise NotificationTypeUndefined('This type does not exist.')
Beispiel #10
0
    ls,
    make_dir,
    set_json_file,
    zero_padding,
    zero_padding_month,
)
from service.logger import (
    logger,
    DEBUG,
    INFO,
    WARN,
    ERROR,
    FATAL,
)

AMS_ROOT_PATH = get_config_item('ROOT_PATH').rstrip('/')

def get_camera_config_by_id(camera_id: str) -> dict:
    cameras = get_camera_config()
    for camera in cameras:
        if camera['camera_id'] == camera_id:
            return camera
    return {}

def get_camera_device_config_by_id(camera_device_id: int) -> dict:
    camera_devices = get_camera_device_config()
    for camera_device in camera_devices:
        if camera_device['camera_device_id'] == camera_device_id:
            return camera_device
    return {}
Beispiel #11
0
def main():
    PORT = get_config_item('port')
    app.run(debug=True, host='0.0.0.0', port=PORT)
Beispiel #12
0
def publish_sensor_data() -> None:

    sensing_config = get_config_item('SENSING')
    sensor_data_publish_period = sensing_config['SENSOR_DATA_PUBLISH_PERIOD']
    sensing_number = sensing_config['SENSING_NUMBER']
    sensor_config = get_sensor_config()

    total_value = {}
    for sensor in sensor_config:
        # if a sensor exists
        if sensor['sensor']: total_value[sensor['sensor_id']] = 0

    for _ in range(sensing_number):
        for sensor_id in total_value.keys():
            sensor_value = read_mcp(sensor_id)
            total_value[sensor_id] += sensor_value
        time.sleep(sensor_data_publish_period / sensing_number)

    publish_data = {
        "timestamp": int( datetime.datetime.now().strftime('%s') ),
        "sensors": [],
    }

    for sensor in sensor_config:
        # if a sensor does not exists
        if sensor['sensor'] == {}:
            continue

        # Least squares coefficients
        if len(sensor['sensor']['calibration']) > 1:
            a, b = least_squares( sensor['sensor']['calibration'] )
        else:
            # use raw value
            a, b = 1, 0

        publish_data['sensors'].append({
            "sensor_id": sensor['sensor_id'],
            "name": sensor['sensor']['name'],
            "type": sensor['sensor']['type'],
            "value": round( a * total_value[sensor['sensor_id']] / sensing_number + b, 2),
            "raw_value": round(total_value[sensor['sensor_id']] / sensing_number, 1),
        })
    

    publish_topic = publish_topics['SENSOR_DATA'] 
    publish_data_json = json.dumps(publish_data)

    write_current_sensor_values(publish_data_json)

    publish(
        topic = publish_topic,
        message = publish_data_json,
        qos = 0,
        retain = True,
    )

    print_color_log(
        title = LOG_TITLE['SENSOR'],
        title_color = Color.YELLOW,
        text = '{unixtime}: {topic}: {message}'.format(
            unixtime = datetime.datetime.now().strftime('%s'),
            topic = color_text(publish_topic, Color.GREEN),
            message = publish_data_json,
        )
    )
Beispiel #13
0
from on_message.camera_album_get import get_album
from on_message.camera_take_picture import camera_take_picture
from service.device import get_all_device_state
from service.sensor import get_current_sensor_values
from service.backup import backup_file_name, get_device_backup_file, import_device_back_file, get_sensor_backup_file, import_sensor_back_file
from service.logger import (
    logger,
    DEBUG,
    INFO,
    WARN,
    ERROR,
    FATAL,
)

app = Flask(__name__)
server_config = get_config_item('LOCAL_SERVER')

empty_response = json.dumps({})


class InvalidUsage(Exception):
    status_code = 400

    def __init__(self, message, status_code=None, payload=None):
        Exception.__init__(self)
        self.message = message
        if status_code is not None:
            self.status_code = status_code
        self.payload = payload

    def to_dict(self):
Beispiel #14
0
        "SLACK_COLOR": '#D7DF01',
    },
    "ERROR": {
        "LEVEL": 4,
        "COLOR": Color.RED,
        "SLACK_COLOR": '#FF4000',
    },
    "FATAL": {
        "LEVEL": 5,
        "COLOR": Color.PURPLE,
        "SLACK_COLOR": '#FF00BF',
    },
}
MIN_FILE_OUTPUT_LEVEL = 2

AMS_ROOT_PATH = get_config_item('ROOT_PATH')
OUTPUT_LOG_FILE_PATH = '/'.join([AMS_ROOT_PATH, 'log', 'logger'])
UNSENT_LOG_FILE_PATH = '/'.join([AMS_ROOT_PATH, 'log', 'tmp', 'unsent.json'])


def log_message_prefix_generator(log_level: str) -> str:
    """
    Parameters
    ----------
    text: log_level
        log level
        e.g. "INFO", "WARN", ...

    Returns
    ----------
    str
Beispiel #15
0
from commons.consts import (
    CRON_START_TEXT,
    CRON_END_TEXT,
    CRON_COMMENT_FORMAT,
    CRON_FORMAT_CONTINUOUS,
    CRON_FORMAT_DAILY,
    CRON_FORMAT_DISCREATE,
    DEVICE_RUN_TYPE,
    DEVICE_TYPE,
)

from lib.config import get_gpio_config, get_config_item, get_root_path
from lib.cron import get_crontab, write_to_crontab

FEED_PUMP_DEFAULT_TIME = get_config_item('DEVICE')['FEED_PUMP_DEFAULT_TIME']


def cron_text_generator() -> str:
    """
    This text is generated by this function.
    
    # ------ AMS start -------
    # device_id: 1
    # device_name: my_main_light
    # on
    30 10 * * * gpio -g mode 26 out && gpio -g write 26 1
    # off
    30 18 * * * gpio -g mode 26 out && gpio -g write 26 0

    # device_id: 2
Beispiel #16
0
import sys

import pathlib
current_dir = pathlib.Path(__file__).resolve().parent
sys.path.append( str(current_dir) + '/../' )

from service.camera import take_picture
from service.trimming import trimming
from service.uploader import s3_upload, publish_picture
from lib.config import get_config_item

TMP_BASE_PICTURE_PATH = get_config_item('tmp_base_picture_path')
TMP_TRIMMED_PICTURE_PATH = get_config_item('tmp_trimmed_picture_path')

def picture(request: dict) -> None:

    # case no camera
    if len(request['cameras']) == 0:
        return

    take_picture(
        file_ = TMP_BASE_PICTURE_PATH,
        x = request['resolution']['x'],
        y = request['resolution']['y'],
        warm_up_time = request['cameraWarmUpTime']
    )

    for camera in request['cameras']:
        trimming(
            input_path = TMP_BASE_PICTURE_PATH,
            output_path = TMP_TRIMMED_PICTURE_PATH,