def deactivate_branch(line_id, mode):
    response_off = get_line_status(line_id)
    if response_off[line_id]["state"] != 0:
        try:
            response_off = retry_branch_off(branch_id=line_id)
        except Exception as e:
            logging.error(e)
            logging.error(
                "Can't turn off branch id={0}. Exception occured".format(
                    line_id))
            raise

        if mode == "manually":
            now = datetime.datetime.now()
            if get_next_rule_from_redis(line_id) is not None:
                database.update(database.QUERY[mn() + "_1"].format(
                    get_next_rule_from_redis(line_id)["interval_id"]))
            else:
                database.update(database.QUERY[mn() + "_2"].format(
                    line_id, 2, 4, now.date(), now, None))

            set_next_rule_to_redis(line_id,
                                   database.get_next_active_rule(line_id))
            logging.info("Rule '{0}' added".format(
                str(get_next_rule_from_redis(line_id))))

            logging.info("Line '{0}' deactivated manually".format(line_id))
        else:
            logging.info("No new entries is added to database.")
    else:
        logging.info(
            "Line '{0}' already deactivated. No action performed".format(
                line_id))

    return form_responce_for_branches(response_off)
Example #2
0
def temp_sensors():
    logging.info("Getting temperature:")
    now = datetime.datetime.now()
    for sensor_id, sensor in SENSORS.items():
        if sensor["type"] == "air_sensor":
            response = remote_controller.air_sensor(sensor_id)
            logging.info("Air temp: {0}".format(str(response)))
            database.update(
                database.QUERY[mn() + "_air"].format(
                    response[sensor_id]["id"],
                    response[sensor_id]["air_temp"],
                    response[sensor_id]["air_hum"],
                    now.strftime("%Y-%m-%d %H:%M"),
                )
            )
        elif sensor["type"] == "ground_sensor":
            response = remote_controller.ground_sensor(sensor_id)
            while response[sensor_id]["ground_temp"] == 85.00:
                logging.info("Sensor send basic temp. Retry.")
                response = remote_controller.ground_sensor(sensor_id)

            logging.info("Ground temp: {0}".format(str(response)))
            database.update(
                database.QUERY[mn() + "_ground"].format(
                    response[sensor_id]["id"],
                    response[sensor_id]["ground_temp"],
                    now.strftime("%Y-%m-%d %H:%M"),
                )
            )
def remove_ongoing_rule():
    """User can remove ongoing rule from ui."""
    rule_id = request.args.get("id")
    database.update(database.QUERY[mn() + "_remove_from_life"].format(rule_id))
    database.update(database.QUERY[mn() +
                                   "_delete_ongoing_rule"].format(rule_id))
    update_all_rules()

    send_ongoing_rule_message(channel="remove_ongoing_rule",
                              data={"rule_id": rule_id})
    send_history_change_message()

    return json.dumps({"status": "OK"})
def cancel_rule():
    """User can remove rule from ongoing rules table."""
    content = request.json["list"]

    for rule_id in content:
        # select l.interval_id, li.name from life as l, lines as li where id = {0} and l.line_id = li.number
        res = database.select(database.QUERY[mn() + "_1"].format(rule_id),
                              "fetchone")
        if res is None:
            logging.error(
                "No {0} rule/interval id in database".format(rule_id))
            abort(500)

        interval_id = res[0]
        ongoing_rule_id = res[2]
        # branch_name = res[1]
        # "UPDATE life SET state=4 WHERE interval_id = '{0}' and state = 1 and rule_id = 1"
        database.update(database.QUERY[mn() + "_2"].format(interval_id))

        res = database.select(
            database.QUERY[mn() +
                           "_select_ongoing_rule"].format(ongoing_rule_id),
            "fetchone",
        )
        if res is None:
            logging.info("No intervals for {0} ongoing rule. Remove it".format(
                ongoing_rule_id))
            database.update(
                database.QUERY[mn() +
                               "_delete_ongoing_rule"].format(ongoing_rule_id))

        logging.info("Rule '{0}' canceled".format(rule_id))

    update_all_rules()

    try:
        lines = {}
        for line_id, line in BRANCHES_SETTINGS.items():
            response_status = remote_controller.line_status(line_id=line_id)
            lines[line_id] = dict(id=line_id,
                                  state=int(response_status[line_id]["state"]))

        arr = form_responce_for_branches(lines)
        send_branch_status_message(arr)
    except Exception as e:
        logging.error(e)
        logging.error("Can't get Raspberri Pi pin status. Exception occured")
        abort(500)

    send_history_change_message()
    return json.dumps({"status": "OK"})
