Exemple #1
0
 def test_before_running(self):
     before_running()
     print(r.get('id_num'))
     print(r.get('plc'))
     print(r.get('group_upload'))
     print(r.get('group_read'))
     print(r.get('variable'))
Exemple #2
0
def self_check():
    """
    celery任务
    定时自检
    
    :return: 
    """

    logging.debug('自检')

    current_time = int(time.time())

    session = Session()
    try:
        # 获取站点配置信息
        id_num = r.get('id_num')

        # 获取上次检查时间并检查时间间隔,判断程序运行状态
        check_time = r.get('check_time')
        if check_time:
            check_time = int(check_time)
            # logging.debug('上次检查时间:{}'.format(datetime.datetime.fromtimestamp(check_time)))
            if current_time - check_time > CHECK_DELAY:
                check_time_err(id_num)
        r.set('check_time', current_time)

        # 检查与服务器通讯状态
        con_time = r.get('con_time')
        if con_time:
            con_time = int(con_time)
            # logging.debug('上次服务器通讯时间:{}'.format(datetime.datetime.fromtimestamp(con_time)))
            if current_time - con_time > SERVER_TIMEOUT:
                connect_server_err(id_num)

        # 检查PLC通讯状态
        plcs = r.get('plc')
        if not plcs:
            plc_models = session.query(YjPLCInfo)
            plcs = plc_info(r, plc_models)
            r.set('plc', plcs)

        for plc in plcs:
            plc_connect_time = int(plc['time'])
            # logging.debug('PLC连接时间:{}'.format(datetime.datetime.fromtimestamp(plc_connect_time)))

            # 超过一定时间的上传服务器
            if current_time - plc_connect_time > PLC_TIMEOUT:
                connect_plc_err(
                    id_num,
                    plc_id=plc['id'],
                )

        # 数据库写入,关闭连接
        session.commit()
    finally:
        session.close()
Exemple #3
0
def server_confirm(url):
    """
    发送请求后,收到服务器回执的确认

    :param url: 具体确认某个功能的地址
    :return: 
    """

    id_num = r.get('id_num')
    post_data = {'id_num': id_num}

    post_data = json.dumps(post_data)
    # print(post_data)
    try:
        rp = req_s.post(url,
                        data=post_data,
                        timeout=(CONNECT_TIMEOUT, REQUEST_TIMEOUT))
    except RequestException as e:
        logging.warning('确认请求发送失败: ' + str(e))
        connect_server_err(id_num, str(url))
        return False
    else:
        http_code = rp.status_code
        if http_code == 200:
            return True
        else:
            return False
Exemple #4
0
def plc_write(variable_model, plc_cli, plc_model):
    id_num = r.get('id_num')
    # 获取变量读写类型
    rw_type = variable_model.rw_type
    value = variable_model.write_value

    # 判断变量存在写操作
    if rw_type == 2 or rw_type == 3 and value is not None:

        # 获取写入变量值所需信息
        data_type = variable_model.data_type
        db = variable_model.db_num
        area = variable_area(variable_model)
        address = int(math.modf(variable_model.address)[1])
        bool_index = round(math.modf(variable_model.address)[0] * 10)
        size = variable_size(data_type)

        # 获取当前字节
        try:
            result = plc_cli.read_area(
                area=area,
                dbnumber=db,
                start=address,
                size=size
            )
        except Snap7Exception as e:
            logging.error('plc_read', str(e))
            read_err(
                id_num=id_num,
                plc_id=plc_model.id,
                plc_name=plc_model.plc_name,
                area=area,
                db_num=db,
                address=address,
                data_type=data_type
            )

        else:

            # 将写入数据转为字节码
            byte_value = write_value(
                data_type,
                result,
                value,
                bool_index=bool_index
            )

            # 数据写入
            plc_cli.write_area(
                area=area,
                dbnumber=db,
                start=address,
                data=byte_value
            )
