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)
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"})
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) })
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.")