Example #1
0
class Main():
    def __init__(self):
        self.commans = (Play(), Variable(), Speech(), Info())  #, Sinoptik())
        self.db = DBConnector()
        # Очищаем список команд. Список не актуален.
        self.db.IUD("delete from core_execute")
        self.last_processed_ID = -1
        self.db.commit()
        self.run()

    def run(self):
        while True:
            try:
                for row in self.db.select("select ID, COMMAND "
                                          "  from core_execute "
                                          " where ID > %s "
                                          "order by ID" %
                                          (self.last_processed_ID)):
                    print(str(row[1], "utf-8"))
                    for c in str(row[1], "utf-8").split("\n"):
                        self.execute(c.strip())
                    self.last_processed_ID = row[0]
                time.sleep(0.1)

                # Дергаем секундный таймер, может кому пригодится
                for cmd in self.commans:
                    cmd.time_handler()
            except mysql.connector.Error as e:
                self.execute('speech("пропала связь с базой", "alarm")')
                time.sleep(10)

    def execute(self, command):
        print("[%s] выполняется %s" %
              (time.strftime("%d-%m-%Y %H:%M"), command))
        for cmd in self.commans:
            if cmd.check_comm(self.db, command):
                break
Example #2
0
class VideoAlerts:
    def __init__(self, host, port):
        self.camIds = [166, 167, 168, 169]
        self.host = host
        self.port = port
        self.sessionID = ""
        self.bs = bytearray()
        self.bbs = bytearray(4)
        self.db = DBConnector()

    def run(self):
        while True:
            try:
                self.sock = socket.socket()
                self.sock.connect((self.host, self.port))
                self._send_login()
                self._send_empty()
                i = 0
                while True:
                    res = self.sock.recv(10240)
                    if res != b'':
                        res = res[20::].decode("cp1251")
                        for line in res.split('\n'):
                            try:
                                a = json.loads(line)
                                if a['Name'] == "AlarmInfo":
                                    c = a['AlarmInfo']
                                    if c['Event'] == 'VideoMotion':
                                        var_v = 0
                                        if c['Status'] == 'Start':
                                            var_v = 1
                                        cam = c['Channel']
                                        var_id = self.camIds[cam]
                                        self._print(
                                            "Замечено движение на камере %s (статус %s)"
                                            % (cam + 1, var_v))
                                        self.db.IUD(
                                            "call CORE_SET_VARIABLE(%s, %s, null)"
                                            % (var_id, var_v))
                                        self.db.commit()
                            except Exception as e:
                                #print("{}".format(e))
                                pass

                        if i >= 5:
                            i = -1
                            self._send_empty()
                        i += 1
                    else:
                        break
                    time.sleep(0.2)
            except Exception as e:
                print("{}".format(e))

            time.sleep(1)

            try:
                self.sock.close()
            except:
                print('error')

    def _send_pack(self, data):
        s = b'\xff' + self.bbs + data + b'\n'
        self.sock.sendall(s)
        #print("CLIENT: ", s)
        res = self.sock.recv(10240)
        #print("SERVER: ", res)
        return res

    def _send_login(self):
        data = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x03d\x00\x00\x00{ "EncryptType" : "MD5", "LoginType" : "DVRIP-Web", "PassWord" : "tlJwpbo6", "UserName" : "admin" }'
        res = self._send_pack(data)
        res = res[20::].decode("cp1251").replace("\n", "").replace(chr(0), "")
        a = json.loads(res)
        self.sessionID = a['SessionID']
        self.bs = bytearray(self.sessionID, "cp1251")
        self.bbs = self._sessIdtoHex(self.sessionID)

    def _send_empty(self):
        data = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdc\x05,\x00\x00\x00{ "Name" : "", "SessionID" : "' + self.bs + b'" }'
        self._send_pack(data)
        #print("PING")

    def _decodeHex(self, s):
        if s in '0123456789':
            return int(s)
        elif s == 'a':
            return 10
        elif s == 'b':
            return 11
        elif s == 'c':
            return 12
        elif s == 'd':
            return 13
        elif s == 'e':
            return 14
        else:
            return 15

    def _sessIdtoHex(self, s):
        res = bytearray(4)
        s = s[2::]
        for i in range(4):
            b1 = s[i * 2]
            b2 = s[i * 2 + 1]
            res[i] = (self._decodeHex(b1.lower()) << 4) + self._decodeHex(
                b2.lower())
        return res

    def _print(self, text):
        print("[%s] %s" % (time.strftime("%d-%m-%Y %H:%M:%S"), text))