Exemple #5
0
def beats():
    """
    celery任务
    与服务器的心跳连接
    
    :param : 
    :return: 
    """
    logging.debug('心跳连接')

    current_time = int(time.time())

    # 从数据库获取站点信息
    id_num = ID_NUM

    # 获取上次心跳时间
    con_time = r.get('con_time')

    # 获取心跳时上传的数据
    data = beats_data(id_num, con_time, current_time)
    # print(data)
    data = encryption_client(data)

    # 发送心跳包
    try:
        rv = req_s.post(BEAT_URL,
                        data=data,
                        timeout=(CONNECT_TIMEOUT, REQUEST_TIMEOUT))

    # 连接服务器失败
    except (RequestException, MaxRetriesExceededError) as e:
        logging.warning('心跳连接错误:' + str(e))
        connect_server_err(id_num)

    # 连接成功
    else:
        # data = decryption_client(rv.json())
        # print(rv.status_code)
        data = rv.json()
        # print(data)

        # 更新服务器通讯时间
        r.set('con_time', current_time)

        # 配置有更新
        if data.get('is_modify') == 1:
            logging.info('发现配置有更新,准备获取配置')
            get_config()
            before_running()

        if data.get('command'):
            remote_command(data.get('command'))
Exemple #6
0
def check_upload():
    """
    检查变量组上传时间,将满足条件的变量组数据打包上传
    
    :return: 
    """
    # upload_time1 = time.time()
    logging.debug('检查变量组上传时间')
    # print('上传')

    current_time = int(time.time())

    # 在redis中查询需要上传的变量组id
    group_upload_data = r.get('group_upload')

    # print(group_upload_data)

    for g in group_upload_data:
        if current_time >= g['upload_time']:
            g['is_uploading'] = True
    r.set('group_upload', group_upload_data)

    group_id = []
    value_list = list()

    # dtime1 = time.time()
    for g in group_upload_data:
        if current_time >= g['upload_time']:
            value_list += upload_data(g, current_time)
            group_id.append(g['id'])
            g['last_time'] = g['upload_time']
            g['upload_time'] = current_time + g['upload_cycle']
            # 设置为不在上传的状态
            g['is_uploading'] = False

            # print('下次上传时间', datetime.datetime.fromtimestamp(g['upload_time']))
    # dtime2 = time.time()
    # print('data', dtime2 - dtime1)
    # print(group_id)

    # print('上传数据', len(value_list), value_list)
    # utime1 = time.time()
    upload(value_list, group_id)
    # utime2 = time.time()
    # print('upload', utime2 - utime1)

    r.set('group_upload', group_upload_data)
Exemple #7
0
def plc_connect(plc):
    client = Client()
    try:
        client.connect(
            address=plc['ip'],
            rack=plc['rack'],
            slot=plc['slot'],
        )
    except Snap7Exception as e:
        logging.warning('PLC连接失败 ip:{} rack:{} slot:{}'.format(plc['ip'], plc['rack'], plc['slot']) + str(e))
        id_num = r.get('id_num')
        connect_plc_err(
            id_num,
            plc_id=plc['id'],
        )

    return client
Exemple #8
0
def upload(variable_list, group_id):
    """
    数据上传
    :param variable_list: 
    :param group_id: 
    :return: 
    """

    logging.debug('上传数据')

    # 获取本机信息
    id_num = r.get('id_num')

    # 包装数据
    data = {'id_num': id_num, 'value': variable_list}
    # print('upload_value', variable_list)
    # print('upload_len', len(variable_list))
    # print('上传数据数量', len(data['value']))

    data = encryption_client(data)

    # 上传日志记录
    # logging.info('group_id: {}将要上传.'.format(group_id))

    # 连接服务器,准备上传数据
    try:
        rv = req_s.post(UPLOAD_URL,
                        data=data,
                        timeout=(CONNECT_TIMEOUT, REQUEST_TIMEOUT))
    except RequestException as e:
        logging.warning('上传数据错误:' + str(e))

        connect_server_err(id_num)

    else:
        # 日志记录
        # 正常传输
        if rv.status_code == 200:
            logging.info('group_id: {}成功上传.'.format(group_id))

        # 未知错误
        else:
            logging.error('upload无法识别服务端反馈 group_id: {}'.format(group_id))
            server_return_err(id_num, 'upload group_id: {}'.format(group_id))
