isar 1.10.14__tar.gz → 1.12.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of isar might be problematic. Click here for more details.

Files changed (207) hide show
  1. {isar-1.10.14 → isar-1.12.0}/.dockerignore +0 -0
  2. {isar-1.10.14 → isar-1.12.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  3. {isar-1.10.14 → isar-1.12.0}/.github/ISSUE_TEMPLATE/feature.md +0 -0
  4. {isar-1.10.14 → isar-1.12.0}/.github/ISSUE_TEMPLATE/improvement.md +0 -0
  5. {isar-1.10.14 → isar-1.12.0}/.github/release.yml +0 -0
  6. {isar-1.10.14 → isar-1.12.0}/.github/workflows/project_automations.yml +0 -0
  7. {isar-1.10.14 → isar-1.12.0}/.github/workflows/publish_isar_base_image.yml +0 -0
  8. {isar-1.10.14 → isar-1.12.0}/.github/workflows/pythonpackage.yml +2 -2
  9. {isar-1.10.14 → isar-1.12.0}/.github/workflows/pythonpublish.yml +0 -0
  10. {isar-1.10.14 → isar-1.12.0}/.github/workflows/repository_dispatch_on_merge.yml +0 -0
  11. {isar-1.10.14 → isar-1.12.0}/.github/workflows/stale.yml +0 -0
  12. {isar-1.10.14 → isar-1.12.0}/.gitignore +0 -0
  13. {isar-1.10.14 → isar-1.12.0}/.pre-commit-config.yaml +0 -0
  14. {isar-1.10.14 → isar-1.12.0}/Dockerfile +0 -0
  15. {isar-1.10.14 → isar-1.12.0}/LICENSE +0 -0
  16. {isar-1.10.14 → isar-1.12.0}/PKG-INFO +1 -1
  17. {isar-1.10.14 → isar-1.12.0}/README.md +0 -0
  18. {isar-1.10.14 → isar-1.12.0}/docker-compose-turtlebot.yml +0 -0
  19. {isar-1.10.14 → isar-1.12.0}/docker-compose.yml +0 -0
  20. {isar-1.10.14 → isar-1.12.0}/docs/Makefile +0 -0
  21. {isar-1.10.14 → isar-1.12.0}/docs/make.bat +0 -0
  22. {isar-1.10.14 → isar-1.12.0}/docs/rst_processing.py +0 -1
  23. {isar-1.10.14 → isar-1.12.0}/docs/source/conf.py +0 -0
  24. {isar-1.10.14 → isar-1.12.0}/docs/source/index.rst +0 -0
  25. {isar-1.10.14 → isar-1.12.0}/docs/source/readme_link.md +0 -0
  26. {isar-1.10.14 → isar-1.12.0}/docs/state_machine_diagram.png +0 -0
  27. {isar-1.10.14 → isar-1.12.0}/main.py +35 -8
  28. {isar-1.10.14 → isar-1.12.0}/pyproject.toml +0 -0
  29. {isar-1.10.14 → isar-1.12.0}/radixconfig.yml +0 -0
  30. {isar-1.10.14 → isar-1.12.0}/setup.cfg +0 -0
  31. {isar-1.10.14 → isar-1.12.0}/setup.py +3 -0
  32. {isar-1.10.14 → isar-1.12.0}/src/isar/__init__.py +0 -0
  33. {isar-1.10.14 → isar-1.12.0}/src/isar/apis/__init__.py +0 -0
  34. {isar-1.10.14 → isar-1.12.0}/src/isar/apis/api.py +54 -4
  35. {isar-1.10.14 → isar-1.12.0}/src/isar/apis/models/__init__.py +0 -0
  36. {isar-1.10.14 → isar-1.12.0}/src/isar/apis/models/models.py +0 -0
  37. {isar-1.10.14 → isar-1.12.0}/src/isar/apis/models/start_mission_definition.py +44 -35
  38. {isar-1.10.14 → isar-1.12.0}/src/isar/apis/schedule/__init__.py +0 -0
  39. {isar-1.10.14 → isar-1.12.0}/src/isar/apis/schedule/scheduling_controller.py +0 -0
  40. {isar-1.10.14 → isar-1.12.0}/src/isar/apis/security/__init__.py +0 -0
  41. {isar-1.10.14 → isar-1.12.0}/src/isar/apis/security/authentication.py +4 -5
  42. {isar-1.10.14 → isar-1.12.0}/src/isar/config/__init__.py +0 -0
  43. {isar-1.10.14 → isar-1.12.0}/src/isar/config/certs/ca-cert.pem +0 -0
  44. {isar-1.10.14 → isar-1.12.0}/src/isar/config/configuration_error.py +0 -0
  45. {isar-1.10.14 → isar-1.12.0}/src/isar/config/keyvault/__init__.py +0 -0
  46. {isar-1.10.14 → isar-1.12.0}/src/isar/config/keyvault/keyvault_error.py +0 -0
  47. isar-1.12.0/src/isar/config/keyvault/keyvault_service.py +88 -0
  48. isar-1.12.0/src/isar/config/log.py +61 -0
  49. {isar-1.10.14 → isar-1.12.0}/src/isar/config/logging.conf +0 -0
  50. {isar-1.10.14 → isar-1.12.0}/src/isar/config/maps/JSP1_intermediate_deck.json +0 -0
  51. {isar-1.10.14 → isar-1.12.0}/src/isar/config/maps/JSP1_weather_deck.json +0 -0
  52. {isar-1.10.14 → isar-1.12.0}/src/isar/config/maps/default_map.json +0 -0
  53. {isar-1.10.14 → isar-1.12.0}/src/isar/config/maps/klab_b.json +0 -0
  54. {isar-1.10.14 → isar-1.12.0}/src/isar/config/maps/klab_compressor.json +0 -0
  55. {isar-1.10.14 → isar-1.12.0}/src/isar/config/maps/klab_turtlebot.json +0 -0
  56. {isar-1.10.14 → isar-1.12.0}/src/isar/config/maps/turtleworld.json +0 -0
  57. {isar-1.10.14/src/isar/config/predefined_missions → isar-1.12.0/src/isar/config/predefined_mission_definition}/__init__.py +0 -0
  58. isar-1.12.0/src/isar/config/predefined_mission_definition/default_mission.json +98 -0
  59. isar-1.12.0/src/isar/config/predefined_mission_definition/default_turtlebot.json +136 -0
  60. {isar-1.10.14/src/isar/config/predefined_poses → isar-1.12.0/src/isar/config/predefined_missions}/__init__.py +0 -0
  61. isar-1.12.0/src/isar/config/predefined_missions/default.json +92 -0
  62. {isar-1.10.14 → isar-1.12.0}/src/isar/config/predefined_missions/default_turtlebot.json +0 -0
  63. {isar-1.10.14/src/isar/mission_planner → isar-1.12.0/src/isar/config/predefined_poses}/__init__.py +0 -0
  64. {isar-1.10.14 → isar-1.12.0}/src/isar/config/predefined_poses/predefined_poses.py +0 -0
  65. {isar-1.10.14 → isar-1.12.0}/src/isar/config/settings.env +5 -0
  66. {isar-1.10.14 → isar-1.12.0}/src/isar/config/settings.py +51 -10
  67. {isar-1.10.14/src/isar/models → isar-1.12.0/src/isar/mission_planner}/__init__.py +0 -0
  68. {isar-1.10.14 → isar-1.12.0}/src/isar/mission_planner/echo_planner.py +1 -1
  69. {isar-1.10.14 → isar-1.12.0}/src/isar/mission_planner/local_planner.py +0 -0
  70. {isar-1.10.14 → isar-1.12.0}/src/isar/mission_planner/mission_planner_interface.py +0 -0
  71. {isar-1.10.14 → isar-1.12.0}/src/isar/mission_planner/sequential_task_selector.py +0 -0
  72. {isar-1.10.14 → isar-1.12.0}/src/isar/mission_planner/task_selector_interface.py +0 -0
  73. {isar-1.10.14/src/isar/models/communication → isar-1.12.0/src/isar/models}/__init__.py +0 -0
  74. {isar-1.10.14/src/isar/models/mission_metadata → isar-1.12.0/src/isar/models/communication}/__init__.py +0 -0
  75. {isar-1.10.14 → isar-1.12.0}/src/isar/models/communication/message.py +0 -0
  76. {isar-1.10.14 → isar-1.12.0}/src/isar/models/communication/queues/__init__.py +0 -0
  77. {isar-1.10.14 → isar-1.12.0}/src/isar/models/communication/queues/queue_io.py +0 -0
  78. {isar-1.10.14 → isar-1.12.0}/src/isar/models/communication/queues/queue_timeout_error.py +0 -0
  79. {isar-1.10.14 → isar-1.12.0}/src/isar/models/communication/queues/queues.py +1 -1
  80. {isar-1.10.14 → isar-1.12.0}/src/isar/models/communication/queues/status_queue.py +0 -0
  81. {isar-1.10.14 → isar-1.12.0}/src/isar/models/mission/__init__.py +0 -0
  82. {isar-1.10.14 → isar-1.12.0}/src/isar/models/mission/mission.py +0 -0
  83. {isar-1.10.14 → isar-1.12.0}/src/isar/models/mission/status.py +5 -5
  84. {isar-1.10.14/src/isar/services → isar-1.12.0/src/isar/models/mission_metadata}/__init__.py +0 -0
  85. {isar-1.10.14 → isar-1.12.0}/src/isar/models/mission_metadata/mission_metadata.py +2 -0
  86. {isar-1.10.14 → isar-1.12.0}/src/isar/modules.py +3 -2
  87. {isar-1.10.14/src/isar/services/auth → isar-1.12.0/src/isar/services}/__init__.py +0 -0
  88. {isar-1.10.14/src/isar/services/readers → isar-1.12.0/src/isar/services/auth}/__init__.py +0 -0
  89. {isar-1.10.14 → isar-1.12.0}/src/isar/services/auth/azure_credentials.py +0 -0
  90. {isar-1.10.14/src/isar/services/service_connections → isar-1.12.0/src/isar/services/readers}/__init__.py +0 -0
  91. {isar-1.10.14 → isar-1.12.0}/src/isar/services/readers/base_reader.py +0 -0
  92. {isar-1.10.14/src/isar/services/service_connections/mqtt → isar-1.12.0/src/isar/services/service_connections}/__init__.py +0 -0
  93. {isar-1.10.14/src/isar/services/service_connections/stid → isar-1.12.0/src/isar/services/service_connections/mqtt}/__init__.py +0 -0
  94. {isar-1.10.14 → isar-1.12.0}/src/isar/services/service_connections/mqtt/mqtt_client.py +0 -18
  95. isar-1.12.0/src/isar/services/service_connections/mqtt/robot_info_publisher.py +33 -0
  96. isar-1.12.0/src/isar/services/service_connections/mqtt/robot_status_publisher.py +66 -0
  97. {isar-1.10.14 → isar-1.12.0}/src/isar/services/service_connections/request_handler.py +1 -1
  98. {isar-1.10.14/src/isar/services/utilities → isar-1.12.0/src/isar/services/service_connections/stid}/__init__.py +0 -0
  99. {isar-1.10.14 → isar-1.12.0}/src/isar/services/service_connections/stid/stid_service.py +0 -0
  100. {isar-1.10.14/src/isar/state_machine → isar-1.12.0/src/isar/services/utilities}/__init__.py +0 -0
  101. {isar-1.10.14 → isar-1.12.0}/src/isar/services/utilities/queue_utilities.py +0 -0
  102. {isar-1.10.14 → isar-1.12.0}/src/isar/services/utilities/scheduling_utilities.py +5 -5
  103. {isar-1.10.14 → isar-1.12.0}/src/isar/services/utilities/threaded_request.py +3 -3
  104. {isar-1.10.14/src/isar/storage → isar-1.12.0/src/isar/state_machine}/__init__.py +0 -0
  105. {isar-1.10.14 → isar-1.12.0}/src/isar/state_machine/state_machine.py +13 -5
  106. {isar-1.10.14 → isar-1.12.0}/src/isar/state_machine/states/__init__.py +0 -0
  107. {isar-1.10.14 → isar-1.12.0}/src/isar/state_machine/states/idle.py +6 -6
  108. {isar-1.10.14 → isar-1.12.0}/src/isar/state_machine/states/initialize.py +9 -8
  109. {isar-1.10.14 → isar-1.12.0}/src/isar/state_machine/states/initiate_step.py +16 -16
  110. {isar-1.10.14 → isar-1.12.0}/src/isar/state_machine/states/monitor.py +17 -11
  111. {isar-1.10.14 → isar-1.12.0}/src/isar/state_machine/states/off.py +0 -0
  112. {isar-1.10.14 → isar-1.12.0}/src/isar/state_machine/states/paused.py +6 -6
  113. {isar-1.10.14 → isar-1.12.0}/src/isar/state_machine/states/stop_step.py +10 -10
  114. {isar-1.10.14 → isar-1.12.0}/src/isar/state_machine/states_enum.py +0 -1
  115. {isar-1.10.14/src/robot_interface → isar-1.12.0/src/isar/storage}/__init__.py +0 -0
  116. {isar-1.10.14 → isar-1.12.0}/src/isar/storage/blob_storage.py +0 -0
  117. {isar-1.10.14 → isar-1.12.0}/src/isar/storage/local_storage.py +2 -2
  118. isar-1.12.0/src/isar/storage/slimm_storage.py +187 -0
  119. {isar-1.10.14 → isar-1.12.0}/src/isar/storage/storage_interface.py +0 -0
  120. {isar-1.10.14 → isar-1.12.0}/src/isar/storage/uploader.py +4 -5
  121. {isar-1.10.14 → isar-1.12.0}/src/isar/storage/utilities.py +1 -23
  122. {isar-1.10.14 → isar-1.12.0}/src/isar.egg-info/PKG-INFO +1 -1
  123. {isar-1.10.14 → isar-1.12.0}/src/isar.egg-info/SOURCES.txt +7 -0
  124. {isar-1.10.14 → isar-1.12.0}/src/isar.egg-info/dependency_links.txt +0 -0
  125. {isar-1.10.14 → isar-1.12.0}/src/isar.egg-info/requires.txt +3 -0
  126. {isar-1.10.14 → isar-1.12.0}/src/isar.egg-info/top_level.txt +0 -0
  127. {isar-1.10.14/src/robot_interface/models → isar-1.12.0/src/robot_interface}/__init__.py +0 -0
  128. {isar-1.10.14/src/robot_interface/telemetry → isar-1.12.0/src/robot_interface/models}/__init__.py +0 -0
  129. {isar-1.10.14 → isar-1.12.0}/src/robot_interface/models/exceptions/__init__.py +0 -0
  130. {isar-1.10.14 → isar-1.12.0}/src/robot_interface/models/exceptions/robot_exceptions.py +0 -0
  131. {isar-1.10.14 → isar-1.12.0}/src/robot_interface/models/initialize/__init__.py +0 -0
  132. {isar-1.10.14 → isar-1.12.0}/src/robot_interface/models/initialize/initialize_params.py +0 -0
  133. {isar-1.10.14 → isar-1.12.0}/src/robot_interface/models/inspection/__init__.py +0 -0
  134. {isar-1.10.14 → isar-1.12.0}/src/robot_interface/models/inspection/inspection.py +3 -22
  135. {isar-1.10.14 → isar-1.12.0}/src/robot_interface/models/mission/__init__.py +0 -0
  136. {isar-1.10.14 → isar-1.12.0}/src/robot_interface/models/mission/status.py +6 -1
  137. {isar-1.10.14 → isar-1.12.0}/src/robot_interface/models/mission/step.py +5 -32
  138. {isar-1.10.14/src/robot_interface/utilities → isar-1.12.0/src/robot_interface/models/robots}/__init__.py +0 -0
  139. isar-1.12.0/src/robot_interface/models/robots/robot_model.py +13 -0
  140. {isar-1.10.14 → isar-1.12.0}/src/robot_interface/robot_interface.py +17 -0
  141. {isar-1.10.14/tests → isar-1.12.0/src/robot_interface/telemetry}/__init__.py +0 -0
  142. {isar-1.10.14 → isar-1.12.0}/src/robot_interface/telemetry/mqtt_client.py +0 -0
  143. isar-1.12.0/src/robot_interface/telemetry/payloads.py +52 -0
  144. {isar-1.10.14 → isar-1.12.0}/src/robot_interface/test_robot_interface.py +0 -0
  145. {isar-1.10.14/tests/integration → isar-1.12.0/src/robot_interface/utilities}/__init__.py +0 -0
  146. {isar-1.10.14 → isar-1.12.0}/src/robot_interface/utilities/json_service.py +3 -0
  147. {isar-1.10.14/tests/integration/turtlebot → isar-1.12.0/tests}/__init__.py +0 -0
  148. {isar-1.10.14 → isar-1.12.0}/tests/conftest.py +0 -0
  149. {isar-1.10.14/tests/integration/turtlebot/config → isar-1.12.0/tests/integration}/__init__.py +0 -0
  150. {isar-1.10.14/tests/integration/turtlebot/config/maps → isar-1.12.0/tests/integration/turtlebot}/__init__.py +0 -0
  151. {isar-1.10.14/tests/integration/turtlebot/config/missions → isar-1.12.0/tests/integration/turtlebot/config}/__init__.py +0 -0
  152. {isar-1.10.14/tests/isar → isar-1.12.0/tests/integration/turtlebot/config/maps}/__init__.py +0 -0
  153. {isar-1.10.14 → isar-1.12.0}/tests/integration/turtlebot/config/maps/turtleworld.json +0 -0
  154. {isar-1.10.14/tests/isar/apis → isar-1.12.0/tests/integration/turtlebot/config/missions}/__init__.py +0 -0
  155. {isar-1.10.14 → isar-1.12.0}/tests/integration/turtlebot/config/missions/default.json +0 -0
  156. {isar-1.10.14 → isar-1.12.0}/tests/integration/turtlebot/test_successful_mission.py +1 -1
  157. {isar-1.10.14/tests/isar/apis/scheduler → isar-1.12.0/tests/isar}/__init__.py +0 -0
  158. {isar-1.10.14/tests/isar/apis/security → isar-1.12.0/tests/isar/apis}/__init__.py +0 -0
  159. {isar-1.10.14/tests/isar/models → isar-1.12.0/tests/isar/apis/scheduler}/__init__.py +0 -0
  160. {isar-1.10.14 → isar-1.12.0}/tests/isar/apis/scheduler/test_scheduler_router.py +8 -8
  161. {isar-1.10.14/tests/isar/models/communication → isar-1.12.0/tests/isar/apis/security}/__init__.py +0 -0
  162. {isar-1.10.14 → isar-1.12.0}/tests/isar/apis/security/test_authentication.py +0 -1
  163. {isar-1.10.14/tests/isar/services → isar-1.12.0/tests/isar/models}/__init__.py +0 -0
  164. {isar-1.10.14/tests/isar/services/readers → isar-1.12.0/tests/isar/models/communication}/__init__.py +0 -0
  165. {isar-1.10.14 → isar-1.12.0}/tests/isar/models/communication/test_queues.py +4 -4
  166. {isar-1.10.14/tests/isar/services/service_connections → isar-1.12.0/tests/isar/services}/__init__.py +0 -0
  167. {isar-1.10.14/tests/isar/services/service_connections/echo → isar-1.12.0/tests/isar/services/readers}/__init__.py +0 -0
  168. {isar-1.10.14 → isar-1.12.0}/tests/isar/services/readers/test_base_reader.py +0 -0
  169. {isar-1.10.14 → isar-1.12.0}/tests/isar/services/readers/test_mission_reader.py +9 -9
  170. {isar-1.10.14/tests/isar/services/service_connections/stid → isar-1.12.0/tests/isar/services/service_connections}/__init__.py +0 -0
  171. {isar-1.10.14/tests/isar/services/utilities → isar-1.12.0/tests/isar/services/service_connections/echo}/__init__.py +0 -0
  172. {isar-1.10.14 → isar-1.12.0}/tests/isar/services/service_connections/echo/test_echo_service.py +1 -1
  173. {isar-1.10.14/tests/isar/state_machine → isar-1.12.0/tests/isar/services/service_connections/stid}/__init__.py +0 -0
  174. {isar-1.10.14 → isar-1.12.0}/tests/isar/services/service_connections/stid/test_stid_service.py +3 -1
  175. {isar-1.10.14 → isar-1.12.0}/tests/isar/services/service_connections/test_base_request_handler.py +0 -0
  176. {isar-1.10.14/tests/isar/state_machine/states → isar-1.12.0/tests/isar/services/utilities}/__init__.py +0 -0
  177. {isar-1.10.14 → isar-1.12.0}/tests/isar/services/utilities/test_queue_utilities.py +0 -0
  178. {isar-1.10.14 → isar-1.12.0}/tests/isar/services/utilities/test_scheduling_utilities.py +0 -0
  179. {isar-1.10.14/tests/mocks → isar-1.12.0/tests/isar/state_machine}/__init__.py +0 -0
  180. isar-1.10.14/tests/mocks/task.py → isar-1.12.0/tests/isar/state_machine/states/__init__.py +0 -0
  181. {isar-1.10.14 → isar-1.12.0}/tests/isar/state_machine/states/test_monitor.py +0 -0
  182. {isar-1.10.14 → isar-1.12.0}/tests/isar/state_machine/test_state_machine.py +17 -15
  183. {isar-1.10.14 → isar-1.12.0}/tests/isar/storage/test_blob_storage.py +0 -0
  184. {isar-1.10.14 → isar-1.12.0}/tests/isar/storage/test_uploader.py +2 -2
  185. isar-1.12.0/tests/mocks/__init__.py +0 -0
  186. {isar-1.10.14 → isar-1.12.0}/tests/mocks/blob_storage.py +0 -0
  187. {isar-1.10.14 → isar-1.12.0}/tests/mocks/mission_definition.py +8 -3
  188. {isar-1.10.14 → isar-1.12.0}/tests/mocks/mqtt_client.py +0 -0
  189. {isar-1.10.14 → isar-1.12.0}/tests/mocks/pose.py +0 -0
  190. {isar-1.10.14 → isar-1.12.0}/tests/mocks/request.py +0 -0
  191. {isar-1.10.14 → isar-1.12.0}/tests/mocks/robot_interface.py +6 -0
  192. {isar-1.10.14 → isar-1.12.0}/tests/mocks/status.py +0 -0
  193. {isar-1.10.14 → isar-1.12.0}/tests/mocks/step.py +0 -0
  194. isar-1.12.0/tests/mocks/task.py +0 -0
  195. {isar-1.10.14 → isar-1.12.0}/tests/mocks/token.py +0 -0
  196. {isar-1.10.14 → isar-1.12.0}/tests/test_data/test_json_file.json +0 -0
  197. {isar-1.10.14 → isar-1.12.0}/tests/test_data/test_map_config/test_map_config.json +0 -0
  198. {isar-1.10.14 → isar-1.12.0}/tests/test_data/test_mission_not_working.json +0 -0
  199. {isar-1.10.14 → isar-1.12.0}/tests/test_data/test_mission_working.json +0 -0
  200. {isar-1.10.14 → isar-1.12.0}/tests/test_data/test_mission_working_no_tasks.json +0 -0
  201. {isar-1.10.14 → isar-1.12.0}/tests/test_data/test_thermal_image_mission.json +0 -0
  202. {isar-1.10.14 → isar-1.12.0}/tests/test_modules.py +0 -0
  203. isar-1.10.14/src/isar/config/keyvault/keyvault_service.py +0 -71
  204. isar-1.10.14/src/isar/config/log.py +0 -32
  205. isar-1.10.14/src/isar/config/predefined_missions/default.json +0 -92
  206. isar-1.10.14/src/isar/storage/slimm_storage.py +0 -121
  207. isar-1.10.14/src/robot_interface/telemetry/payloads.py +0 -18
File without changes
File without changes
@@ -17,10 +17,10 @@ jobs:
17
17
  python-version: ["3.8", "3.9", "3.10"]
18
18
 
19
19
  steps:
20
- - uses: actions/checkout@v2
20
+ - uses: actions/checkout@v3
21
21
 
22
22
  - name: Set up Python ${{ matrix.python-version }}
23
- uses: actions/setup-python@v2
23
+ uses: actions/setup-python@v3
24
24
  with:
25
25
  python-version: ${{ matrix.python-version }}
26
26
 
File without changes
File without changes
File without changes
File without changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: isar
3
- Version: 1.10.14
3
+ Version: 1.12.0
4
4
  Summary: Integration and Supervisory control of Autonomous Robots
5
5
  Home-page: https://github.com/equinor/isar
6
6
  Author: Equinor ASA
File without changes
File without changes
File without changes
File without changes
@@ -3,7 +3,6 @@ from pathlib import Path
3
3
  src_dir = Path("source/api")
4
4
 
5
5
  for file in src_dir.iterdir():
6
-
7
6
  print(f"Processing .rst-file: {file}")
8
7
 
9
8
  with open(file, "r") as f:
File without changes
File without changes
File without changes
@@ -7,12 +7,19 @@ from dotenv import load_dotenv
7
7
  from injector import Injector
8
8
 
9
9
  from isar.apis.api import API
10
- from isar.config.log import setup_logger
10
+ from isar.config.keyvault.keyvault_service import Keyvault
11
+ from isar.config.log import setup_loggers
11
12
  from isar.config.settings import settings
12
13
  from isar.models.communication.queues.queues import Queues
13
14
  from isar.modules import get_injector
14
15
  from isar.services.service_connections.mqtt.mqtt_client import MqttClient
15
- from isar.state_machine.state_machine import main
16
+ from isar.services.service_connections.mqtt.robot_info_publisher import (
17
+ RobotInfoPublisher,
18
+ )
19
+ from isar.services.service_connections.mqtt.robot_status_publisher import (
20
+ RobotStatusPublisher,
21
+ )
22
+ from isar.state_machine.state_machine import StateMachine, main
16
23
  from isar.storage.storage_interface import StorageInterface
17
24
  from isar.storage.uploader import Uploader
18
25
  from robot_interface.robot_interface import RobotInterface
@@ -20,18 +27,20 @@ from robot_interface.robot_interface import RobotInterface
20
27
  if __name__ == "__main__":
21
28
  load_dotenv()
22
29
 
23
- setup_logger()
24
- logger: Logger = logging.getLogger("main")
25
-
26
30
  injector: Injector = get_injector()
27
31
 
32
+ keyvault_client = injector.get(Keyvault)
33
+ setup_loggers(keyvault=keyvault_client)
34
+ logger: Logger = logging.getLogger("main")
35
+
36
+ state_machine: StateMachine = injector.get(StateMachine)
28
37
  robot: RobotInterface = injector.get(RobotInterface)
29
38
  queues: Queues = injector.get(Queues)
30
39
 
31
40
  threads: List[Thread] = []
32
41
 
33
42
  state_machine_thread: Thread = Thread(
34
- target=main, name="ISAR State Machine", args=[injector], daemon=True
43
+ target=main, name="ISAR State Machine", args=[state_machine], daemon=True
35
44
  )
36
45
  threads.append(state_machine_thread)
37
46
 
@@ -51,13 +60,31 @@ if __name__ == "__main__":
51
60
  mqtt_thread: Thread = Thread(
52
61
  target=mqtt_client.run, name="ISAR MQTT Client", daemon=True
53
62
  )
54
-
55
63
  threads.append(mqtt_thread)
56
64
 
65
+ robot_status_publisher: RobotStatusPublisher = RobotStatusPublisher(
66
+ mqtt_queue=queues.mqtt_queue, robot=robot, state_machine=state_machine
67
+ )
68
+ robot_status_thread: Thread = Thread(
69
+ target=robot_status_publisher.run,
70
+ name="ISAR Robot Status Publisher",
71
+ daemon=True,
72
+ )
73
+ threads.append(robot_status_thread)
74
+
75
+ robot_info_publisher: RobotInfoPublisher = RobotInfoPublisher(
76
+ mqtt_queue=queues.mqtt_queue
77
+ )
78
+ robot_info_thread: Thread = Thread(
79
+ target=robot_info_publisher.run,
80
+ name="ISAR Robot Info Publisher",
81
+ daemon=True,
82
+ )
83
+ threads.append(robot_info_thread)
84
+
57
85
  publishers: List[Thread] = robot.get_telemetry_publishers(
58
86
  queue=queues.mqtt_queue, robot_id=settings.ROBOT_ID
59
87
  )
60
-
61
88
  if publishers:
62
89
  threads.extend(publishers)
63
90
 
File without changes
File without changes
File without changes
@@ -36,6 +36,9 @@ setup(
36
36
  "fastapi-azure-auth",
37
37
  "fastapi",
38
38
  "injector",
39
+ "opencensus-ext-logging",
40
+ "opencensus-ext-requests",
41
+ "opencensus-ext-azure",
39
42
  "numpy",
40
43
  "paho-mqtt",
41
44
  "pydantic",
File without changes
File without changes
@@ -1,21 +1,34 @@
1
1
  import logging
2
2
  from http import HTTPStatus
3
3
  from logging import Logger
4
+ import os
4
5
  from typing import List, Union
5
6
 
6
7
  import click
7
8
  import uvicorn
8
- from fastapi import FastAPI, Security
9
+ from fastapi import FastAPI, Security, Request
9
10
  from fastapi.middleware.cors import CORSMiddleware
10
11
  from fastapi.routing import APIRouter
11
12
  from injector import inject
12
13
  from pydantic import AnyHttpUrl
13
14
 
15
+ from opencensus.ext.azure.trace_exporter import AzureExporter
16
+ from opencensus.trace.samplers import ProbabilitySampler
17
+ from opencensus.trace.tracer import Tracer
18
+ from opencensus.trace.span import SpanKind
19
+ from opencensus.trace.attributes_helper import COMMON_ATTRIBUTES
20
+
14
21
  from isar.apis.models.models import ControlMissionResponse, StartMissionResponse
15
22
  from isar.apis.schedule.scheduling_controller import SchedulingController
16
23
  from isar.apis.security.authentication import Authenticator
24
+ from isar.config.configuration_error import ConfigurationError
25
+ from isar.config.keyvault.keyvault_error import KeyvaultError
26
+ from isar.config.keyvault.keyvault_service import Keyvault
17
27
  from isar.config.settings import settings
18
28
 
29
+ HTTP_URL = COMMON_ATTRIBUTES["HTTP_URL"]
30
+ HTTP_STATUS_CODE = COMMON_ATTRIBUTES["HTTP_STATUS_CODE"]
31
+
19
32
 
20
33
  class API:
21
34
  @inject
@@ -23,13 +36,16 @@ class API:
23
36
  self,
24
37
  authenticator: Authenticator,
25
38
  scheduling_controller: SchedulingController,
39
+ keyvault_client: Keyvault,
26
40
  port: int = settings.API_PORT,
41
+ azure_ai_logging_enabled: bool = settings.LOG_HANDLER_APPLICATION_INSIGHTS_ENABLED,
27
42
  ) -> None:
28
-
29
43
  self.authenticator: Authenticator = authenticator
30
44
  self.scheduling_controller: SchedulingController = scheduling_controller
45
+ self.keyvault_client: Keyvault = keyvault_client
31
46
  self.host: str = "0.0.0.0" # Locking uvicorn to use 0.0.0.0
32
47
  self.port: int = port
48
+ self.azure_ai_logging_enabled: bool = azure_ai_logging_enabled
33
49
 
34
50
  self.logger: Logger = logging.getLogger("api")
35
51
 
@@ -77,6 +93,9 @@ class API:
77
93
  allow_headers=["*"],
78
94
  )
