isar 1.11.0__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 (205) hide show
  1. {isar-1.11.0 → isar-1.12.0}/.dockerignore +0 -0
  2. {isar-1.11.0 → isar-1.12.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  3. {isar-1.11.0 → isar-1.12.0}/.github/ISSUE_TEMPLATE/feature.md +0 -0
  4. {isar-1.11.0 → isar-1.12.0}/.github/ISSUE_TEMPLATE/improvement.md +0 -0
  5. {isar-1.11.0 → isar-1.12.0}/.github/release.yml +0 -0
  6. {isar-1.11.0 → isar-1.12.0}/.github/workflows/project_automations.yml +0 -0
  7. {isar-1.11.0 → isar-1.12.0}/.github/workflows/publish_isar_base_image.yml +0 -0
  8. {isar-1.11.0 → isar-1.12.0}/.github/workflows/pythonpackage.yml +2 -2
  9. {isar-1.11.0 → isar-1.12.0}/.github/workflows/pythonpublish.yml +0 -0
  10. {isar-1.11.0 → isar-1.12.0}/.github/workflows/repository_dispatch_on_merge.yml +0 -0
  11. {isar-1.11.0 → isar-1.12.0}/.github/workflows/stale.yml +0 -0
  12. {isar-1.11.0 → isar-1.12.0}/.gitignore +0 -0
  13. {isar-1.11.0 → isar-1.12.0}/.pre-commit-config.yaml +0 -0
  14. {isar-1.11.0 → isar-1.12.0}/Dockerfile +0 -0
  15. {isar-1.11.0 → isar-1.12.0}/LICENSE +0 -0
  16. {isar-1.11.0 → isar-1.12.0}/PKG-INFO +1 -1
  17. {isar-1.11.0 → isar-1.12.0}/README.md +0 -0
  18. {isar-1.11.0 → isar-1.12.0}/docker-compose-turtlebot.yml +0 -0
  19. {isar-1.11.0 → isar-1.12.0}/docker-compose.yml +0 -0
  20. {isar-1.11.0 → isar-1.12.0}/docs/Makefile +0 -0
  21. {isar-1.11.0 → isar-1.12.0}/docs/make.bat +0 -0
  22. {isar-1.11.0 → isar-1.12.0}/docs/rst_processing.py +0 -0
  23. {isar-1.11.0 → isar-1.12.0}/docs/source/conf.py +0 -0
  24. {isar-1.11.0 → isar-1.12.0}/docs/source/index.rst +0 -0
  25. {isar-1.11.0 → isar-1.12.0}/docs/source/readme_link.md +0 -0
  26. {isar-1.11.0 → isar-1.12.0}/docs/state_machine_diagram.png +0 -0
  27. {isar-1.11.0 → isar-1.12.0}/main.py +6 -4
  28. {isar-1.11.0 → isar-1.12.0}/pyproject.toml +0 -0
  29. {isar-1.11.0 → isar-1.12.0}/radixconfig.yml +0 -0
  30. {isar-1.11.0 → isar-1.12.0}/setup.cfg +0 -0
  31. {isar-1.11.0 → isar-1.12.0}/setup.py +3 -0
  32. {isar-1.11.0 → isar-1.12.0}/src/isar/__init__.py +0 -0
  33. {isar-1.11.0 → isar-1.12.0}/src/isar/apis/__init__.py +0 -0
  34. {isar-1.11.0 → isar-1.12.0}/src/isar/apis/api.py +54 -1
  35. {isar-1.11.0 → isar-1.12.0}/src/isar/apis/models/__init__.py +0 -0
  36. {isar-1.11.0 → isar-1.12.0}/src/isar/apis/models/models.py +0 -0
  37. {isar-1.11.0 → isar-1.12.0}/src/isar/apis/models/start_mission_definition.py +40 -31
  38. {isar-1.11.0 → isar-1.12.0}/src/isar/apis/schedule/__init__.py +0 -0
  39. {isar-1.11.0 → isar-1.12.0}/src/isar/apis/schedule/scheduling_controller.py +0 -0
  40. {isar-1.11.0 → isar-1.12.0}/src/isar/apis/security/__init__.py +0 -0
  41. {isar-1.11.0 → isar-1.12.0}/src/isar/apis/security/authentication.py +2 -2
  42. {isar-1.11.0 → isar-1.12.0}/src/isar/config/__init__.py +0 -0
  43. {isar-1.11.0 → isar-1.12.0}/src/isar/config/certs/ca-cert.pem +0 -0
  44. {isar-1.11.0 → isar-1.12.0}/src/isar/config/configuration_error.py +0 -0
  45. {isar-1.11.0 → isar-1.12.0}/src/isar/config/keyvault/__init__.py +0 -0
  46. {isar-1.11.0 → isar-1.12.0}/src/isar/config/keyvault/keyvault_error.py +0 -0
  47. {isar-1.11.0 → isar-1.12.0}/src/isar/config/keyvault/keyvault_service.py +36 -21
  48. isar-1.12.0/src/isar/config/log.py +61 -0
  49. {isar-1.11.0 → isar-1.12.0}/src/isar/config/logging.conf +0 -0
  50. {isar-1.11.0 → isar-1.12.0}/src/isar/config/maps/JSP1_intermediate_deck.json +0 -0
  51. {isar-1.11.0 → isar-1.12.0}/src/isar/config/maps/JSP1_weather_deck.json +0 -0
  52. {isar-1.11.0 → isar-1.12.0}/src/isar/config/maps/default_map.json +0 -0
  53. {isar-1.11.0 → isar-1.12.0}/src/isar/config/maps/klab_b.json +0 -0
  54. {isar-1.11.0 → isar-1.12.0}/src/isar/config/maps/klab_compressor.json +0 -0
  55. {isar-1.11.0 → isar-1.12.0}/src/isar/config/maps/klab_turtlebot.json +0 -0
  56. {isar-1.11.0 → isar-1.12.0}/src/isar/config/maps/turtleworld.json +0 -0
  57. {isar-1.11.0/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.11.0/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.11.0 → isar-1.12.0}/src/isar/config/predefined_missions/default_turtlebot.json +0 -0
  63. {isar-1.11.0/src/isar/mission_planner → isar-1.12.0/src/isar/config/predefined_poses}/__init__.py +0 -0
  64. {isar-1.11.0 → isar-1.12.0}/src/isar/config/predefined_poses/predefined_poses.py +0 -0
  65. {isar-1.11.0 → isar-1.12.0}/src/isar/config/settings.env +5 -0
  66. {isar-1.11.0 → isar-1.12.0}/src/isar/config/settings.py +15 -3
  67. {isar-1.11.0/src/isar/models → isar-1.12.0/src/isar/mission_planner}/__init__.py +0 -0
  68. {isar-1.11.0 → isar-1.12.0}/src/isar/mission_planner/echo_planner.py +1 -1
  69. {isar-1.11.0 → isar-1.12.0}/src/isar/mission_planner/local_planner.py +0 -0
  70. {isar-1.11.0 → isar-1.12.0}/src/isar/mission_planner/mission_planner_interface.py +0 -0
  71. {isar-1.11.0 → isar-1.12.0}/src/isar/mission_planner/sequential_task_selector.py +0 -0
  72. {isar-1.11.0 → isar-1.12.0}/src/isar/mission_planner/task_selector_interface.py +0 -0
  73. {isar-1.11.0/src/isar/models/communication → isar-1.12.0/src/isar/models}/__init__.py +0 -0
  74. {isar-1.11.0/src/isar/models/mission_metadata → isar-1.12.0/src/isar/models/communication}/__init__.py +0 -0
  75. {isar-1.11.0 → isar-1.12.0}/src/isar/models/communication/message.py +0 -0
  76. {isar-1.11.0 → isar-1.12.0}/src/isar/models/communication/queues/__init__.py +0 -0
  77. {isar-1.11.0 → isar-1.12.0}/src/isar/models/communication/queues/queue_io.py +0 -0
  78. {isar-1.11.0 → isar-1.12.0}/src/isar/models/communication/queues/queue_timeout_error.py +0 -0
  79. {isar-1.11.0 → isar-1.12.0}/src/isar/models/communication/queues/queues.py +0 -0
  80. {isar-1.11.0 → isar-1.12.0}/src/isar/models/communication/queues/status_queue.py +0 -0
  81. {isar-1.11.0 → isar-1.12.0}/src/isar/models/mission/__init__.py +0 -0
  82. {isar-1.11.0 → isar-1.12.0}/src/isar/models/mission/mission.py +0 -0
  83. {isar-1.11.0 → isar-1.12.0}/src/isar/models/mission/status.py +5 -5
  84. {isar-1.11.0/src/isar/services → isar-1.12.0/src/isar/models/mission_metadata}/__init__.py +0 -0
  85. {isar-1.11.0 → isar-1.12.0}/src/isar/models/mission_metadata/mission_metadata.py +2 -0
  86. {isar-1.11.0 → isar-1.12.0}/src/isar/modules.py +3 -2
  87. {isar-1.11.0/src/isar/services/auth → isar-1.12.0/src/isar/services}/__init__.py +0 -0
  88. {isar-1.11.0/src/isar/services/readers → isar-1.12.0/src/isar/services/auth}/__init__.py +0 -0
  89. {isar-1.11.0 → isar-1.12.0}/src/isar/services/auth/azure_credentials.py +0 -0
  90. {isar-1.11.0/src/isar/services/service_connections → isar-1.12.0/src/isar/services/readers}/__init__.py +0 -0
  91. {isar-1.11.0 → isar-1.12.0}/src/isar/services/readers/base_reader.py +0 -0
  92. {isar-1.11.0/src/isar/services/service_connections/mqtt → isar-1.12.0/src/isar/services/service_connections}/__init__.py +0 -0
  93. {isar-1.11.0/src/isar/services/service_connections/stid → isar-1.12.0/src/isar/services/service_connections/mqtt}/__init__.py +0 -0
  94. {isar-1.11.0 → isar-1.12.0}/src/isar/services/service_connections/mqtt/mqtt_client.py +0 -0
  95. {isar-1.11.0 → isar-1.12.0}/src/isar/services/service_connections/mqtt/robot_info_publisher.py +0 -0
  96. {isar-1.11.0 → isar-1.12.0}/src/isar/services/service_connections/mqtt/robot_status_publisher.py +0 -0
  97. {isar-1.11.0 → isar-1.12.0}/src/isar/services/service_connections/request_handler.py +1 -1
  98. {isar-1.11.0/src/isar/services/utilities → isar-1.12.0/src/isar/services/service_connections/stid}/__init__.py +0 -0
  99. {isar-1.11.0 → isar-1.12.0}/src/isar/services/service_connections/stid/stid_service.py +0 -0
  100. {isar-1.11.0/src/isar/state_machine → isar-1.12.0/src/isar/services/utilities}/__init__.py +0 -0
  101. {isar-1.11.0 → isar-1.12.0}/src/isar/services/utilities/queue_utilities.py +0 -0
  102. {isar-1.11.0 → isar-1.12.0}/src/isar/services/utilities/scheduling_utilities.py +0 -0
  103. {isar-1.11.0 → isar-1.12.0}/src/isar/services/utilities/threaded_request.py +0 -0
  104. {isar-1.11.0/src/isar/storage → isar-1.12.0/src/isar/state_machine}/__init__.py +0 -0
  105. {isar-1.11.0 → isar-1.12.0}/src/isar/state_machine/state_machine.py +9 -1
  106. {isar-1.11.0 → isar-1.12.0}/src/isar/state_machine/states/__init__.py +0 -0
  107. {isar-1.11.0 → isar-1.12.0}/src/isar/state_machine/states/idle.py +0 -0
  108. {isar-1.11.0 → isar-1.12.0}/src/isar/state_machine/states/initialize.py +0 -0
  109. {isar-1.11.0 → isar-1.12.0}/src/isar/state_machine/states/initiate_step.py +0 -0
  110. {isar-1.11.0 → isar-1.12.0}/src/isar/state_machine/states/monitor.py +0 -0
  111. {isar-1.11.0 → isar-1.12.0}/src/isar/state_machine/states/off.py +0 -0
  112. {isar-1.11.0 → isar-1.12.0}/src/isar/state_machine/states/paused.py +0 -0
  113. {isar-1.11.0 → isar-1.12.0}/src/isar/state_machine/states/stop_step.py +0 -0
  114. {isar-1.11.0 → isar-1.12.0}/src/isar/state_machine/states_enum.py +0 -0
  115. {isar-1.11.0/src/robot_interface → isar-1.12.0/src/isar/storage}/__init__.py +0 -0
  116. {isar-1.11.0 → isar-1.12.0}/src/isar/storage/blob_storage.py +0 -0
  117. {isar-1.11.0 → isar-1.12.0}/src/isar/storage/local_storage.py +0 -0
  118. isar-1.12.0/src/isar/storage/slimm_storage.py +187 -0
  119. {isar-1.11.0 → isar-1.12.0}/src/isar/storage/storage_interface.py +0 -0
  120. {isar-1.11.0 → isar-1.12.0}/src/isar/storage/uploader.py +0 -0
  121. {isar-1.11.0 → isar-1.12.0}/src/isar/storage/utilities.py +1 -23
  122. {isar-1.11.0 → isar-1.12.0}/src/isar.egg-info/PKG-INFO +1 -1
  123. {isar-1.11.0 → isar-1.12.0}/src/isar.egg-info/SOURCES.txt +3 -0
  124. {isar-1.11.0 → isar-1.12.0}/src/isar.egg-info/dependency_links.txt +0 -0
  125. {isar-1.11.0 → isar-1.12.0}/src/isar.egg-info/requires.txt +3 -0
  126. {isar-1.11.0 → isar-1.12.0}/src/isar.egg-info/top_level.txt +0 -0
  127. {isar-1.11.0/src/robot_interface/models → isar-1.12.0/src/robot_interface}/__init__.py +0 -0
  128. {isar-1.11.0/src/robot_interface/models/robots → isar-1.12.0/src/robot_interface/models}/__init__.py +0 -0
  129. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/models/exceptions/__init__.py +0 -0
  130. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/models/exceptions/robot_exceptions.py +0 -0
  131. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/models/initialize/__init__.py +0 -0
  132. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/models/initialize/initialize_params.py +0 -0
  133. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/models/inspection/__init__.py +0 -0
  134. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/models/inspection/inspection.py +3 -22
  135. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/models/mission/__init__.py +0 -0
  136. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/models/mission/status.py +0 -0
  137. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/models/mission/step.py +4 -30
  138. {isar-1.11.0/src/robot_interface/telemetry → isar-1.12.0/src/robot_interface/models/robots}/__init__.py +0 -0
  139. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/models/robots/robot_model.py +0 -0
  140. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/robot_interface.py +0 -0
  141. {isar-1.11.0/src/robot_interface/utilities → isar-1.12.0/src/robot_interface/telemetry}/__init__.py +0 -0
  142. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/telemetry/mqtt_client.py +0 -0
  143. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/telemetry/payloads.py +0 -0
  144. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/test_robot_interface.py +0 -0
  145. {isar-1.11.0/tests → isar-1.12.0/src/robot_interface/utilities}/__init__.py +0 -0
  146. {isar-1.11.0 → isar-1.12.0}/src/robot_interface/utilities/json_service.py +0 -0
  147. {isar-1.11.0/tests/integration → isar-1.12.0/tests}/__init__.py +0 -0
  148. {isar-1.11.0 → isar-1.12.0}/tests/conftest.py +0 -0
  149. {isar-1.11.0/tests/integration/turtlebot → isar-1.12.0/tests/integration}/__init__.py +0 -0
  150. {isar-1.11.0/tests/integration/turtlebot/config → isar-1.12.0/tests/integration/turtlebot}/__init__.py +0 -0
  151. {isar-1.11.0/tests/integration/turtlebot/config/maps → isar-1.12.0/tests/integration/turtlebot/config}/__init__.py +0 -0
  152. {isar-1.11.0/tests/integration/turtlebot/config/missions → isar-1.12.0/tests/integration/turtlebot/config/maps}/__init__.py +0 -0
  153. {isar-1.11.0 → isar-1.12.0}/tests/integration/turtlebot/config/maps/turtleworld.json +0 -0
  154. {isar-1.11.0/tests/isar → isar-1.12.0/tests/integration/turtlebot/config/missions}/__init__.py +0 -0
  155. {isar-1.11.0 → isar-1.12.0}/tests/integration/turtlebot/config/missions/default.json +0 -0
  156. {isar-1.11.0 → isar-1.12.0}/tests/integration/turtlebot/test_successful_mission.py +0 -0
  157. {isar-1.11.0/tests/isar/apis → isar-1.12.0/tests/isar}/__init__.py +0 -0
  158. {isar-1.11.0/tests/isar/apis/scheduler → isar-1.12.0/tests/isar/apis}/__init__.py +0 -0
  159. {isar-1.11.0/tests/isar/apis/security → isar-1.12.0/tests/isar/apis/scheduler}/__init__.py +0 -0
  160. {isar-1.11.0 → isar-1.12.0}/tests/isar/apis/scheduler/test_scheduler_router.py +0 -0
  161. {isar-1.11.0/tests/isar/models → isar-1.12.0/tests/isar/apis/security}/__init__.py +0 -0
  162. {isar-1.11.0 → isar-1.12.0}/tests/isar/apis/security/test_authentication.py +0 -0
  163. {isar-1.11.0/tests/isar/models/communication → isar-1.12.0/tests/isar/models}/__init__.py +0 -0
  164. {isar-1.11.0/tests/isar/services → isar-1.12.0/tests/isar/models/communication}/__init__.py +0 -0
  165. {isar-1.11.0 → isar-1.12.0}/tests/isar/models/communication/test_queues.py +0 -0
  166. {isar-1.11.0/tests/isar/services/readers → isar-1.12.0/tests/isar/services}/__init__.py +0 -0
  167. {isar-1.11.0/tests/isar/services/service_connections → isar-1.12.0/tests/isar/services/readers}/__init__.py +0 -0
  168. {isar-1.11.0 → isar-1.12.0}/tests/isar/services/readers/test_base_reader.py +0 -0
  169. {isar-1.11.0 → isar-1.12.0}/tests/isar/services/readers/test_mission_reader.py +0 -0
  170. {isar-1.11.0/tests/isar/services/service_connections/echo → isar-1.12.0/tests/isar/services/service_connections}/__init__.py +0 -0
  171. {isar-1.11.0/tests/isar/services/service_connections/stid → isar-1.12.0/tests/isar/services/service_connections/echo}/__init__.py +0 -0
  172. {isar-1.11.0 → isar-1.12.0}/tests/isar/services/service_connections/echo/test_echo_service.py +0 -0
  173. {isar-1.11.0/tests/isar/services/utilities → isar-1.12.0/tests/isar/services/service_connections/stid}/__init__.py +0 -0
  174. {isar-1.11.0 → isar-1.12.0}/tests/isar/services/service_connections/stid/test_stid_service.py +0 -0
  175. {isar-1.11.0 → isar-1.12.0}/tests/isar/services/service_connections/test_base_request_handler.py +0 -0
  176. {isar-1.11.0/tests/isar/state_machine → isar-1.12.0/tests/isar/services/utilities}/__init__.py +0 -0
  177. {isar-1.11.0 → isar-1.12.0}/tests/isar/services/utilities/test_queue_utilities.py +0 -0
  178. {isar-1.11.0 → isar-1.12.0}/tests/isar/services/utilities/test_scheduling_utilities.py +0 -0
  179. {isar-1.11.0/tests/isar/state_machine/states → isar-1.12.0/tests/isar/state_machine}/__init__.py +0 -0
  180. {isar-1.11.0/tests/mocks → isar-1.12.0/tests/isar/state_machine/states}/__init__.py +0 -0
  181. {isar-1.11.0 → isar-1.12.0}/tests/isar/state_machine/states/test_monitor.py +0 -0
  182. {isar-1.11.0 → isar-1.12.0}/tests/isar/state_machine/test_state_machine.py +0 -0
  183. {isar-1.11.0 → isar-1.12.0}/tests/isar/storage/test_blob_storage.py +0 -0
  184. {isar-1.11.0 → isar-1.12.0}/tests/isar/storage/test_uploader.py +0 -0
  185. isar-1.11.0/tests/mocks/task.py → isar-1.12.0/tests/mocks/__init__.py +0 -0
  186. {isar-1.11.0 → isar-1.12.0}/tests/mocks/blob_storage.py +0 -0
  187. {isar-1.11.0 → isar-1.12.0}/tests/mocks/mission_definition.py +8 -3
  188. {isar-1.11.0 → isar-1.12.0}/tests/mocks/mqtt_client.py +0 -0
  189. {isar-1.11.0 → isar-1.12.0}/tests/mocks/pose.py +0 -0
  190. {isar-1.11.0 → isar-1.12.0}/tests/mocks/request.py +0 -0
  191. {isar-1.11.0 → isar-1.12.0}/tests/mocks/robot_interface.py +0 -0
  192. {isar-1.11.0 → isar-1.12.0}/tests/mocks/status.py +0 -0
  193. {isar-1.11.0 → isar-1.12.0}/tests/mocks/step.py +0 -0
  194. isar-1.12.0/tests/mocks/task.py +0 -0
  195. {isar-1.11.0 → isar-1.12.0}/tests/mocks/token.py +0 -0
  196. {isar-1.11.0 → isar-1.12.0}/tests/test_data/test_json_file.json +0 -0
  197. {isar-1.11.0 → isar-1.12.0}/tests/test_data/test_map_config/test_map_config.json +0 -0
  198. {isar-1.11.0 → isar-1.12.0}/tests/test_data/test_mission_not_working.json +0 -0
  199. {isar-1.11.0 → isar-1.12.0}/tests/test_data/test_mission_working.json +0 -0
  200. {isar-1.11.0 → isar-1.12.0}/tests/test_data/test_mission_working_no_tasks.json +0 -0
  201. {isar-1.11.0 → isar-1.12.0}/tests/test_data/test_thermal_image_mission.json +0 -0
  202. {isar-1.11.0 → isar-1.12.0}/tests/test_modules.py +0 -0
  203. isar-1.11.0/src/isar/config/log.py +0 -32
  204. isar-1.11.0/src/isar/config/predefined_missions/default.json +0 -92
  205. isar-1.11.0/src/isar/storage/slimm_storage.py +0 -123
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
File without changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: isar
3
- Version: 1.11.0
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
File without changes
File without changes
File without changes
File without changes
@@ -7,7 +7,8 @@ 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
@@ -26,11 +27,12 @@ from robot_interface.robot_interface import RobotInterface
26
27
  if __name__ == "__main__":
27
28
  load_dotenv()
28
29
 
29
- setup_logger()
30
- logger: Logger = logging.getLogger("main")
31
-
32
30
  injector: Injector = get_injector()
33
31
 
32
+ keyvault_client = injector.get(Keyvault)
33
+ setup_loggers(keyvault=keyvault_client)
34
+ logger: Logger = logging.getLogger("main")
35
+
34
36
  state_machine: StateMachine = injector.get(StateMachine)
35
37
  robot: RobotInterface = injector.get(RobotInterface)
36
38
  queues: Queues = injector.get(Queues)
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,12 +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
43
  self.authenticator: Authenticator = authenticator
29
44
  self.scheduling_controller: SchedulingController = scheduling_controller
45
+ self.keyvault_client: Keyvault = keyvault_client
30
46
  self.host: str = "0.0.0.0" # Locking uvicorn to use 0.0.0.0
31
47
  self.port: int = port
48
+ self.azure_ai_logging_enabled: bool = azure_ai_logging_enabled
32
49
 
33
50
  self.logger: Logger = logging.getLogger("api")
34
51
 
@@ -76,6 +93,9 @@ class API:
76
93
  allow_headers=["*"],
77
94
  )
