gateway_api.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. from __future__ import annotations
  2. from typing import Any
  3. from .auth import find_project_config
  4. from .http_client import request_json
  5. from .protocols import BACNET_SPEC, MODBUS_SPEC, S7_SPEC
  6. from .protocols.bacnet import normalize_bacnet_object_type
  7. def _request_gateway(project_key: str, path: str | None, payload: dict[str, Any], protocol: str) -> dict[str, Any]:
  8. project = find_project_config(project_key)
  9. if not path:
  10. raise ValueError(f"{protocol} gateway path is not configured")
  11. response_payload = request_json(
  12. "POST",
  13. f"{project['base_url']}{path}",
  14. json_payload=payload,
  15. )
  16. if not isinstance(response_payload, dict):
  17. raise ValueError(f"gateway API returned invalid payload: {response_payload}")
  18. return response_payload
  19. def modbus_point_collect_test(
  20. project_key: str,
  21. *,
  22. ip: str,
  23. port: int,
  24. slave_id: int,
  25. points: list[dict[str, Any]],
  26. device_type: str = "ModbusTCP",
  27. word_byte_order: str = "ABCD",
  28. address_base: int = 0,
  29. ) -> dict[str, Any]:
  30. payload = {
  31. "device_type": device_type,
  32. "ip": ip,
  33. "port": port,
  34. "word_byte_order": word_byte_order,
  35. "address_base": address_base,
  36. "slave_id": slave_id,
  37. "points": points,
  38. }
  39. return _request_gateway(project_key, MODBUS_SPEC.point_test_path, payload, "modbus point test")
  40. def bacnet_point_collect_test(
  41. project_key: str,
  42. *,
  43. ip: str,
  44. bacnet_device_id: int,
  45. points: list[dict[str, Any]],
  46. port: int = 47808,
  47. ) -> dict[str, Any]:
  48. normalized_points = []
  49. for point in points:
  50. normalized_point = dict(point)
  51. normalized_point["object_type"] = normalize_bacnet_object_type(normalized_point.get("object_type"))
  52. normalized_points.append(normalized_point)
  53. payload = {
  54. "ip": ip,
  55. "bacnet_device_id": bacnet_device_id,
  56. "port": port,
  57. "points": normalized_points,
  58. }
  59. return _request_gateway(project_key, BACNET_SPEC.point_test_path, payload, "bacnet point test")
  60. def bacnet_point_search(
  61. project_key: str,
  62. *,
  63. ip: str,
  64. bacnet_device_id: int,
  65. port: int = 47808,
  66. ) -> dict[str, Any]:
  67. payload = {
  68. "ip": ip,
  69. "bacnet_device_id": bacnet_device_id,
  70. "port": port,
  71. }
  72. return _request_gateway(project_key, BACNET_SPEC.search_points_path, payload, "bacnet point search")
  73. def s7_raw_read(
  74. project_key: str,
  75. *,
  76. ip: str,
  77. rock: int,
  78. slot: int,
  79. read: dict[str, Any],
  80. device_type: str = "S7-1200",
  81. port: int = 102,
  82. tsap_conn_type: str | None = None,
  83. ) -> dict[str, Any]:
  84. payload = {
  85. "device_type": device_type,
  86. "ip": ip,
  87. "port": port,
  88. "rock": rock,
  89. "slot": slot,
  90. "tsap_conn_type": _resolve_s7_tsap_conn_type(device_type, tsap_conn_type),
  91. "read": read,
  92. }
  93. return _request_gateway(project_key, S7_SPEC.raw_read_path, payload, "s7 raw read")
  94. def s7_point_collect_test(
  95. project_key: str,
  96. *,
  97. ip: str,
  98. rock: int,
  99. slot: int,
  100. points: list[dict[str, Any]],
  101. device_type: str = "S7-1200",
  102. port: int = 102,
  103. tsap_conn_type: str | None = None,
  104. ) -> dict[str, Any]:
  105. payload = {
  106. "device_type": device_type,
  107. "ip": ip,
  108. "port": port,
  109. "rock": rock,
  110. "slot": slot,
  111. "tsap_conn_type": _resolve_s7_tsap_conn_type(device_type, tsap_conn_type),
  112. "points": points,
  113. }
  114. return _request_gateway(project_key, S7_SPEC.point_test_path, payload, "s7 point test")
  115. def s7_connect_scan(project_key: str, *, ip: str) -> dict[str, Any]:
  116. return _request_gateway(project_key, S7_SPEC.connect_scan_path, {"ip": ip}, "s7 connect scan")
  117. def _resolve_s7_tsap_conn_type(device_type: str, tsap_conn_type: str | None) -> str:
  118. normalized_tsap = str(tsap_conn_type or "").strip().upper()
  119. if normalized_tsap:
  120. return normalized_tsap
  121. return "PG"