79
95
 
96
+ if self.azure_ai_logging_enabled:
97
+ self._add_request_logging_middleware(app)
98
+
80
99
  app.include_router(router=self._create_scheduler_router())
81
100
 
82
101
  app.include_router(router=self._create_info_router())
@@ -84,7 +103,6 @@ class API:
84
103
  return app
85
104
 
86
105
  def _create_scheduler_router(self) -> APIRouter:
87
-
88
106
  router: APIRouter = APIRouter(tags=["Scheduler"])
89
107
 
90
108
  authentication_dependency: Security = Security(self.authenticator.get_scheme())
@@ -213,7 +231,6 @@ class API:
213
231
  return router
214
232
 
215
233
  def _create_info_router(self) -> APIRouter:
216
-
217
234
  router: APIRouter = APIRouter(tags=["Info"])
218
235
 
219
236
  authentication_dependency: Security = Security(self.authenticator.get_scheme())
@@ -244,3 +261,36 @@ class API:
244
261
  self.port,
245
262
  extra={"color_message": color_message},
246
263
  )
264
+
265
+ def _add_request_logging_middleware(self, app: FastAPI) -> None:
266
+ connection_string: str
267
+ try:
268
+ connection_string = self.keyvault_client.get_secret(
269
+ "application-insights-connection-string"
270
+ ).value
271
+ except KeyvaultError:
272
+ message: str = (
273
+ "Missing connection string for Application Insights in key vault. "
274
+ )
275
+ self.logger.critical(message)
276
+ raise ConfigurationError(message)
277
+
278
+ @app.middleware("http")
279
+ async def middlewareOpencensus(request: Request, call_next):
280
+ tracer = Tracer(
281
+ exporter=AzureExporter(connection_string=connection_string),
282
+ sampler=ProbabilitySampler(1.0),
283
+ )
284
+ with tracer.span("main") as span:
285
+ span.span_kind = SpanKind.SERVER
286
+
287
+ response = await call_next(request)
288
+
289
+ tracer.add_attribute_to_current_span(
290
+ attribute_key=HTTP_STATUS_CODE, attribute_value=response.status_code
291
+ )
292
+ tracer.add_attribute_to_current_span(
293
+ attribute_key=HTTP_URL, attribute_value=str(request.url)
294
+ )
295
+
296
+ return response
@@ -1,37 +1,41 @@
1
- from typing import List, Optional, Type
1
+ from enum import Enum
2
+ from typing import List, Optional
2
3
 