Exemple #9
0
def ntpdate():
    # 使用supervisor启动时用户为root 不需要sudo输入密码 不安全
    pw = 'touhou'

    cmd2 = 'echo {0} | sudo -S ntpdate {1}'.format(pw, NTP_SERVER)
    ntp = subprocess.Popen(cmd2,
                           shell=True,
                           stdin=subprocess.PIPE,
                           stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE)
    status = ntp.wait()
    stdout, stderr = ntp.communicate()

    if not status:  # 判断进程执行状态
        note = '完成校时 :{0}'.format(stdout.decode('utf-8'))
        logging.info(note)
    else:
        note = '校时失败 :{0}'.format(stderr.decode('utf-8'))
        logging.error(note)
        id_num = r.get('id_num')
        ntpdate_err(id_num=id_num, note=note)
Exemple #10
0
def plc_client(ip, rack, slot, plc_id):
    """
    建立plc连接的上下文管理器
    :param ip: 
    :param rack: 
    :param slot: 
    :return: 
    """
    client = Client()
    try:
        client.connect(ip, rack, slot)
    except Snap7Exception as e:
        logging.warning('连接plc失败' + str(e))
        session = Session()
        id_num = r.get('id_num')
        alarm = connect_plc_err(id_num, plc_id)
        session.add(alarm)
        session.commit()
    yield client
    client.disconnect()
    client.destroy()
Exemple #11
0
 def test_beats_data(self):
     id_num = r.get('id_num')
     con_time = r.get('con_time')
     current_time = int(time.time())
     print(beats_data(id_num, con_time, current_time))