def edit_ongoing_rule():
    """User can edit ongoing rule from ui."""
    rules = request.json["rules"]
    now = datetime.datetime.now()

    for rule in rules:
        rule["line_id"] = int(rule["line_id"])
        rule["time"] = convert_to_datetime(rule["time"])
        rule["intervals"] = int(rule["intervals"])
        rule["time_wait"] = int(rule["time_wait"])
        rule["repeat_value"] = int(rule["repeat_value"])
        rule["date_start"] = convert_to_datetime(rule["date_start"])
        rule["time_start"] = convert_to_datetime(rule["time_start"])
        rule["date_time_start"] = datetime.datetime.combine(
            rule["date_start"], rule["time_start"].time())
        rule["end_date"] = convert_to_datetime(rule["end_date"])
        rule["rule_id"] = rule["rule_id"]
        rule["days"] = -1

        if rule["date_start"].date() == rule["end_date"].date():
            date_delta = rule["end_date"].date() - now.date()
            if date_delta.days == 0:
                rule["days"] = 0
            if date_delta.days == 1:
                rule["days"] = 1

        # "UPDATE ongoing_rules
        # SET line_id = {0}, time = {1}, intervals = {2}, time_wait = {3}, repeat_value={4}, date_time_start='{5}'"
        # end_date = '{6}' WHERE rule_id = '{7}'"
        database.update(database.QUERY[mn() + "_ongoing"].format(
            rule["line_id"],
            rule["time"],
            rule["intervals"],
            rule["time_wait"],
            rule["repeat_value"],
            rule["date_time_start"],
            rule["end_date"],
            rule["rule_id"],
        ))

        # update rules;
        update_rules_from_ongoing_rules(rule)
        # update_all_rules()
        logging.info("Ongoing rule modified. {0}".format(str(rule)))

        send_ongoing_rule_message(channel="ongoing_rule_state", data=rule)

    send_history_change_message()
    return json.dumps({"status": "OK"})
def deactivate_ongoing_rule():
    """User can deactivate ongoing rule from ui."""
    rule_id = request.args.get("id")
    database.update(database.QUERY[mn() + "_ongoing"].format(rule_id))
    database.update(database.QUERY[mn() + "_life"].format(rule_id))
    update_all_rules()

    send_ongoing_rule_message(channel="ongoing_rule_state",
                              data={
                                  "rule_id": rule_id,
                                  "status": 0
                              })

    send_history_change_message()
    return json.dumps({"status": "OK"})
Example #7
0
def migrate_data():
    database.select(database.QUERY[mn()])

    database.update(database.QUERY[mn() + "_insert"])
def activate_branch():
    """Blablbal."""
    # ============ check input params =======================
    mode = request.args.get("mode")
    if mode is None:
        logging.error("no 'mode' parameter passed")
        abort(500)

    if mode == "single":
        branch_id = int(request.args.get("id"))
        time_min = int(request.args.get("time_min"))
    elif mode == "interval":
        branch_id = int(request.args.get("id"))
        time_min = int(request.args.get("time_min"))
        time_wait = int(request.args.get("time_wait"))
        num_of_intervals = int(request.args.get("quantity"))
    elif mode == "auto":
        branch_id = int(request.args.get("id"))
        time_min = int(request.args.get("time_min"))
    else:
        logging.error("incorrect mode parameter passed: {0}".format(mode))
        abort(500)
    # ============ check input params =======================

    response_arr = get_line_status(branch_id)
    if response_arr[branch_id]["state"] != 1:
        try:
            response_arr = retry_branch_on(branch_id=branch_id,
                                           time_min=time_min)
        except Exception as e:
            logging.error(e)
            logging.error(
                "Can't turn on branch id={0}. Exception occured".format(
                    branch_id))
            abort(500)

        # needs to be executed in both cases single and interval, but in in auto
        if mode != "auto":
            interval_id = str(uuid.uuid4())
            now = datetime.datetime.now()
            stop_time = now + datetime.timedelta(minutes=time_min)

            database.update(database.QUERY[mn() + "_1"].format(
                branch_id, 1, 2, now.date(), now, interval_id, time_min))
            lastid = database.update(database.QUERY[mn() + "_1"].format(
                branch_id, 2, 1, now.date(), stop_time, interval_id, 0))
            logging.debug("lastid:{0}".format(lastid))

            res = database.select(database.QUERY[mn() + "_2"].format(lastid),
                                  "fetchone")
            logging.debug("res:{0}".format(res[0]))

            set_next_rule_to_redis(
                branch_id,
                {
                    "id": res[0],
                    "line_id": res[1],
                    "rule_id": res[2],
                    "user_friendly_name": res[6],
                    "timer": res[3],
                    "interval_id": res[4],
                    "time": res[5],
                },
            )
            logging.info("Rule '{0}' added".format(
                str(database.get_next_active_rule(branch_id))))

        if mode == "interval":
            # first interval is already added
            for x in range(2, num_of_intervals + 1):
                start_time = stop_time + datetime.timedelta(minutes=time_wait)
                stop_time = start_time + datetime.timedelta(minutes=time_min)
                database.update(database.QUERY[mn() + "_1"].format(
                    branch_id, 1, 1, now.date(), start_time, interval_id,
                    time_min))
                database.update(database.QUERY[mn() + "_1"].format(
                    branch_id, 2, 1, now.date(), stop_time, interval_id, 0))
                logging.info(
                    "Start time: {0}. Stop time: {1} added to database".format(
                        str(start_time), str(stop_time)))

        if mode == "auto":
            logging.info(
                "Branch '{0}' activated from rules service".format(branch_id))
        else:
            logging.info("Branch '{0}' activated manually".format(branch_id))
    else:
        logging.info(
            "Branch '{0}' already activated no action performed".format(
                branch_id))

    arr = form_responce_for_branches(response_arr)
    send_branch_status_message(arr)
    send_history_change_message()

    return jsonify(branches=arr)