3
4
  from alitra import Position
4
5
  from pydantic import BaseModel, Field
6
+
7
+ from isar.apis.models.models import InputPose, InputPosition
8
+ from isar.mission_planner.mission_planner_interface import MissionPlannerError
9
+ from isar.models.mission.mission import Mission, Task
5
10
  from robot_interface.models.mission.step import (
6
11
  STEPS,
7
12
  DriveToPose,
8
- InspectionStep,
9
13
  TakeImage,
10
14
  TakeThermalImage,
11
15
  TakeThermalVideo,
12
16
  TakeVideo,
13
17
  )
14
18
 
15
- from isar.apis.models.models import InputPose, InputPosition
16
- from isar.mission_planner.mission_planner_interface import MissionPlannerError
17
- from isar.models.mission.mission import Mission, Task
18
19
 
19
- inspection_step_types: List[Type[InspectionStep]] = [
20
- TakeImage,
21
- TakeThermalImage,
22
- TakeVideo,
23
- TakeThermalVideo,
24
- ]
20
+ class InspectionTypes(str, Enum):
21
+ image = "Image"
22
+ thermal_image = "ThermalImage"
23
+ video = "Video"
24
+ thermal_video = "ThermalVideo"
25
+
26
+
27
+ class StartMissionInspectionDefinition(BaseModel):
28
+ type: InspectionTypes = Field(default=InspectionTypes.image)
29
+ inspection_target: InputPosition
30
+ analysis_types: Optional[List]
31
+ duration: Optional[float]
32
+ metadata: Optional[dict]
25
33
 