Exemple #12
0
def get_config():
    """
    连接服务器接口,获取本机变量信息

    :return: 
    """
    gtime1 = int(time.time())
    logging.debug('连接服务器,获取数据')

    current_time = time.time()

    # 获取本机信息
    id_num = r.get('id_num')

    post_data = {'id_num': id_num}
    post_data = json.dumps(post_data)
    # logging.info('获取配置,发送请求:' + str(post_data))

    # 连接服务器
    try:
        time_c1 = time.time()
        rv = req_s.post(CONFIG_URL,
                        data=post_data,
                        timeout=(CONNECT_TIMEOUT, REQUEST_TIMEOUT))
        time_c2 = time.time()
        print('连接服务器获取配置', time_c2 - time_c1)
    # 连接失败
    except RequestException as e:
        logging.warning('获取配置错误:' + str(e))

        connect_server_err(id_num)

    # 连接成功
    else:
        # 记录本次服务器通讯时间
        r.set('con_time', current_time)

        if rv.status_code == 200:
            rp = rv.json()

            # data = rp['data']
            data = decryption_client(rp['data'])

            # print(data)
            time11 = time.time()

            with ConnMySQL() as db:
                cur = db.cursor()
                try:
                    # 配置更新,清空现有表
                    cur.execute('SET foreign_key_checks = 0')
                    cur.execute('truncate table `variables_groups`')
                    cur.execute('truncate table alarm_info')
                    # cur.execute('truncate table `values`')
                    cur.execute('truncate table yjvariableinfo')
                    cur.execute('truncate table yjgroupinfo')
                    cur.execute('truncate table yjplcinfo')
                    cur.execute('truncate table yjstationinfo')
                    cur.execute('SET foreign_key_checks = 1')
                    # 添加新获取的数据
                    station_sql = '''insert into `yjstationinfo`
                                                            (id, station_name, mac, ip, note, id_num, plc_count, ten_id, item_id)
                                                            values (%(id)s, %(station_name)s, %(mac)s, %(ip)s, %(note)s, %(id_num)s,
                                                            %(plc_count)s, %(ten_id)s, %(item_id)s)'''
                    cur.execute(station_sql, data['stations'])
                    plc_sql = '''insert into `yjplcinfo`(
                                                          id, station_id, plc_name, note, ip, mpi, type, plc_type, ten_id,
                                                           item_id, rack, slot, tcp_port) 
                                                          values (%(id)s, %(station_id)s, %(plc_name)s, %(note)s, %(ip)s, %(mpi)s, %(type)s,
                                                           %(plc_type)s, %(ten_id)s, %(item_id)s, %(rack)s, %(slot)s, %(tcp_port)s)'''
                    cur.executemany(plc_sql, data['plcs'])
                    group_sql = '''insert into `yjgroupinfo`(
                                                            id, group_name, note, upload_cycle, acquisition_cycle, server_record_cycle,
                                                             is_upload, ten_id, item_id, plc_id) 
                                                             values (%(id)s, %(group_name)s, %(note)s, %(upload_cycle)s,
                                                              %(acquisition_cycle)s, %(server_record_cycle)s, %(is_upload)s, %(ten_id)s,
                                                               %(item_id)s, %(plc_id)s)'''
                    cur.executemany(group_sql, data['groups'])
                    var_sql = '''insert into `yjvariableinfo`
                                 (id, variable_name, note, db_num, address, data_type, rw_type, ten_id, item_id,
                                  write_value, area, is_analog, analog_low_range, analog_high_range,
                                   digital_low_range, digital_high_range) 
                                   values (%(id)s, %(variable_name)s, %(note)s, %(db_num)s, %(address)s,
                                    %(data_type)s, %(rw_type)s, %(ten_id)s, %(item_id)s, %(write_value)s, %(area)s,
                                     %(is_analog)s, %(analog_low_range)s, %(analog_high_range)s,
                                      %(digital_low_range)s, %(digital_high_range)s)'''
                    cur.executemany(var_sql, data['variables'])
                    relation_sql = '''insert into `variables_groups`(id, variable_id, group_id) 
                                                              values (%(id)s, %(variable_id)s, %(group_id)s)'''
                    cur.executemany(relation_sql, data['variables_groups'])
                    alarm_sql = '''insert into `alarm_info`
                                   (id, variable_id, alarm_type, note, type, symbol, `limit`, delay) 
                                   values (%(id)s, %(variable_id)s, %(alarm_type)s, %(note)s, %(type)s, %(symbol)s,
                                    %(limit)s, %(delay)s)'''
                    cur.executemany(alarm_sql, data['alarm'])
                except Error as e:
                    logging.error('更新配置出错: ' + str(e))
                    db.rollback()
                    db_commit_err(id_num, 'get_config')
                else:
                    db.commit()
                finally:
                    cur.close()
                    time12 = time.time()
                    print('清空添加配置', time12 - time11)

            logging.debug('发送配置完成确认信息')
            time21 = time.time()
            result = server_confirm(CONFIRM_CONFIG_URL)
            time22 = time.time()
            print('确认配置获取', time22 - time21)

            if result:
                logging.info('配置获取完成')
            else:
                logging.error('无法向服务器确认获取配置已完成')

        else:
            server_return_err(id_num, 'get_config')

        gtime2 = time.time()
        print('get_config', gtime2 - gtime1)