def add_ongoing_rule(rules):
    now = datetime.datetime.now()
    for rule in rules:
        rule["line_id"] = int(rule["line_id"])
        rule["line_name"] = rule["line_name"]
        rule["time"] = int(rule["time"])
        rule["intervals"] = int(rule["intervals"])
        rule["time_wait"] = int(rule["time_wait"])
        rule["repeat_value"] = int(rule["repeat_value"])
        rule["date_start"] = convert_to_datetime(rule["date_start"])
        rule["time_start"] = convert_to_datetime(rule["time_start"])
        rule["date_time_start"] = datetime.datetime.combine(
            rule["date_start"], rule["time_start"].time())
        rule["end_date"] = convert_to_datetime(rule["end_date"])
        rule["active"] = 1
        rule["rule_id"] = str(uuid.uuid4())
        rule["days"] = -1

        if rule["date_start"].date() == rule["end_date"].date():
            date_delta = rule["end_date"].date() - now.date()
            if date_delta.days == 0:
                rule["days"] = 0
            if date_delta.days == 1:
                rule["days"] = 1

        # "INSERT INTO life(line_id, time, intervals, time_wait, repeat_value, date_start, "
        # "time_start, end_date, active, rule_id) "
        # "VALUES ({0}, '{1}', {2}, '{3}', {4}, {5}, '{6}', {7}, {8}, {9}")
        # insert into ongoing table
        database.update(database.QUERY[mn()].format(
            rule["line_id"],
            rule["time"],
            rule["intervals"],
            rule["time_wait"],
            rule["repeat_value"],
            rule["date_time_start"],
            rule["end_date"],
            rule["active"],
            rule["rule_id"],
        ))

        # update rules;
        update_rules_from_ongoing_rules(rule)
        logging.info("Ongoing rule added. {0}".format(str(rule)))

        template = render_template("ongoing_rule_single.html", n=rule)
        send_ongoing_rule_message(
            channel="add_ongoing_rule",
            data={
                "template": template,
                "rule_id": rule["rule_id"],
                "days": rule["days"],
            },
        )

    update_all_rules()
    try:
        lines = {}
        for line_id, line in BRANCHES_SETTINGS.items():
            response_status = remote_controller.line_status(line_id=line_id)
            lines[line_id] = dict(id=line_id,
                                  state=int(response_status[line_id]["state"]))

        arr = form_responce_for_branches(lines)
        send_branch_status_message(arr)
    except Exception as e:
        logging.error(e)
        logging.error("Can't send updated rules. Exception occured")

    send_history_change_message()
