PLC三端分离 python

from copy import deepcopy
from datetime import datetime
import threading
import time
from typing import Tuple, List, Dict, Any

import requests
import snap7
from snap7 import util

# 后端地址
backend_url = 'http://' + 'localhost:8080'
# 获取设备ip 路径
listEquipmentIp_path = '/listEquipmentIp'
# 发送component 举例
send_component_path = '/sendComponent'

# 读取间隔
read_sleep = 1

# 设备属性模板
component_list_template = [
    {
        'name': 's1',
        'db_number': 0,
        'start': 0,
        'size': 0,
        'ctype': '',
        'index': (1,),
        'send_mnp': (None, 'true')  # 是否需要发送操作给后端,在值为多少的时候发送
    }
]

# 内存解析器
read_parser = {
    'bool': util.get_bool,
    'int': util.get_int,
    'str': util.get_string,
    'real': util.get_real
}

# 全局plc管理
global_plc_info = []

class Component:
    def __init__(self, name, db_number, start, size, ctype, index: Tuple[int, int], send_mnp: Tuple[str, str]):
        self.name = name
        self.db_number = db_number
        self.start = start
        self.size = size
        self.ctype = ctype
        self.index = index
        self.last_value = ''
        self.send_mnp = send_mnp  # ('操作名,若为None则没有相关操作', '可执行操作的值,若为None则任何值都发送')

    def __init__(self, temp: Dict[str, Any]):
        for k, v in temp.items():
            self.__setattr__(k, v)


class Equipment:
    def __init__(self, ip, component_list):
        self.ip = ip
        self.component_list: List[Component] = component_list
        self.link_status = False
        self.linked_plc = None


def get_plc_ip():
    url = backend_url + listEquipmentIp_path
    response = requests.get(url)
    return response.json()


def set_global():
    plc_ip_list = get_plc_ip()
    for plc_ip in plc_ip_list:
        component_list = [Component(temp) for temp in component_list_template]
        global_plc_info.append(Equipment(plc_ip, component_list))


def run_acq():
    for plc in global_plc_info:
        threading.Thread(target=_acq_one_device, args=(plc,)).start()


def start():
    set_global()
    run_acq()


# 维护设备所有信息的全局变量
global_plc_info_list = []


def need_time():
    time.sleep(10)


def _db_read(equipment, component, now):
    try:
        data = equipment.linked_plc.db_read(component.db_number, component.start, component.size)
        # 解析数据
        value = read_parser[component.ctype](data, *component.index)
        if component.last_value != value:
            component.last_value = value

            threading.Thread(target=_send_component, args=(equipment, component, now)).start()
            if component.send_mnp[0] and (
                    (component.send_mnp[1] is None) or (component.last_value == component.send_mnp[1])):
                # TODO 向后端发送操作指令
                pass
    except Exception as e:
        print(e)
        equipment.link_status = False


def _send_component(equipment, component, now):
    url = backend_url + send_component_path
    payload = {
        'equipmentIp': equipment.ip,
        'cmpName': component.name,
        'value': component.last_value,
        'time': now.strftime('%Y-%m-%dT%H:%M:%S')
    }
    # 发送给后端
    threading.Thread(target=_send, args=(url, payload)).start()


def _send(url, payload):
    response = requests.post(url, payload)
    print(response)


def _acq_one_device(equipment: Equipment):
    # 连接设备
    def link():
        plc = snap7.client.Client()
        plc.connect(equipment.ip, 0, 2)
        equipment.link_status = True
        return plc

    if not equipment.link_status:
        equipment.linked_plc = link()

    while True:
        # 获取当前时间
        now = datetime.now()
        # 多线程读值
        thread_list = []
        for component in equipment.component_list:
            t = threading.Thread(target=_db_read, args=(equipment, component, now))
            thread_list.append(t)
            t.start()
        for th in thread_list:
            th.join()
        # 延时
        time.sleep(read_sleep)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值