plc_test_dry_run.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. PLC指令模拟测试工具
  5. 仅显示请求详情,不实际发送,用于调试和验证
  6. """
  7. import json
  8. import hashlib
  9. import time
  10. def load_config(config_file='config.json'):
  11. """加载配置文件"""
  12. with open(config_file, 'r', encoding='utf-8') as f:
  13. return json.load(f)
  14. def generate_md5_signature(record_data, secret, timestamp):
  15. """生成MD5签名"""
  16. cal_str = f"{record_data}{secret}{timestamp}"
  17. cal_md5 = hashlib.md5(cal_str.encode('utf-8')).hexdigest()
  18. return cal_md5.upper()
  19. def prepare_plc_request(device_name, item, old_value, new_value, command_type):
  20. """
  21. 准备PLC请求参数
  22. 参数:
  23. device_name: 设备名称
  24. item: 参数项名称
  25. old_value: 当前值
  26. new_value: 目标值
  27. command_type: 命令类型
  28. 返回:
  29. 请求信息字典
  30. """
  31. config = load_config()
  32. PLC_URL = config['api']['base_url'] + config['api']['plc_endpoint']
  33. PROJECT_ID = config['scada']['project_id']
  34. SCADA_SECRET = config['scada']['secret']
  35. timestamp = int(time.time())
  36. record_dict = {
  37. "project_id": PROJECT_ID,
  38. "item": item,
  39. "old_value": old_value,
  40. "new_value": new_value,
  41. "command_type": command_type
  42. }
  43. record_data = json.dumps(record_dict, separators=(',', ':'))
  44. signature = generate_md5_signature(record_data, SCADA_SECRET, timestamp)
  45. full_url = f"{PLC_URL}?sign={signature}&timestamp={timestamp}"
  46. payload = [record_dict]
  47. return {
  48. 'url': full_url,
  49. 'payload': payload,
  50. 'signature_data': record_data,
  51. 'signature': signature,
  52. 'timestamp': timestamp,
  53. 'secret': SCADA_SECRET
  54. }
  55. if __name__ == "__main__":
  56. print("=== PLC指令测试 - 模拟运行 ===")
  57. print()
  58. # 测试参数
  59. device_name = "UF2"
  60. item = "C.M.UF2_DB@time_production"
  61. old_value = "3800"
  62. new_value = "3801"
  63. command_type = 1
  64. # 准备请求
  65. request_info = prepare_plc_request(device_name, item, old_value, new_value, command_type)
  66. print(f"📋 测试场景:")
  67. print(f" 设备: {device_name}")
  68. print(f" 参数项: {item}")
  69. print(f" 当前值: {old_value}")
  70. print(f" 目标值: {new_value}")
  71. print(f" 命令类型: {command_type}")
  72. print()
  73. print(f"🔧 请求详情:")
  74. print(f" 完整URL: {request_info['url']}")
  75. print()
  76. print(f"📝 请求头:")
  77. print(f" Content-Type: application/json")
  78. print()
  79. print(f"📦 请求体:")
  80. print(json.dumps(request_info['payload'], indent=4, ensure_ascii=False))
  81. print()
  82. print(f"🔐 签名计算:")
  83. print(f" SCADA密钥: {request_info['secret']}")
  84. print(f" 时间戳: {request_info['timestamp']}")
  85. print(f" 签名原数据: {request_info['signature_data']}")
  86. print(f" 计算字符串: {request_info['signature_data']}{request_info['secret']}{request_info['timestamp']}")
  87. print(f" MD5签名: {request_info['signature']}")
  88. print()
  89. print(f"✨ curl命令:")
  90. curl_cmd = f"""curl -X POST '{request_info['url']}' \\
  91. -H 'Content-Type: application/json' \\
  92. -d '{json.dumps(request_info['payload'], separators=(',', ':'), ensure_ascii=False)}'"""
  93. print(curl_cmd)
  94. print()
  95. print("🚀 这就是将要发送给PLC系统的完整请求!")
  96. print(" 如果看起来正确,您可以运行 test_plc_update.py 来实际发送。")