Exemple #13
0
def check_alarm():
    # time1 = time.time()
    # r.set('alarm_info', None)
    logging.debug('check alarm')
    # print('检查报警')
    # redis_alarm_variables(r)

    is_no_alarm = r.get('is_no_alarm')
    if is_no_alarm:
        return
    alarm_variables = r.get('alarm_variables')
    # print('报警变量', alarm_variables)

    if not alarm_variables:
        redis_alarm_variables(r)
        return

    # 循环报警变量,查看最近采集的数值是否满足报警条件
    current_time = int(time.time())
    alarm_data = list()

    session = Session()
    try:
        # print(alarm_variables)
        for alarm in alarm_variables:
            # 获取需要判断的采集数据
            if alarm['delay']:
                values = session.query(Value).filter_by(var_id=alarm['var_id']). \
                    filter(Value.time > current_time - alarm['delay'] - 1).all()
            else:
                values = session.query(Value).filter_by(var_id=alarm['var_id']). \
                    order_by(Value.time.desc()).limit(1).all()
            # print(values[0].value)
            is_alarm = False
            if alarm['type'] == 1:
                for v in values:
                    # print(v.value, v.var_id)
                    if bool(v.value) == bool(alarm['limit']):
                        is_alarm = True
                    else:
                        is_alarm = False
                        break

            elif alarm['type'] == 2:
                if alarm['symbol'] == 1:
                    for v in values:
                        if v.value > alarm['limit']:
                            is_alarm = True
                        else:
                            is_alarm = False
                            break

                elif alarm['symbol'] == 2:
                    for v in values:
                        if v.value >= alarm['limit']:
                            is_alarm = True
                        else:
                            is_alarm = False
                            break

                elif alarm['symbol'] == 3:
                    for v in values:
                        if v.value < alarm['limit']:
                            is_alarm = True
                        else:
                            is_alarm = False
                            break

                elif alarm['symbol'] == 4:
                    for v in values:
                        if v.value <= alarm['limit']:
                            is_alarm = True
                        else:
                            is_alarm = False
                            break

                elif alarm['symbol'] == 5:
                    for v in values:
                        if v.value == alarm['limit']:
                            is_alarm = True
                        else:
                            is_alarm = False
                            break
                else:
                    is_alarm = False

            else:
                is_alarm = False

            if is_alarm and not alarm['is_alarming']:
                alarm_data.append({'i': alarm['var_id'], 'a': is_alarm})
                alarm['is_alarming'] = True
            elif not is_alarm and alarm['is_alarming']:
                alarm_data.append({'i': alarm['var_id'], 'a': is_alarm})
                alarm['is_alarming'] = False

        r.set('alarm_variables', alarm_variables)

        if alarm_data:
            alarm_info = {'time': current_time, 'data': alarm_data}
            old_alarm = r.get('alarm_info')
            # print(old_alarm)
            if old_alarm:
                old_alarm.append(alarm_info)
                r.set('alarm_info', old_alarm)
            else:
                r.set('alarm_info', [alarm_info])

                # print(alarm_info)
                # print(alarm_variables)
    # except Exception as e:
    #     logging.exception('check_alarm' + str(e))
    #     session.rollback()
    finally:
        session.close()
Exemple #14
0
def check_gather():
    """
    检查变量采集时间,采集满足条件的变量值

    :return:
    """
    # time.sleep(30)
    with ConnMySQL() as db:
        cur = db.cursor()
        try:
            # lock_time2 = time.time()
            # print('lock_time', lock_time2 - lock_time1)
            # time1 = time.time()
            logging.debug('检查变量采集时间')

            current_time = int(time.time())
            value_list = list()

            plcs = r.get('plc')

            group_read_data = r.get('group_read')

            for plc in plcs:
                # todo 循环内部 使用并发

                group_id = []
                for v in group_read_data:
                    if v['plc_id'] == plc[
                            'id'] and current_time >= v['read_time']:
                        group_id.append(v['id'])
                        v['read_time'] = current_time + v['read_cycle']
                r.set('group_read', group_read_data)

                group_data = r.get('variable')
                variables = [
                    variable for group in group_data
                    if group['group_id'] in group_id
                    for variable in group['variables']
                ]

                # print(variables)
                # print('采集数量', len(variables))

                with plc_client(plc['ip'], plc['rack'], plc['slot'],
                                plc['id']) as client:
                    if client.get_connected():
                        plc['time'] = current_time

                    if variables:

                        while len(variables) > 0:
                            variable_group = variables[:18]
                            variables = variables[18:]

                            # print(len(variables))
                            # print(plc)
                            try:
                                value_info = read_multi(
                                    plc=plc,
                                    variables=variable_group,
                                    current_time=current_time,
                                    client=client)
                            except Snap7ConnectException:
                                id_num = r.get('id_num')
                                connect_plc_err(id_num, plc['id'])
                            except Snap7ReadException as e:
                                id_num = r.get('id_num')
                                area, db_num, addr, data_type = e.args
                                read_err(id_num=id_num,
                                         plc_id=plc['id'],
                                         plc_name=plc['name'],
                                         area=area,
                                         db_num=db_num,
                                         address=addr,
                                         data_type=data_type)

                            else:
                                value_list += value_info

            # ctime1 = time.time()
            value_insert_sql = "insert into `values`(var_id, value, time) values "
            if value_list:
                v = map(str, value_list)

                value_insert_sql = value_insert_sql + ','.join(v)

                cur.execute(value_insert_sql)
                db.commit()

            # value_data = {str(current_time): value_list}
            # if redis_value:
            # else:
            #     r.set('value', value_data)

            # ctime2 = time.time()
            # print('commit', ctime2 - ctime1)

            r.set('plc', plcs)
        finally:
            # time2 = time.time()
            # print('采集时间' + str(time2 - time1))
            cur.close()