26
34
 
27
35
  class StartMissionTaskDefinition(BaseModel):
28
36
  pose: InputPose
29
37
  tag: Optional[str]
30
- inspection_target: InputPosition
31
- inspection_types: List[str] = Field(
32
- default=[step.get_inspection_type().__name__ for step in inspection_step_types]
33
- )
34
- video_duration: Optional[float] = Field(default=10)
38
+ inspections: List[StartMissionInspectionDefinition]
35
39
 
36
40
 
37
41
  class StartMissionDefinition(BaseModel):
@@ -47,14 +51,16 @@ def to_isar_mission(mission_definition: StartMissionDefinition) -> Mission:
47
51
  drive_step: DriveToPose = DriveToPose(pose=task.pose.to_alitra_pose())
48
52
  inspection_steps: List[STEPS] = [
49
53
  create_inspection_step(
50
- inspection_type=inspection_type,
51
- duration=task.video_duration,
52
- target=task.inspection_target.to_alitra_position(),
54
+ inspection_type=inspection.type,
55
+ duration=inspection.duration,
56
+ target=inspection.inspection_target.to_alitra_position(),
53
57
  tag_id=tag_id,
58
+ analysis=inspection.analysis_types,
59
+ metadata=inspection.metadata,
54
60
  )
55
- for inspection_type in task.inspection_types
61
+ for inspection in task.inspections
56
62
  ]
