gateway_api.py 3.7 KB

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