def update_rules_from_ongoing_rules(rule):
    """Form rules from ongoing rule."""
    database.update(database.QUERY[mn() + "_remove_from_life"].format(
        rule["rule_id"]))

    _delta = rule["end_date"] - rule["date_time_start"]
    _days = _delta.days + 1
    logging.info("number of days: {0}".format(_days))

    ongoing_rule_id = rule["rule_id"]

    for days_to_add in range(0, _days + 1, rule["repeat_value"]):
        date_datetime = rule["date_time_start"] + datetime.timedelta(
            days=days_to_add)

        # start_time = rule['date_time_start']
        branch_id = int(rule["line_id"])
        time_min = int(rule["time"])
        time_wait = int(rule["time_wait"])
        num_of_intervals = int(rule["intervals"])
        interval_id = str(uuid.uuid4())

        stop_datetime = date_datetime + datetime.timedelta(minutes=time_min)

        database.update(database.QUERY[mn() + "_add_rule_to_life"].format(
            branch_id,
            START_RULE,
            ENABLED_RULE,
            date_datetime.date(),
            date_datetime,
            interval_id,
            time_min,
            ongoing_rule_id,
        ))
        database.update(database.QUERY[mn() + "_add_rule_to_life"].format(
            branch_id,
            STOP_RULE,
            ENABLED_RULE,
            date_datetime.date(),
            stop_datetime,
            interval_id,
            0,
            ongoing_rule_id,
        ))

        logging.info(
            "Start time: {0}. Stop time: {1} added to database".format(
                str(date_datetime), str(stop_datetime)))

        # first interval is executed
        for x in range(2, num_of_intervals + 1):
            date_datetime = stop_datetime + datetime.timedelta(
                minutes=time_wait)
            stop_datetime = date_datetime + datetime.timedelta(
                minutes=time_min)

            database.update(database.QUERY[mn() + "_add_rule_to_life"].format(
                branch_id,
                START_RULE,
                ENABLED_RULE,
                date_datetime.date(),
                date_datetime,
                interval_id,
                time_min,
                ongoing_rule_id,
            ))
            database.update(database.QUERY[mn() + "_add_rule_to_life"].format(
                branch_id,
                STOP_RULE,
                ENABLED_RULE,
                date_datetime.date(),
                stop_datetime,
                interval_id,
                0,
                ongoing_rule_id,
            ))

            logging.info(
                "Start time: {0}. Stop time: {1} added to database".format(
                    str(date_datetime), str(stop_datetime)))
def stop_filling():
    """Blablbal."""

    device_id = "upper_tank"
    line_id = LINES_UPPER_TANK.get(device_id, None)

    logging.info(
        "INERUPT SIGNAL RESEIVED FROM '{0}' device!".format(device_id))
    database.update(database.QUERY[mn()])

    if line_id is None:
        logging.error("Unsupported '{0}' device id!".format(device_id))
        return json.dumps(
            {"status": "Unsupported '{0}' device id!".format(device_id)})

    _no_key = False
    response_arr = get_line_status(line_id)
    if response_arr[line_id]["state"] == 0:
        logging.info(
            "Line '{0}' is not active. Message won't be send.".format(line_id))
        return json.dumps({
            "status":
            "Line '{0}' is not active. Message won't be send.".format(line_id)
        })

    last_time_sent = get_time_last_notification()
    if last_time_sent is None:
        set_time_last_notification(date=datetime.datetime.now())
        last_time_sent = get_time_last_notification()
        _no_key = True

    delta = datetime.datetime.now() - last_time_sent
    if delta.seconds > 60 * TANK_NOTIFICATION_MINUTES or _no_key is True:
        try:
            logging.info("Deactivating line '{0}'.".format(line_id))
            deactivate_branch(line_id=line_id, mode="manually")
            logging.info("Line deactivated")
            message = "Водопостачання вимкнено автоматично."
        except Exception as e:
            logging.error(e)
            logging.error(
                "Can't deactivate line '{0}'. Exception occurred".format(
                    line_id))
            message = "Помилка. Водопостачання не вимкнено!"

        try:
            _users_list = TELEGRAM_USERS[device_id]
            logging.info(
                "Sending notify_filled message to users: '{0}'.".format(
                    str(_users_list)))
            payload = {"users": _users_list}
            response = requests.post(
                VIBER_BOT_IP + "/notify_filled",
                json=payload,
                timeout=(READ_TIMEOUT, RESP_TIMEOUT),
                verify=False,
            )
            response.raise_for_status()
            logging.info("Messages send.")
        except Exception as e:
            logging.error(e)
            logging.error("Can't send rule to telegram. Exception occurred")

        try:

            logging.info("Updating redis.")
            set_time_last_notification(date=datetime.datetime.now())
            logging.info("Redis updated")
        except Exception as e:
            logging.error(e)
            logging.error("Can't update redis. Exception occured")

        try:
            logging.info(
                "Sending line deactivated message to users: '{0}'.".format(
                    str(_users_list)))
            payload = {"users": _users_list, "message": message}
            response = requests.post(
                VIBER_BOT_IP + "/send_message",
                json=payload,
                timeout=(READ_TIMEOUT, RESP_TIMEOUT),
                verify=False,
            )
            response.raise_for_status()
            logging.info("Messages send.")
        except Exception as e:
            logging.error(e)
            logging.error("Can't send rule to telegram. Exception occured")
            return json.dumps(
                {"status": "Can't send rule to telegram. Exception occured"})

        return json.dumps({"status": "Redis updated"})
    else:
        logging.info(
            "{0} minutes not passed yet. Send message pending.".format(
                TANK_NOTIFICATION_MINUTES))
        return json.dumps({
            "status":
            "{0} minutes not passed yet. Send message pending.".format(
                TANK_NOTIFICATION_MINUTES)
        })