57
- except (ValueError) as e:
63
+ except ValueError as e:
58
64
  raise MissionPlannerError(f"Failed to create task: {str(e)}")
59
65
  isar_task: Task = Task(steps=[drive_step, *inspection_steps], tag_id=tag_id)
60
66
  isar_tasks.append(isar_task)
@@ -68,27 +74,30 @@ def to_isar_mission(mission_definition: StartMissionDefinition) -> Mission:
68
74
 
69
75
 
70
76
  def create_inspection_step(
71
- inspection_type: str, duration: float, target: Position, tag_id: Optional[str]
77
+ inspection_type: InspectionTypes,
78
+ duration: float,
79
+ target: Position,
80
+ analysis: Optional[List],
81
+ tag_id: Optional[str],
82
+ metadata: Optional[dict],
72
83
  ) -> STEPS:
73
84
  inspection_step: STEPS
74
-
75
- if inspection_type == TakeImage.get_inspection_type().__name__:
85
+ if inspection_type == InspectionTypes.image.value:
76
86
  inspection_step = TakeImage(target=target)
77
- if tag_id:
78
- inspection_step.tag_id = tag_id
79
- elif inspection_type == TakeVideo.get_inspection_type().__name__:
87
+ elif inspection_type == InspectionTypes.video.value:
80
88
  inspection_step = TakeVideo(target=target, duration=duration)