Exemple #15
0
def check_gather_redis(self):
    """
    检查变量采集时间,采集满足条件的变量值

    :return: 
    """

    lock_time2 = time.time()
    # print('lock_time', lock_time2 - lock_time1)
    time1 = time.time()
    logging.debug('检查变量采集时间')

    current_time = int(time.time())
    value_list = list()
    session = Session()

    plcs = r.get('plc')

    group_read_data = r.get('group_read')

    for plc in plcs:
        # todo 循环内部 使用并发

        group_id = []
        for v in group_read_data:
            if v['plc_id'] == plc['id'] and current_time >= v['read_time']:
                group_id.append(v['id'])
                v['read_time'] = current_time + v['read_cycle']
        r.set('group_read', group_read_data)

        group_data = r.get('variable')
        variables = [
            variable for group in group_data if group['group_id'] in group_id
            for variable in group['variables']
        ]

        # print(variables)
        # print('采集数量', len(variables))

        # client = plc_connect(plc)
        with plc_client(plc['ip'], plc['rack'], plc['slot'],
                        plc['id']) as client:
            if client.get_connected():
                plc['time'] = current_time

            if variables:

                # readsuan(variables)
                # variables = variables[0:2]
                # print('variables', len(variables))

                while len(variables) > 0:
                    variable_group = variables[:18]
                    variables = variables[18:]

                    # print(len(variables))
                    # print(plc)
                    try:
                        value_info = read_multi(plc=plc,
                                                variables=variable_group,
                                                current_time=current_time,
                                                client=client)
                    except Snap7ReadException as e:
                        id_num = r.get('id_num')
                        area, db_num, addr, data_type = e.args
                        read_err(id_num=id_num,
                                 plc_id=plc['id'],
                                 plc_name=plc['name'],
                                 area=area,
                                 db_num=db_num,
                                 address=addr,
                                 data_type=data_type)

                    else:
                        value_list += value_info

                        # except Exception:
                        #     print('跳过一次采集')

                        # client.disconnect()
                        # client.destroy()
    # session.bulk_insert_mappings(Value, value_list)
    # session.commit()
    ctime1 = time.time()
    # value_insert_sql = "insert into `values`(var_id, value, time) values "
    # if value_list:
    #     v = map(str, value_list)
    #
    #     value_insert_sql = value_insert_sql + ','.join(v)
    #
    #     cur.execute(value_insert_sql)
    #     db.commit()
    redis_value = r.conn.hlen('value')
    # print(redis_value)

    # value_data = {str(current_time): value_list}
    value_list = pickle.dumps(value_list)
    # if redis_value:
    r.conn.hset('value', str(current_time), value_list)
    # else:
    #     r.set('value', value_data)

    ctime2 = time.time()
    # print('commit', ctime2 - ctime1)

    r.set('plc', plcs)