Example #12
0
def enable_rule():
    """Synch with redis each 10 seconds. Execute rules if any."""
    try:
        logging.info("enable rule thread started.")

        logging.info("Updating rules on start.")
        update_all_rules()

        logging.info("Synch with redis.")
        sync_rules_from_redis()
        rules_to_log()

        logging.info("Entering While loop")
        start_time = datetime.datetime.now()
        while True:
            # logging.info("enable_rule_daemon heartbeat. RULES_FOR_BRANCHES: {0}".format(str(RULES_FOR_BRANCHES)))
            time.sleep(10)
            sync_rules_from_redis()

            for rule in RULES_FOR_BRANCHES:
                if rule is None:
                    continue

                now_time = datetime.datetime.now()

                # Send message to log ones per 10 minutes
                delta = now_time - start_time
                if delta.seconds >= 60 * 10:
                    rules_to_log()
                    start_time = now_time

                # send message to messenger X minutes  before rules execution started
                if now_time >= (rule["timer"] - datetime.timedelta(
                        minutes=VIBER_SENT_TIMEOUT)):
                    try:
                        send_to_viber_bot(rule)
                    except Exception as e:
                        logging.error(
                            "Can't send rule {0} to viber. Exception occured. {1}"
                            .format(str(rule), e))

                # Start of execution
                if now_time >= rule["timer"]:

                    # Check rain volume for last X hours
                    if inspect_conditions(rule) is False:
                        logging.error(
                            "Rule can't be executed cause of rain volume too high"
                        )
                        database.update(
                            database.QUERY[mn() + "_canceled_by_rain"].format(
                                rule["id"]))
                        set_next_rule_to_redis(
                            rule["line_id"],
                            database.get_next_active_rule(rule["line_id"]),
                        )
                        continue

                    # Troubleshoot case. In case timedelta more than 5 minutes - skip rule
                    logging.info(
                        "Rule '{0}' execution is about to start. Checking time delta not more than '{1}' minutes"
                        .format(str(rule), MAX_DELTA_FOR_RULES_SERVICE))
                    delta = now_time - rule["timer"]
                    if delta.seconds >= 60 * MAX_DELTA_FOR_RULES_SERVICE:
                        logging.error(
                            "Rule execution won't be started since time delta more than'{0}' minutes"
                            .format(MAX_DELTA_FOR_RULES_SERVICE))
                        database.update(
                            database.QUERY[mn() +
                                           "_canceled_by_mistime"].format(
                                               rule["id"]))
                        set_next_rule_to_redis(
                            rule["line_id"],
                            database.get_next_active_rule(rule["line_id"]),
                        )
                        continue
                    else:
                        logging.info("Rule execution allowed")

                    logging.info("Rule '{0}' execution started".format(
                        str(rule)))

                    try:
                        if rule["rule_id"] == 1:
                            branch_on(rule["line_id"], rule["time"])

                        if rule["rule_id"] == 2:
                            branch_off(rule["line_id"])

                    except Exception as e:
                        logging.error(
                            "Rule '{0}' can't be executed. Exception occured. {1}"
                            .format(str(rule), e))
                        # Set failed state
                        database.update(
                            database.QUERY[mn() + "_cancel_interval"].format(
                                rule["interval_id"], 3))
                        database.update(database.QUERY[mn()].format(
                            rule["id"], 3))
                    else:
                        logging.info("Rule '{0}' is done.".format(str(rule)))
                        # Set ok state
                        database.update(database.QUERY[mn()].format(
                            rule["id"], 2))
                    finally:
                        logging.info(
                            "Get next active rule for {0} line id.".format(
                                rule["line_id"]))
                        set_next_rule_to_redis(
                            rule["line_id"],
                            database.get_next_active_rule(rule["line_id"]),
                        )
    except Exception as e:
        logging.error("enable rule thread exception occured. {0}".format(e))
    finally:
        logging.info("enable rule thread stopped.")