81
- if tag_id:
82
- inspection_step.tag_id = tag_id
83
- elif inspection_type == TakeThermalImage.get_inspection_type().__name__:
89
+ elif inspection_type == InspectionTypes.thermal_image.value:
84
90
  inspection_step = TakeThermalImage(target=target)
85
- if tag_id:
86
- inspection_step.tag_id = tag_id
87
- elif inspection_type == TakeThermalVideo.get_inspection_type().__name__:
91
+ elif inspection_type == InspectionTypes.thermal_video.value:
88
92
  inspection_step = TakeThermalVideo(target=target, duration=duration)
89
- if tag_id:
90
- inspection_step.tag_id = tag_id
91
93
  else:
92
94
  raise ValueError(f"Inspection type '{inspection_type}' not supported")
93
95
 
96
+ if tag_id:
97
+ inspection_step.tag_id = tag_id
98
+ if analysis:
99
+ inspection_step.analysis = analysis
100
+ if metadata:
101
+ inspection_step.metadata = metadata
102
+
94
103
  return inspection_step
@@ -1,11 +1,10 @@
1
1
  import logging
2
2
 
3
-
4
3
  from fastapi import Depends
5
- from fastapi_azure_auth.exceptions import InvalidAuth
6
- from fastapi_azure_auth.user import User
7
4
  from fastapi.security.base import SecurityBase
