test_callback.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. """
  2. send_decision_to_callback 函数测试脚本
  3. 测试功能:
  4. 1. 测试正常的决策数据发送
  5. 2. 测试不同参数组合
  6. 3. 模拟实际使用场景
  7. 4. 测试PLC指令下发(当use_model_status=1时)
  8. """
  9. import json
  10. from datetime import datetime
  11. from loop_main import send_decision_to_callback, send_plc_update, DATETIME_FORMAT, load_config, get_device_value
  12. def test_basic_callback():
  13. """
  14. 基础测试:发送一组标准的决策数据,如果use_model_status=1则测试PLC指令下发
  15. """
  16. print("=" * 60)
  17. print("测试1: 基础回调测试")
  18. print("=" * 60)
  19. # 模拟决策结果数据
  20. device_name = "UF1" # 设备名称
  21. test_data = {
  22. "type_name": device_name,
  23. "water_production_time": 4201, # 产水时间(秒)
  24. "physical_backwash": 120, # 物理反洗时间(秒)
  25. "ceb_backwash_frequency": 35, # CEB反洗频率
  26. "duration_system": 3800, # 系统运行时间(秒)
  27. "tmp_action": 0.045, # TMP动作值
  28. "recovery_rate": 0.95, # 回收率
  29. "ton_water_energy_kWh": 0.28, # 吨水电耗
  30. "max_permeability": 850.5, # 最高渗透率
  31. "daily_prod_time_h": 22.5, # 日均产水时间(小时)
  32. "ctime": datetime.now().strftime(DATETIME_FORMAT) # 当前时间
  33. }
  34. print("发送数据:")
  35. print(json.dumps(test_data, indent=2, ensure_ascii=False))
  36. print()
  37. # 调用函数
  38. try:
  39. use_model_status = send_decision_to_callback(**test_data)
  40. print(f"返回的 use_model 状态: {use_model_status}")
  41. if use_model_status == 1:
  42. print("测试结果: 成功 - 模型开关已开启")
  43. print()
  44. print("-" * 60)
  45. print("开始测试PLC指令下发")
  46. print("-" * 60)
  47. # 加载配置获取设备信息
  48. config = load_config()
  49. device_config = None
  50. for dev in config['devices']:
  51. if dev['name'] == device_name:
  52. device_config = dev
  53. break
  54. if device_config:
  55. # 先读取当前PLC的产水时间值
  56. print("正在读取PLC当前产水时间...")
  57. current_prod_time = get_device_value(device_config["production_time_payload"], device_name)
  58. if current_prod_time is not None:
  59. old_prod_time = str(int(current_prod_time))
  60. new_prod_time = str(int(current_prod_time) + 1) # 当前值+1
  61. prod_time_item = device_config["production_time_payload"]["deviceItems"]
  62. print(f"✓ 读取成功: 当前产水时间 = {old_prod_time}")
  63. print()
  64. print(f"测试参数:")
  65. print(f" 设备名称: {device_name}")
  66. print(f" 参数项: {prod_time_item}")
  67. print(f" 旧值: {old_prod_time} (从PLC读取)")
  68. print(f" 新值: {new_prod_time} (旧值+1)")
  69. print(f" 指令类型: 1 (产水时间)")
  70. print()
  71. # 发送PLC指令
  72. print("正在发送PLC指令...")
  73. plc_result = send_plc_update(
  74. device_name=device_name,
  75. item=prod_time_item,
  76. old_value=old_prod_time,
  77. new_value=new_prod_time,
  78. command_type=1 # 产水时间的指令类型
  79. )
  80. if plc_result:
  81. print("✓ PLC指令发送成功")
  82. else:
  83. print("✗ PLC指令发送失败")
  84. else:
  85. print("✗ 错误:无法读取当前产水时间,跳过PLC指令测试")
  86. else:
  87. print(f"⚠ 警告: 未找到设备 {device_name} 的配置")
  88. print("-" * 60)
  89. elif use_model_status == 0:
  90. print("测试结果: 成功 - 模型开关已关闭")
  91. print("跳过PLC指令测试")
  92. else:
  93. print("测试结果: 失败 - 未能获取 use_model 状态")
  94. except Exception as e:
  95. print(f"测试异常: {e}")
  96. import traceback
  97. traceback.print_exc()
  98. print("=" * 60)
  99. print()
  100. def test_minimal_callback():
  101. """
  102. 最小参数测试:只传递必要的参数
  103. """
  104. print("=" * 60)
  105. print("测试2: 最小参数测试")
  106. print("=" * 60)
  107. # 最小数据集
  108. test_data = {
  109. "type_name": "UF2",
  110. "water_production_time": 3500,
  111. "physical_backwash": 100,
  112. "ctime": datetime.now().strftime(DATETIME_FORMAT)
  113. }
  114. print("发送数据:")
  115. print(json.dumps(test_data, indent=2, ensure_ascii=False))
  116. print()
  117. try:
  118. use_model_status = send_decision_to_callback(**test_data)
  119. print(f"返回的 use_model 状态: {use_model_status}")
  120. if use_model_status == 1:
  121. print("测试结果: 成功 - 模型开关已开启")
  122. elif use_model_status == 0:
  123. print("测试结果: 成功 - 模型开关已关闭")
  124. else:
  125. print("测试结果: 失败 - 未能获取 use_model 状态")
  126. except Exception as e:
  127. print(f"测试异常: {e}")
  128. print("=" * 60)
  129. print()
  130. def test_multiple_devices():
  131. """
  132. 多设备测试:模拟多个设备的决策数据发送
  133. """
  134. print("=" * 60)
  135. print("测试3: 多设备测试")
  136. print("=" * 60)
  137. devices = ["UF1", "UF2", "UF3"]
  138. for device_name in devices:
  139. print(f"\n发送设备 {device_name} 的决策数据...")
  140. test_data = {
  141. "type_name": device_name,
  142. "water_production_time": 3600 + (devices.index(device_name) * 100),
  143. "physical_backwash": 100 + (devices.index(device_name) * 10),
  144. "ceb_backwash_frequency": 40 - devices.index(device_name),
  145. "duration_system": 3800,
  146. "tmp_action": 0.040 + (devices.index(device_name) * 0.005),
  147. "recovery_rate": 0.95,
  148. "ton_water_energy_kWh": 0.25 + (devices.index(device_name) * 0.02),
  149. "max_permeability": 850.0,
  150. "daily_prod_time_h": 22.0,
  151. "ctime": datetime.now().strftime(DATETIME_FORMAT)
  152. }
  153. try:
  154. use_model_status = send_decision_to_callback(**test_data)
  155. print(f"{device_name} 返回的 use_model 状态: {use_model_status}")
  156. if use_model_status == 1:
  157. print(f"{device_name} 测试结果: 成功 - 模型开关已开启")
  158. elif use_model_status == 0:
  159. print(f"{device_name} 测试结果: 成功 - 模型开关已关闭")
  160. else:
  161. print(f"{device_name} 测试结果: 失败 - 未能获取 use_model 状态")
  162. except Exception as e:
  163. print(f"{device_name} 测试异常: {e}")
  164. print("\n" + "=" * 60)
  165. print()
  166. def test_custom_scenario():
  167. """
  168. 自定义场景测试:可以根据需要修改参数
  169. """
  170. print("=" * 60)
  171. print("测试4: 自定义场景测试")
  172. print("=" * 60)
  173. # 这里可以自定义测试参数
  174. test_data = {
  175. "type_name": "UF1", # 修改设备名称
  176. "water_production_time": 4000, # 修改产水时间
  177. "physical_backwash": 150, # 修改反洗时间
  178. "ceb_backwash_frequency": 30, # 修改CEB频率
  179. "duration_system": 4200,
  180. "tmp_action": 0.055,
  181. "recovery_rate": 0.92,
  182. "ton_water_energy_kWh": 0.30,
  183. "max_permeability": 800.0,
  184. "daily_prod_time_h": 21.5,
  185. "ctime": datetime.now().strftime(DATETIME_FORMAT)
  186. }
  187. print("自定义测试数据:")
  188. print(json.dumps(test_data, indent=2, ensure_ascii=False))
  189. print()
  190. try:
  191. use_model_status = send_decision_to_callback(**test_data)
  192. print(f"返回的 use_model 状态: {use_model_status}")
  193. if use_model_status == 1:
  194. print("测试结果: 成功 - 模型开关已开启")
  195. elif use_model_status == 0:
  196. print("测试结果: 成功 - 模型开关已关闭")
  197. else:
  198. print("测试结果: 失败 - 未能获取 use_model 状态")
  199. except Exception as e:
  200. print(f"测试异常: {e}")
  201. print("=" * 60)
  202. print()
  203. def test_plc_update_with_callback():
  204. """
  205. 测试5: 回调+PLC指令测试(完整流程)
  206. """
  207. print("=" * 60)
  208. print("测试5: 回调+PLC指令完整流程测试")
  209. print("=" * 60)
  210. device_name = "UF1"
  211. # 第一步:发送回调数据
  212. test_data = {
  213. "type_name": device_name,
  214. "water_production_time": 4201, # 决策建议的产水时间
  215. "physical_backwash": 120,
  216. "ceb_backwash_frequency": 35,
  217. "duration_system": 3800,
  218. "tmp_action": 0.045,
  219. "recovery_rate": 0.95,
  220. "ton_water_energy_kWh": 0.28,
  221. "max_permeability": 850.5,
  222. "daily_prod_time_h": 22.5,
  223. "ctime": datetime.now().strftime(DATETIME_FORMAT)
  224. }
  225. print("步骤1: 发送决策数据到回调接口")
  226. print("=" * 60)
  227. print(json.dumps(test_data, indent=2, ensure_ascii=False))
  228. print()
  229. try:
  230. # use_model_status = 1
  231. use_model_status = send_decision_to_callback(**test_data)
  232. print(f"✓ 回调响应: use_model_status = {use_model_status}")
  233. print()
  234. # 第二步:根据返回状态决定是否发送PLC指令
  235. print("步骤2: 根据use_model_status决定是否下发PLC指令")
  236. print("=" * 60)
  237. if use_model_status == 1:
  238. print("✓ 模型开关已开启,准备下发PLC指令")
  239. print()
  240. # 加载配置
  241. config = load_config()
  242. device_config = None
  243. for dev in config['devices']:
  244. if dev['name'] == device_name:
  245. device_config = dev
  246. break
  247. if device_config:
  248. print("步骤3: 读取PLC当前产水时间")
  249. print("=" * 60)
  250. # 先读取当前PLC的产水时间值
  251. current_prod_time = get_device_value(device_config["production_time_payload"], device_name)
  252. if current_prod_time is not None:
  253. old_prod_time = str(int(current_prod_time))
  254. new_prod_time = str(int(current_prod_time) - 1) # 当前值+1
  255. prod_time_item = device_config["production_time_payload"]["deviceItems"]
  256. print(f"✓ 读取成功: 当前产水时间 = {old_prod_time} 秒")
  257. print()
  258. print("步骤4: 下发PLC指令(修改产水时间)")
  259. print("=" * 60)
  260. print(f"设备: {device_name}")
  261. print(f"参数: {prod_time_item}")
  262. print(f"变更: {old_prod_time} -> {new_prod_time} (当前值+1)")
  263. print(f"类型: command_type=1 (产水时间)")
  264. print()
  265. # 发送PLC指令
  266. plc_result = send_plc_update(
  267. device_name=device_name,
  268. item=prod_time_item,
  269. old_value=old_prod_time,
  270. new_value=new_prod_time,
  271. command_type=1
  272. )
  273. print()
  274. if plc_result:
  275. print("✓✓✓ 测试成功:完整流程执行完毕")
  276. print(" 1. 回调接口调用成功")
  277. print(" 2. use_model_status=1")
  278. print(" 3. 从PLC读取当前值成功")
  279. print(" 4. PLC指令发送成功")
  280. else:
  281. print("✗ 测试失败:PLC指令发送失败")
  282. else:
  283. print("✗ 错误:无法读取当前产水时间")
  284. print("测试失败:无法获取PLC当前值")
  285. else:
  286. print(f"✗ 错误:未找到设备 {device_name} 的配置")
  287. elif use_model_status == 0:
  288. print("⚠ 模型开关已关闭,跳过PLC指令下发")
  289. print(" 这是正常行为(use_model_status=0)")
  290. else:
  291. print("✗ 测试失败:未能获取有效的 use_model_status")
  292. except Exception as e:
  293. print(f"✗ 测试异常: {e}")
  294. import traceback
  295. traceback.print_exc()
  296. print()
  297. print("=" * 60)
  298. print()
  299. def main():
  300. """
  301. 主测试函数
  302. """
  303. print("\n")
  304. print("*" * 60)
  305. print("send_decision_to_callback + PLC指令 测试")
  306. print("*" * 60)
  307. print()
  308. # 运行各个测试
  309. # 默认运行基础回调测试(包含PLC指令测试)
  310. # test_basic_callback()
  311. # 取消注释下面的行来运行其他测试
  312. # test_minimal_callback()
  313. # test_multiple_devices()
  314. # test_custom_scenario()
  315. # 完整流程测试(推荐使用)
  316. test_plc_update_with_callback()
  317. print("\n")
  318. print("*" * 60)
  319. print("测试完成")
  320. print("*" * 60)
  321. print()
  322. print("提示:")
  323. print(" - 如果 use_model_status=1,会自动发送PLC指令")
  324. print(" - 测试会先从PLC读取当前产水时间,然后修改为当前值+1")
  325. print(" - 这样确保old_value与PLC实际值匹配,避免'设置scada变量失败'错误")
  326. print(" - 可以运行 test_plc_update_with_callback() 查看完整流程")
  327. print()
  328. if __name__ == "__main__":
  329. main()