78
95
 
96
+ if self.azure_ai_logging_enabled:
97
+ self._add_request_logging_middleware(app)
98
+
79
99
  app.include_router(router=self._create_scheduler_router())
80
100
 
81
101
  app.include_router(router=self._create_info_router())
@@ -241,3 +261,36 @@ class API:
241
261
  self.port,
242
262
  extra={"color_message": color_message},
243
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,4 +1,5 @@
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
@@ -9,29 +10,32 @@ from isar.models.mission.mission import Mission, Task
9
10
  from robot_interface.models.mission.step import (
10
11
  STEPS,
11
12
  DriveToPose,
12
- InspectionStep,
13
13
  TakeImage,
14
14
  TakeThermalImage,
15
15
  TakeThermalVideo,
16
16
  TakeVideo,
17
17
  )
18
18
 
19
- inspection_step_types: List[Type[InspectionStep]] = [
20
- TakeImage,
21
- TakeThermalImage,
22
- TakeVideo,
23
- TakeThermalVideo,
24
- ]
19
+
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,12 +51,14 @@ 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
63
  except ValueError as e:
58
64
  raise MissionPlannerError(f"Failed to create task: {str(e)}")
@@ -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
@@ -31,8 +31,8 @@ azure_scheme = SingleTenantAzureAuthorizationCodeBearer(
31
31
 
32
32
  async def validate_has_role(user: User = Depends(azure_scheme)) -> None:
33
33
  """
34
- Validate that a user has the `role` role in order to access the API.
35
- 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.
36
36
  """
37
37
  if settings.REQUIRED_ROLE not in user.roles:
38
38
  raise InvalidAuth(
File without changes
@@ -21,25 +21,33 @@ class Keyvault:
21
21
  client_secret: str = None,
22
22
  tenant_id: str = None,
23
23
  ):
24
+ self.name = keyvault_name
24
25
  self.url = "https://" + keyvault_name + ".vault.azure.net"
25
26
  self.client_id = client_id
26
27
  self.client_secret = client_secret
27
28
  self.tenant_id = tenant_id
28
29
  self.logger = logging.getLogger("API")
30
+ self.client: SecretClient = None
29
31
 
30
32
  def get_secret(self, secret_name: str) -> KeyVaultSecret:
31
33
  secret_client: SecretClient = self.get_secret_client()
32
34
  try:
33
35
  secret: KeyVaultSecret = secret_client.get_secret(name=secret_name)
34
36
  except ResourceNotFoundError:
35
- self.logger.error("Secret was not found in keyvault.")
36
- traceback.print_exc()
37
+ self.logger.error(
38
+ "Secret '%s' was not found in keyvault '%s'.",
39
+ secret_name,
40
+ self.name,
41
+ exc_info=True,
42
+ )
37
43
  raise KeyvaultError # type: ignore
38
44
  except HttpResponseError:
39
45
  self.logger.error(
40
- "An error occurred while retrieving a secret from keyvault."
46
+ "An error occurred while retrieving the secret '%s' from keyvault '%s'.",
47
+ secret_name,
48
+ self.name,
49
+ exc_info=True,
41
50
  )
42
- traceback.print_exc()
43
51
  raise KeyvaultError # type: ignore
44
52
 
45
53
  return secret
@@ -49,25 +57,32 @@ class Keyvault:
49
57
  try:
50
58
  secret_client.set_secret(name=secret_name, value=secret_value)
51
59
  except HttpResponseError:
52
- self.logger.error("An error occurred while setting a secret in keyvault.")
53
- traceback.print_exc()
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
+ )
54
66
  raise KeyvaultError # type: ignore
