gateway_api.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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] | None, 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 bacnet_bbmd_whois(project_key: str) -> dict[str, Any]:
  74. return _request_gateway(project_key, BACNET_SPEC.bbmd_whois_path, None, "bacnet bbmd whois")
  75. def s7_raw_read(
  76. project_key: str,
  77. *,
  78. ip: str,
  79. rock: int,
  80. slot: int,
  81. read: dict[str, Any],
  82. device_type: str = "S7-1200",
  83. port: int = 102,
  84. tsap_conn_type: str | None = None,
  85. ) -> dict[str, Any]:
  86. payload = {
  87. "device_type": device_type,
  88. "ip": ip,
  89. "port": port,
  90. "rock": rock,
  91. "slot": slot,
  92. "tsap_conn_type": _resolve_s7_tsap_conn_type(device_type, tsap_conn_type),
  93. "read": read,
  94. }
  95. return _request_gateway(project_key, S7_SPEC.raw_read_path, payload, "s7 raw read")
  96. def s7_point_collect_test(
  97. project_key: str,
  98. *,
  99. ip: str,
  100. rock: int,
  101. slot: int,
  102. points: list[dict[str, Any]],
  103. device_type: str = "S7-1200",
  104. port: int = 102,
  105. tsap_conn_type: str | None = None,
  106. ) -> dict[str, Any]:
  107. payload = {
  108. "device_type": device_type,
  109. "ip": ip,
  110. "port": port,
  111. "rock": rock,
  112. "slot": slot,
  113. "tsap_conn_type": _resolve_s7_tsap_conn_type(device_type, tsap_conn_type),
  114. "points": points,
  115. }
  116. return _request_gateway(project_key, S7_SPEC.point_test_path, payload, "s7 point test")
  117. def s7_connect_scan(project_key: str, *, ip: str) -> dict[str, Any]:
  118. return _request_gateway(project_key, S7_SPEC.connect_scan_path, {"ip": ip}, "s7 connect scan")
  119. def _resolve_s7_tsap_conn_type(device_type: str, tsap_conn_type: str | None) -> str:
  120. normalized_tsap = str(tsap_conn_type or "").strip().upper()
  121. if normalized_tsap:
  122. return normalized_tsap
  123. return "PG"