Example #3
0
class Main():
    def __init__(self):
        self.db = DBConnector()
        self.termostats = []
        self._add_termostat(50, 49, "В хозяйской спальне")  #Спальня №3
        self._add_termostat(47, 46, "В детской спальне")  #Спальня №2
        self._add_termostat(44, 43, "В гостевой спальне")  #Спальня №1
        self._add_termostat(60, 59, "В гостинной")  #Гостинная
        self._add_termostat(66, 65, "В кухне")  #Кухня

        # ID, CHANNEL, VALUE
        self.BMP280_VARS = [[150, "t", None], [151, "p", None]]
        self.bmp280_drv = None
        self.bmp280_init()

        self.cam_alerts = []
        self._load_cam_alerts()

        self.run()

    def bmp280_init(self):
        addr = 0x76
        for i in range(2):
            addr += i
            try:
                self.bmp280_drv = BMP280(addr)
                print("BMP280 OK: %s" % (hex(addr)))
            except:
                print("BMP280 ERROR: %s" % (hex(addr)))

    def run(self):
        termostats_time_step = 0
        bmp280_time_step = 0
        clear_db_mem_time_ignore = False
        boiler_term = None
        while True:
            relIds = []
            relIds_named = []
            for keys in self.db.select("select CORE_GET_LAST_CHANGE_ID()"):
                if keys[0] - 1 > self.db.lastVarChangeID:
                    # c.ID, c.VARIABLE_ID, c.VALUE, v.APP_CONTROL, v.GROUP_ID
                    for row in self.db.variable_changes():
                        if row[3] == 1:  # Слежение за светом
                            relIds += [str(row[1]), ","]
                        if row[3] == 3:  # Слежение за розетками
                            relIds_named += [str(row[1]), ","]
                        elif row[
                                3] == 8:  # Слежение за пиродатчиками (камерами)
                            try:
                                cam_num = self.cam_alerts.index(row[1]) + 1
                                if row[2] == 1:
                                    self._add_command(
                                        'speech("Замечено движение на камере %s", "notify")'
                                        % (cam_num))
                            except:
                                pass
                        elif row[3] == 4:  #Термометры
                            for r in self.termostats:
                                if r[2] == row[1]:
                                    r[3] = row[2]
                            # критические температуры
                            if row[1] == 95 and row[2] > 55:  # Дымоход
                                self._add_command(
                                    'speech("Температура дымохода %s градусов", "alarm")'
                                    % (round(row[2])))
                            if row[1] == 93:
                                boiler_term = row[2]
                                if row[2] > 55:  # Подача котла
                                    self._add_command(
                                        'speech("Температура котла %s градусов", "alarm")'
                                        % (round(row[2])))
                                elif row[2] >= 45 and row[2] <= 48:
                                    self._add_command(
                                        'speech("Котел холодный", "notify")')
                            # -----------------------
                        elif row[3] == 5:  #Термостаты
                            for r in self.termostats:
                                if r[0] == row[1]:
                                    r[1] = row[2]
                        elif row[1] == 163 and row[2] == 1:
                            self._add_command(
                                'speech("Прозвенел звон*ок на воротах")')

                    if len(relIds) > 0:
                        for row in self.db.select(
                                "select v.APP_CONTROL, c.NAME, p.NAME, v.VALUE "
                                "  from core_variables v, core_variable_controls c, plan_parts p "
                                " where v.ID in (%s) "
                                "   and v.APP_CONTROL = c.ID "
                                "   and v.GROUP_ID = p.ID "
                                " order by v.ID" % ("".join(relIds[:-1]), )):
                            s = [
                                str(row[2], "utf-8"), ". ",
                                str(row[1], "utf-8"), " "
                            ]
                            if row[3]:
                                s += ["включен"]
                            else:
                                s += ["выключен"]

                            self._add_command('speech("%s", "notify")' %
                                              "".join(s).lower())

                    if len(relIds_named) > 0:
                        for row in self.db.select(
                                "select v.COMM, v.VALUE "
                                "  from core_variables v "
                                " where v.ID in (%s) " %
                            ("".join(relIds_named[:-1]), )):
                            comm = str(row[0], "utf-8")
                            s = [comm, " "]
                            if comm[-1::].upper() == "А":
                                if row[1]:
                                    s += ["включена"]
                                else:
                                    s += ["выключена"]
                            else:
                                if row[1]:
                                    s += ["включен"]
                                else:
                                    s += ["выключен"]

                            self._add_command('speech("%s", "notify")' %
                                              "".join(s).lower())

            if termostats_time_step == 0:
                termostats_time_step = round(15 * 60 / 0.2)
                if boiler_term != None and boiler_term > 30:
                    for t in self.termostats:
                        if t[3] > t[1] + 0.2:  # Перегрели
                            self._add_command('speech("%s жарко", "notify")' %
                                              (t[4]))
                        elif t[3] < t[1] - 0.2 and t[
                                3] > t[1] - 1:  # Переостудили
                            self._add_command(
                                'speech("%s холодно", "notify")' % (t[4]))
            termostats_time_step -= 1

            if bmp280_time_step == 0:
                bmp280_time_step = round(60 / 0.2)
                self._check_bmp280()
            bmp280_time_step -= 1

            # -------------------------------------------
            if datetime.datetime.now().hour == 4:
                if not clear_db_mem_time_ignore:
                    clear_db_mem_time_ignore = True
                    self.clear_mem_db()
                    self.clear_values()
            else:
                clear_db_mem_time_ignore = False
            # -------------------------------------------

            time.sleep(0.2)

    def _add_termostat(self, tst_id, trm_id, title):
        # Зачитка стартовых значений
        for rec in self.db.select(
                "select VALUE from core_variables where ID = %s" % (tst_id)):
            tst_val = rec[0]
        for rec in self.db.select(
                "select VALUE from core_variables where ID = %s" % (trm_id)):
            trm_val = rec[0]
        # ---------------------------
        self.termostats += [[tst_id, tst_val, trm_id, trm_val, title]]

    def _check_bmp280(self):
        try:
            res = self.bmp280_drv.get_data()
            t = res["t"]
            p = res["p"]

            for var in self.BMP280_VARS:
                if var[2] != res[var[1]]:
                    var[2] = res[var[1]]
                    self.db.IUD("call CORE_SET_VARIABLE(%s, %s, null)" %
                                (var[0], var[2]))
                    self.db.commit()
        except Exception as e:
            self.bmp280_init()
            print(e)

    def _add_command(self, command):
        print("[%s] %s" % (time.strftime("%d-%m-%Y %H:%M"), command))
        """
        if self.get_quiet_time() and alarm == False:
            try:
                command.index("speech(")
                command = "speech(\"\")"
            except:
                pass
        """
        self.db.IUD("insert into core_execute (COMMAND) values ('%s')" %
                    command)
        self.db.commit()

    def get_quiet_time(self):
        for rec in self.db.select(
                "select VALUE from core_variables where NAME = 'QUIET_TIME'"):
            if rec[0]:
                return True
        return False

    def _load_cam_alerts(self):
        self.cam_alerts = []
        for rec in self.db.select(
                "select NAME, ALERT_VAR_ID from plan_video order by ORDER_NUM"
        ):
            self.cam_alerts += [rec[1]]

    def _clear_mem_db_table(self, table, space=100):
        for rec in self.db.select("select MAX(ID) from %s" % (table)):
            if rec[0]:
                max_id = rec[0] - space
                self.db.IUD("delete from %s where ID < %s" % (table, max_id))
                self.db.commit()

    def clear_mem_db(self):
        try:
            self._clear_mem_db_table("app_control_exe_queue")
            self._clear_mem_db_table("app_control_queue")
            self._clear_mem_db_table("app_control_sess")
            self._clear_mem_db_table("core_execute")
            self._clear_mem_db_table("core_variable_changes_mem")
            print("[%s] CLEAR MEM TABLES" % (time.strftime("%d-%m-%Y %H:%M")))
        except Exception as e:
            print(e)

    def clear_values(self):
        try:
            subprocess.call(
                'python3 /home/pyhome/server/watcher/clear_values_15.py',
                shell=True)
        except:
            pass