55
67
 
56
68
  def get_secret_client(self) -> SecretClient:
57
- try:
58
- credential: Union[ClientSecretCredential, DefaultAzureCredential]
59
- if self.client_id and self.client_secret and self.tenant_id:
60
- credential = ClientSecretCredential(
61
- tenant_id=self.tenant_id,
62
- client_id=self.client_id,
63
- client_secret=self.client_secret,
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,
64
84
  )
65
- else:
66
- credential = DefaultAzureCredential()
67
- except ClientAuthenticationError:
68
- self.logger.error("Failed to authenticate to Azure.")
69
- traceback.print_exc()
70
- raise KeyvaultError
85
+ raise KeyvaultError
71
86
 
72
- secret_client = SecretClient(vault_url=self.url, credential=credential)
73
- return secret_client
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
@@ -0,0 +1,98 @@
1
+ {
2
+ "mission_definition": {
3
+ "tasks": [
4
+ {
5
+ "pose": {
6
+ "position": {
7
+ "x": 0,
8
+ "y": 0,
9
+ "z": 0,
10
+ "frame_name": "robot"
11
+ },
12
+ "orientation": {
13
+ "x": 0,
14
+ "y": 0,
15
+ "z": 0,
16
+ "w": 1,
17
+ "frame_name": "robot"
18
+ },
19
+ "frame_name": "robot"
20
+ },
21
+ "tag": "1-A",
22
+ "inspections": [
23
+ {
24
+ "type": "Image",
25
+ "inspection_target": {
26
+ "x": 0,
27
+ "y": 0,
28
+ "z": 0,
29
+ "frame_name": "robot"
30
+ },
31
+ "analysis_types": [
32
+ "CarSeal",
33
+ "Rust"
34
+ ],
35
+ "metadata": {
36
+ "zoom": "2x"
37
+ }
38
+ },
39
+ {
40
+ "type": "ThermalVideo",
41
+ "inspection_target": {
42
+ "x": 0,
43
+ "y": 0,
44
+ "z": 0,
45
+ "frame_name": "robot"
46
+ },
47
+ "analysis_types": [
48
+ "GasDetection"
49
+ ],
50
+ "duration": 10
51
+ }
52
+ ]
53
+ },
54
+ {
55
+ "pose": {
56
+ "position": {
57
+ "x": 1,
58
+ "y": 1,
59
+ "z": 1,
60
+ "frame_name": "robot"
61
+ },
62
+ "orientation": {
63
+ "x": 0,
64
+ "y": 0,
65
+ "z": 0,
66
+ "w": 1,
67
+ "frame_name": "robot"
68
+ },
69
+ "frame_name": "robot"
70
+ },
71
+ "inspections": [
72
+ {
73
+ "type": "ThermalImage",
74
+ "inspection_target": {
75
+ "x": 0,
76
+ "y": 0,
77
+ "z": 0,
78
+ "frame_name": "robot"
79
+ },
80
+ "analysis_types": [
81
+ "ColdSpot",
82
+ "HotSpot"
83
+ ]
84
+ },
85
+ {
86
+ "type": "Video",
87
+ "inspection_target": {
88
+ "x": 0,
89
+ "y": 0,
90
+ "z": 0,
91
+ "frame_name": "robot"
92
+ }
93
+ }
94
+ ]
95
+ }
96
+ ]
97
+ }
98
+ }