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)
PLC三端分离 python
最新推荐文章于 2024-10-03 09:02:12 发布