Example #4
0
    if row[2] == prev_var_id:
        if row[3] - prev_var_time < 600 and check_values(
                values, row):  # Если часто, то вкидываем на просмотр
            values += [row]
        else:
            if len(values) > 2:
                f1, f2 = values[:2]
                l1, l2 = values[-2:]

                drop_ids = []
                for r in values:
                    if r[0] != f2[0] and r[0] != l1[0]:
                        drop_ids += [str(r[0]), ","]

                d = "".join(drop_ids[:-1])
                db.IUD("delete from core_variable_changes where ID in (%s)" %
                       (d))

                v_f, v_l = f1[1] + (f2[1] - f1[1]) / 2, l1[1] + (l2[1] -
                                                                 l1[1]) / 2
                db.IUD(
                    "update core_variable_changes set VALUE = %s where ID = %s"
                    % (v_f, f2[0]))
                db.IUD(
                    "update core_variable_changes set VALUE = %s where ID = %s"
                    % (v_l, l1[0]))
                db.commit()

            values = [row]

        prev_var_time = row[3]
        prev_var_value = row[1]
Example #5
0
class Main():
    def __init__(self):
        self.db = DBConnector()
        self.db.IUD("update core_scheduler set ACTION_DATETIME = NULL")
        self.db.commit()

        print("-- Предстоящие задачи --")
        for row in self.db.select(
                "select ID, COMM, ACTION, ACTION_DATETIME, INTERVAL_TIME_OF_DAY, INTERVAL_DAY_OF_TYPE, INTERVAL_TYPE, ENABLE from core_scheduler"
        ):
            next_time = self.parse_time(None, str(row[4], "utf-8"),
                                        str(row[5], "utf-8"), row[6])
            enable = ""
            if row[7] == 0:
                enable = "      [НЕ ВЫПОЛНЯТЬ!!!]"
            print("[%s] %s %s" % (datetime.datetime.fromtimestamp(next_time),
                                  str(row[1], "utf-8"), enable))
        print("------------------------")
        self.check_time()
        self.run()

    def check_time(self):
        now = datetime.datetime.now().timestamp()
        for row in self.db.select(
                "select ID, COMM, ACTION, ACTION_DATETIME, INTERVAL_TIME_OF_DAY, INTERVAL_DAY_OF_TYPE, INTERVAL_TYPE, ENABLE from core_scheduler"
        ):
            next_time = None
            if row[3] == None:  # Это обнуленная дата - будет перещитана в холостую относительно текущей
                next_time = self.parse_time(None, str(row[4], "utf-8"),
                                            str(row[5], "utf-8"), row[6])
            elif row[3].timestamp(
            ) <= now:  # Это дата, что пришла для выполнения. Выполняем и перещитываем.
                next_time = self.parse_time(row[3].timestamp(),
                                            str(row[4], "utf-8"),
                                            str(row[5], "utf-8"), row[6])
                if row[7]:  # Проверка на Выполнять/Не выполнять
                    self.execute(str(row[1], "utf-8"), str(row[2], "utf-8"))
                if row[6] == 4:  # Одноразовая задача выполнена. Удаляем ее запись.
                    self.db.IUD("delete from core_scheduler where ID = %s" %
                                (row[0]))
                    self.db.commit()
            if next_time != None:
                #self.db.IUD("update core_scheduler set ACTION_DATETIME = FROM_UNIXTIME(%s) where ID = %s" % (next_time, row[0]))
                d_s = datetime.datetime.fromtimestamp(next_time).strftime(
                    "%Y-%m-%d %H:%M:%S")
                self.db.IUD(
                    "update core_scheduler set ACTION_DATETIME = '%s' where ID = %s"
                    % (d_s, row[0]))
                self.db.commit()

    def calc_suntime(self, d, sun_type):
        st = GetSunTime(d // (24 * 3600), 49.697287, 34.354388,
                        90.8333333333333, (-time.altzone // 3600) - 1,
                        sun_type)
        hour = math.trunc(st)
        minutes = round((st - hour) * 60)
        return (hour * 60 + minutes) * 60

    def parese_sun_delta(self, comm):
        """
        SUNRISE - 1
        SUNRISE - 1:03
        SUNRISE - 1:03:02
        """
        s = comm
        s = s.replace("SUNSET", "")
        s = s.replace("SUNRISE", "")
        s = s.replace(" ", "")
        try:
            is_minus = s[0] == "-"
        except:
            is_minus = False
        s = s.replace("-", "")
        a = s.split(":")
        h, m, s = 0, 0, 0
        try:
            if len(a) > 0:
                h = int(a[0])
            if len(a) > 1:
                m = int(a[1])
            if len(a) > 2:
                s = int(a[2])
        except:
            pass

        res = h * 3600 + m * 60 + s
        if is_minus:
            res = -res
        return res

    def parse_time(self, action_datetime, time_of_day, day_of_type, int_type):
        if action_datetime == None:
            action_datetime = datetime.datetime.now().timestamp()

        now = datetime.datetime.now()
        now = datetime.datetime(now.year, now.month, now.day)

        times = []
        dates = []

        time_type = ""
        try:
            time_of_day.upper().index("SUNRISE")
            time_type = "Sunrise"
        except:
            pass

        try:
            time_of_day.upper().index("SUNSET")
            time_type = "Sunset"
        except:
            pass

        if time_type == "Sunrise" or time_type == "Sunset":
            """
            Это особый случай блуждающего времени.
            Сборка даты/времени выполняется здесь отдельно и дальше код
            не пойдет.
            """

            sun_delta = self.parese_sun_delta(time_of_day.upper())

            d1 = now.timestamp()
            d2 = now.timestamp() + 24 * 3600
            dt = [
                d1 + self.calc_suntime(d1, time_type) + sun_delta,
                d2 + self.calc_suntime(d2, time_type) + sun_delta
            ]

            dt.sort()

            # Проверяем какая дата из расписания готова к выполнению
            for d in dt:
                if d > action_datetime:
                    return d
            return None
        else:
            # Получаем список времени в секундах
            for t in time_of_day.split(","):
                m = t.split(":")
                hour = int(m[0].strip()) * 60
                minutes = 0
                try:
                    minutes = int(m[1].strip())
                except:
                    pass
                sec = 0
                try:
                    sec = int(m[2].strip())
                except:
                    pass
                s = hour + minutes
                times += [s * 60 + sec]

        if int_type == 0:
            # Сегодняшняя дата и завтрашняя
            dates += [now.timestamp(), now.timestamp() + 24 * 3600]
        elif int_type == 1:
            # Получаем дату понедельника этой недели в секундах
            dw = now.timestamp() - now.weekday() * 24 * 3600
            # Получаем дату понедельника следующей недели в секундах
            dw_next = dw + 7 * 24 * 3600
            w = ["пн", "вт", "ср", "чт", "пт", "сб", "вс"]
            for d in day_of_type.split(","):
                s = w.index(d.strip().lower())
                dates += [dw + (s * 24 * 3600)]
                dates += [dw_next + (s * 24 * 3600)]
        elif int_type == 2:
            # Получаем 1 число этого месяца в секундах
            m = datetime.datetime(now.year, now.month, 1).timestamp()
            # Получаем 1 число следующего месяца в секундах
            if now.month < 12:
                m_next = datetime.datetime(now.year, now.month, 1).timestamp()
            else:
                m_next = datetime.datetime(now.year + 1, 1, 1).timestamp()

            for d in day_of_type.split(","):
                s = int(d.strip())
                dates += [m + (s * 24 * 3600)]
                dates += [m_next + (s * 24 * 3600)]

        elif int_type == 3 or int_type == 4:  # Ежегодно или Только один раз
            for d in day_of_type.split(","):
                m = d.split("-")
                s = datetime.datetime(now.year, int(m[1].strip()),
                                      int(m[0].strip())).timestamp()
                dates += [s]
                s_next = datetime.datetime(now.year + 1, int(m[1].strip()),
                                           int(m[0].strip())).timestamp()
                dates += [s_next]

        dt = []

        # Собираем дату и время расписания в одно
        for tim in times:
            if len(dates) > 0:
                for dat in dates:
                    dt += [dat + tim]

        dt.sort()

        # Проверяем какая дата из расписания готова к выполнению
        for d in dt:
            if d > action_datetime:
                return d

        return None

    def execute(self, comm, action):
        self.db.IUD("insert into core_execute (COMMAND) values ('%s')" %
                    (action))
        self.db.commit()
        print("[%s] Произошло событие \"%s\"" %
              (time.strftime("%d-%m-%Y %H:%M"), comm))
        print("                   и запрошена команда %s" % (action))

    def run(self):
        while True:
            self.check_time()
            time.sleep(1)