8
5
  from fastapi_azure_auth import SingleTenantAzureAuthorizationCodeBearer
6
+ from fastapi_azure_auth.exceptions import InvalidAuth
7
+ from fastapi_azure_auth.user import User
9
8
  from pydantic import BaseModel
10
9
 
11
10
  from isar.config.settings import settings
@@ -32,8 +31,8 @@ azure_scheme = SingleTenantAzureAuthorizationCodeBearer(
32
31
 
33
32
  async def validate_has_role(user: User = Depends(azure_scheme)) -> None:
34
33
  """
35
- Validate that a user has the `role` role in order to access the API.
36
- Raises a 401 authentication error if not.
34
+ Validate if the user has the required role in order to access the API.
35
+ Raises a 401 authorization error if not.
37
36
  """
38
37
  if settings.REQUIRED_ROLE not in user.roles:
39
38
  raise InvalidAuth(
@@ -0,0 +1,88 @@
1
+ import logging
2
+ import traceback
3
+ from typing import Union
4
+
5
+ from azure.core.exceptions import (
6
+ ClientAuthenticationError,
7
+ HttpResponseError,
8
+ ResourceNotFoundError,
9
+ )
10
+ from azure.identity import ClientSecretCredential, DefaultAzureCredential
11
+ from azure.keyvault.secrets import KeyVaultSecret, SecretClient
12
+
13
+ from isar.config.keyvault.keyvault_error import KeyvaultError
14
+
15
+
16
+ class Keyvault:
17
+ def __init__(
18
+ self,
19
+ keyvault_name: str,
20
+ client_id: str = None,
21
+ client_secret: str = None,
22
+ tenant_id: str = None,
23
+ ):
24
+ self.name = keyvault_name
25
+ self.url = "https://" + keyvault_name + ".vault.azure.net"
26
+ self.client_id = client_id
27
+ self.client_secret = client_secret
28
+ self.tenant_id = tenant_id
29
+ self.logger = logging.getLogger("API")
30
+ self.client: SecretClient = None
31
+
32
+ def get_secret(self, secret_name: str) -> KeyVaultSecret:
33
+ secret_client: SecretClient = self.get_secret_client()
34
+ try:
35
+ secret: KeyVaultSecret = secret_client.get_secret(name=secret_name)
36
+ except ResourceNotFoundError:
37
+ self.logger.error(
38
+ "Secret '%s' was not found in keyvault '%s'.",
39
+ secret_name,
40
+ self.name,
41
+ exc_info=True,
42
+ )
43
+ raise KeyvaultError # type: ignore
44
+ except HttpResponseError:
45
+ self.logger.error(
46
+ "An error occurred while retrieving the secret '%s' from keyvault '%s'.",
47
+ secret_name,
48
+ self.name,
49
+ exc_info=True,
50
+ )
51
+ raise KeyvaultError # type: ignore
52
+
53
+ return secret
54
+
55
+ def set_secret(self, secret_name: str, secret_value) -> None:
56
+ secret_client: SecretClient = self.get_secret_client()
57
+ try:
58
+ secret_client.set_secret(name=secret_name, value=secret_value)
59
+ except HttpResponseError:
60
+ self.logger.error(
61
+ "An error occurred while setting secret '%s' in keyvault '%s'.",
62
+ secret_name,
63
+ self.name,
64
+ exc_info=True,
65
+ )
66
+ raise KeyvaultError # type: ignore
67
+
68
+ def get_secret_client(self) -> SecretClient:
69
+ if self.client == None:
70
+ try:
71
+ credential: Union[ClientSecretCredential, DefaultAzureCredential]
72
+ if self.client_id and self.client_secret and self.tenant_id:
73
+ credential = ClientSecretCredential(
74
+ tenant_id=self.tenant_id,
75
+ client_id=self.client_id,
76
+ client_secret=self.client_secret,
77
+ )
78
+ else:
79
+ credential = DefaultAzureCredential()
80
+ except ClientAuthenticationError:
81
+ self.logger.error(
82
+ "Failed to authenticate to Azure while connecting to KeyVault",
83
+ exc_info=True,
84
+ )
85
+ raise KeyvaultError
86
+
87
+ self.client = SecretClient(vault_url=self.url, credential=credential)
88
+ return self.client
@@ -0,0 +1,61 @@
1
+ import importlib.resources as pkg_resources
2
+ import logging
3
+ import logging.config
4
+ import yaml
5
+ from uvicorn.logging import ColourizedFormatter
6
+ from opencensus.ext.azure.log_exporter import AzureLogHandler
7
+ from isar.config.configuration_error import ConfigurationError
8
+ from isar.config.keyvault.keyvault_error import KeyvaultError
9
+ from isar.config.keyvault.keyvault_service import Keyvault
10
+ from isar.config.settings import settings
11
+
12
+
13
+ def setup_loggers(keyvault: Keyvault) -> None:
14
+ log_levels: dict = settings.LOG_LEVELS
15
+ with pkg_resources.path("isar.config", "logging.conf") as path:
16
+ log_config = yaml.safe_load(open(path))
17
+
18
+ logging.config.dictConfig(log_config)
19
+
20
+ handlers = []
21
+ if settings.LOG_HANDLER_LOCAL_ENABLED:
22
+ handlers.append(configure_console_handler(log_config=log_config))
23
+ if settings.LOG_HANDLER_APPLICATION_INSIGHTS_ENABLED:
24
+ handlers.append(
25
+ configure_azure_handler(log_config=log_config, keyvault=keyvault)
26
+ )
27
+
28
+ for log_handler in handlers:
29
+ for loggers in log_config["loggers"].keys():
30
+ logging.getLogger(loggers).addHandler(log_handler)
31
+ logging.getLogger(loggers).setLevel(log_levels[loggers])
32
+ logging.getLogger().addHandler(log_handler)
33
+
34
+
35
+ def configure_console_handler(log_config: dict) -> logging.Handler:
36
+ handler = logging.StreamHandler()
37
+ handler.setLevel(log_config["root"]["level"])
38
+ handler.setFormatter(
39
+ ColourizedFormatter(
40
+ log_config["formatters"]["colourized"]["format"],
41
+ style="{",
42
+ use_colors=True,
43
+ )
44
+ )
45
+ return handler
46
+
47
+
48
+ def configure_azure_handler(log_config: dict, keyvault: Keyvault) -> logging.Handler:
49
+ connection_string: str
50
+ try:
51
+ connection_string = keyvault.get_secret(
52
+ "application-insights-connection-string"
53
+ ).value
54
+ except KeyvaultError:
55
+ message: str = f"CRITICAL ERROR: Missing connection string for Application Insights in key vault '{keyvault.name}'."
56
+ print(f"\n{message} \n")
57
+ raise ConfigurationError(message)
58
+
59
+ handler = AzureLogHandler(connection_string=connection_string)
60
+ handler.setLevel(log_config["root"]["level"])
61
+ return handler