s7data.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import snap7, csv, threading, warnings, time
  2. from utils.statepoint import *
  3. S7Client = snap7.client.Client
  4. class S7data:
  5. def __init__(self, csvfile):
  6. self.logger = None
  7. self.S7Client = None
  8. self.lock = threading.Lock()
  9. self.thread_run = False
  10. self.threads = []
  11. self.nodes = {}
  12. self.node_data = {}
  13. self.target_from_name = {}
  14. with open(csvfile) as f:
  15. for i in csv.DictReader(f):
  16. if i['name'] in self.nodes:
  17. raise Exception(f"S7配置文件节点名称重复:{i['name']}")
  18. else:
  19. self.nodes[i['name']] = i
  20. self.node_data[i['name']] = bytearray(int(i['size']))
  21. def set_logger(self, logger):
  22. self.logger = logger
  23. def set_S7Client(self, s7c):
  24. self.S7Client = s7c
  25. def get_S7Client(self):
  26. return self.S7Client
  27. def send(self, name):
  28. if self.nodes[name]['type'] == 'int':
  29. data = snap7.util.get_int(self.node_data[name], 0)
  30. elif self.nodes[name]['type'] == 'dint':
  31. data = snap7.util.get_dint(self.node_data[name], 0)
  32. elif self.nodes[name]['type'] == 'bool':
  33. data = snap7.util.get_bool(self.node_data[name], 0, int(self.nodes[name]['offset']))
  34. elif self.nodes[name]['type'] == 'boollist':
  35. data = [(self.node_data[name][0] >> i) & 1 for i in range(8)]
  36. elif self.nodes[name]['type'] == 'real':
  37. data = snap7.util.get_real(self.node_data[name], 0)
  38. elif self.nodes[name]['type'] == 'string':
  39. data = self.node_data[name][2:2+int.from_bytes(self.node_data[name][1:2])].decode('gbk')
  40. elif self.nodes[name]['type'] == 'wstring':
  41. data = self.node_data[name][4:].decode(encoding='utf-16be')
  42. else:
  43. warnings.warn('暂不支持的类型:' + self.nodes[name]['type'])
  44. if self.logger:
  45. self.logger.error('暂不支持的类型:' + self.nodes[name]['type'])
  46. return None
  47. if name in self.target_from_name:
  48. for i in self.target_from_name[name]:
  49. i.inject(data)
  50. if self.nodes[name]['type'] == 'boollist' and name + '*' in self.target_from_name:
  51. for i in range(8):
  52. for j in self.target_from_name[name+'*'][i]:
  53. j.inject(data[i])
  54. def update(self, name):
  55. nodeinfo = self.nodes[name]
  56. try:
  57. while True:
  58. if not self.thread_run:
  59. return None
  60. self.lock.acquire()
  61. if not self.S7Client.get_connected():
  62. warnings.warn('S7Client连接中断')
  63. if self.logger:
  64. self.logger.error('S7Client连接中断')
  65. self.thread_run = False
  66. self.lock.release()
  67. return None
  68. tmp = self.S7Client.db_read(int(nodeinfo['db']), int(nodeinfo['start']), int(nodeinfo['size']))
  69. self.lock.release()
  70. if self.node_data[name] != tmp:
  71. self.node_data[name] = tmp
  72. self.send(name)
  73. time.sleep(float(nodeinfo['frequency']) / 1000)
  74. except RuntimeError as reason:
  75. warnings.warn(reason)
  76. if self.logger:
  77. self.logger.error(reason)
  78. self.thread_run = False
  79. self.lock.release()
  80. def start_auto_update(self):
  81. if self.thread_run:
  82. return None
  83. self.threads = []
  84. if self.S7Client == None:
  85. warnings.warn('未初始化S7Client')
  86. if self.logger:
  87. self.logger.error('未初始化S7Client')
  88. return None
  89. if not self.S7Client.get_connected():
  90. warnings.warn('S7Client未连接')
  91. if self.logger:
  92. self.logger.error('S7Client未连接')
  93. return None
  94. for key, value in self.nodes.items():
  95. if value['read_allow'].upper() != 'FALSE':
  96. self.threads.append(threading.Thread(target=self.update, args=(value['name'],)))
  97. self.thread_run = True
  98. for i in self.threads:
  99. i.start()
  100. def end_auto_update(self):
  101. self.thread_run = False
  102. for i in self.threads:
  103. i.join()
  104. def make_point(self, name):
  105. index = -1
  106. solvedname = name
  107. if len(name) > 3 and name[-3] == '[' and name[-1] == ']' and name[-2].isdigit() and 0 <= int(name[-2]) < 8:
  108. index = int(name[-2])
  109. name = name[:-3]
  110. solvedname = name + '*'
  111. if name not in self.nodes:
  112. raise ValueError("创建了未配置的点")
  113. if solvedname not in self.target_from_name:
  114. if index == -1:
  115. self.target_from_name[solvedname] = []
  116. else:
  117. self.target_from_name[solvedname] = [[],[],[],[],[],[],[],[]]
  118. res = Statepoint()
  119. if index == -1:
  120. self.target_from_name[solvedname].append(res)
  121. else:
  122. self.target_from_name[solvedname][index].append(res)
  123. return res