JaiaBot  1.19.0
JaiaBot micro-AUV software
rest_api.proto
Go to the documentation of this file.
1 syntax = "proto2";
2 
3 import "jaiabot/messages/jaia_dccl.proto";
4 import "jaiabot/messages/hub.proto";
5 import "jaiabot/messages/metadata.proto";
6 import "jaiabot/messages/option_extensions.proto";
7 
8 package jaiabot.protobuf;
9 
10 message TaskPacketsRequest
11 {
12  required uint64 start_time = 1
13  [(jaia.field).rest_api = {
14  presence: GUARANTEED,
15  doc: "Start of time range as a Unix timestamp in microseconds."
16  }];
17  required uint64 end_time = 2
18  [(jaia.field).rest_api = {
19  presence: GUARANTEED,
20  doc: "End of time range as a Unix timestamp in microseconds."
21  }];
22 }
23 
24 message CommandResult
25 {
26  required bool command_sent = 1
27  [(jaia.field).rest_api.presence = GUARANTEED];
28 }
29 
30 enum APIErrorCode
31 {
32  // REST API URL errors
33  API_ERROR__UNSUPPORTED_API_VERSION = 1
34  [(jaia.ev).rest_api.presence = GUARANTEED];
35  API_ERROR__INVALID_ACTION = 2 [(jaia.ev).rest_api.presence = GUARANTEED];
36  API_ERROR__TARGETS_STRING_MALFORMATTED = 3
37  [(jaia.ev).rest_api.presence = GUARANTEED];
38  API_ERROR__ACTION_REQUIRES_JSON_POST_DATA = 4
39  [(jaia.ev).rest_api.presence = GUARANTEED];
40  API_ERROR__INVALID_TARGET = 5 [(jaia.ev).rest_api.presence = GUARANTEED];
41 
42  // Parse errors
43  API_ERROR__COULD_NOT_PARSE_API_REQUEST_JSON = 10
44  [(jaia.ev).rest_api.presence = GUARANTEED];
45 
46  // Missing fields
47  API_ERROR__REQUEST_NOT_INITIALIZED = 11
48  [(jaia.ev).rest_api.presence = GUARANTEED];
49  API_ERROR__NO_ACTION_SPECIFIED = 12
50  [(jaia.ev).rest_api.presence = GUARANTEED];
51 
52  API_ERROR__INVALID_TYPE = 13 [(jaia.ev).rest_api.presence = GUARANTEED];
53 
54  // Unimplemented
55  API_ERROR__NOT_IMPLEMENTED = 20;
56 }
57 
58 message APIError
59 {
60  required APIErrorCode code = 1
61  [(jaia.field).rest_api.presence = GUARANTEED];
62  optional string details = 2 [(jaia.field).rest_api.presence = GUARANTEED];
63 }
64 
65 message APIRequest
66 {
67  message Nodes
68  {
69  repeated int32 hubs = 1 [(jaia.field).rest_api.presence = GUARANTEED];
70  repeated int32 bots = 2 [(jaia.field).rest_api.presence = GUARANTEED];
71  optional bool all = 3
72  [default = false, (jaia.field).rest_api.presence = GUARANTEED];
73  }
74  required Nodes target = 1 [(jaia.field).rest_api.presence = GUARANTEED];
75  optional string api_key = 2 [(jaia.field).rest_api.presence = GUARANTEED];
76 
77  oneof action
78  {
79  bool status = 11 [(jaia.field).rest_api = {
80  presence: GUARANTEED,
81  doc: "Query the status of bots/hubs. Expect a response of type 'status'."
82  example {
83  request: '{"api_key": "4vS6s2jnulxVjrKSB-__tQ", "status": true, "target": {"all": true}}'
84  response: '{"request":{"status":true,"target":{"all":true}},"status":{"bots":[{"attitude":{"course_over_ground":180.0,"heading":166.0,"pitch":85.0,"roll":-57.0},"battery_percent":95.0,"bot_id":1,"bot_type":"HYDRO","calibration_status":3,"depth":0.0,"hdop":0.25,"health_state":"HEALTH__OK","location":{"lat":41.657645,"lon":-71.27212},"mission_state":"PRE_DEPLOYMENT__IDLE","pdop":2.07,"received_time":"1722893284636801","salinity":20.0,"speed":{"over_ground":0.0},"temperature":15.06,"time":"1722878885000000","vcc_voltage":24.0,"wifi_link_quality_percentage":100},{"attitude":{"course_over_ground":180.0,"heading":166.0,"pitch":85.0,"roll":-57.0},"battery_percent":95.0,"bot_id":2,"bot_type":"HYDRO","calibration_status":3,"depth":0.0,"hdop":1.03,"health_state":"HEALTH__OK","location":{"lat":41.65765,"lon":-71.27212},"mission_state":"PRE_DEPLOYMENT__IDLE","pdop":1.47,"received_time":"1722893284635458","salinity":20.0,"speed":{"over_ground":0.0},"temperature":15.04,"time":"1722878885000000","vcc_voltage":24.0,"wifi_link_quality_percentage":100}],"hubs":[{"bot_ids_in_radio_file":[1,2],"fleet_id":0,"health_state":"HEALTH__OK","hub_id":1,"known_bot": [{"id": 1, "last_status_time": "1722893284000000"}, {"id": 2, "last_status_time": "1722893285000000"}],"linux_hardware_status":{"wifi":{"is_connected":true,"link_quality":70,"link_quality_percentage":100,"noise_level":0,"signal_level":33}},"location":{"lat":41.66268,"lon":-71.273018},"received_time":"1722893284552504","time":"8614394422756020"}]},"target":{"bots":[1,2],"hubs":[1]}}'
85  }
86  }];
87  bool metadata = 12 [(jaia.field).rest_api = {
88  presence: GUARANTEED,
89  doc: "Query the metadata of the hub. Expect a response of type 'metadata'."
90  example {
91  request: '{ "target": {"all": true },"metadata": true, "api_key": "4vS6s2jnulxVjrKSB-__tQ"}'
92  response: '{"metadata": {"hubs": [{"goby_version": "3.1.5", "intervehicle_api_version": 7, "is_simulation": true, "ivp_version": "19.8.1+svn9395-10~ubuntu20.04.1", "jaiabot_image_build_date": "Thu Aug 15 16:20:53 UTC 2024", "jaiabot_image_first_boot_date": "Thu Aug 15 13:50:13 UTC 2024", "jaiabot_image_version": "1.12.0~beta2", "jaiabot_version": {"deb_release_branch": "1.y", "deb_repository": "beta", "major": "1", "minor": "12", "patch": "0~beta2"}, "moos_version": "10.4.0", "name": "hub2-fleet6", "raspi_firmware_version": "1.20220331", "xbee_node_id": "Not Available", "xbee_serial_number": "Not Available"}, {"goby_version": "3.1.5", "intervehicle_api_version": 7, "is_simulation": true, "ivp_version": "19.8.1+svn9395-10~ubuntu20.04.1", "jaiabot_image_build_date": "Thu Aug 15 16:20:53 UTC 2024", "jaiabot_image_first_boot_date": "Thu Aug 15 13:50:11 UTC 2024", "jaiabot_image_version": "1.12.0~beta2", "jaiabot_version": {"deb_release_branch": "1.y", "deb_repository": "beta", "major": "1", "minor": "12", "patch": "0~beta2"}, "moos_version": "10.4.0", "name": "hub1-fleet6", "raspi_firmware_version": "1.20220331", "xbee_node_id": "Not Available", "xbee_serial_number": "Not Available"}]}, "request": {"api_key": "", "metadata": true, "target": {"all": true}}, "target": {"hubs": [2, 1]}}'
93  }
94  }];
95  TaskPacketsRequest task_packets = 13 [(jaia.field).rest_api = {
96  presence: GUARANTEED,
97  doc: "Query task packets from a given range of time. Expect a response of type 'task_packets'."
98  example {
99  request: '{"target": {"bots": [1]}, "task_packets": {"start_time": 1722797666581176.0, "end_time": 1722970466581176.0}, "api_key": "4vS6s2jnulxVjrKSB-__tQ"}'
100  response: '{"request": {"api_key": "4vS6s2jnulxVjrKSB-__tQ", "target": {"bots": [1]}, "task_packets": {"end_time": "1722970466581176", "start_time": "1722797666581176"}}, "task_packets": {"packets": [{"bot_id": 1, "drift": {"drift_duration": 10, "end_location": {"lat": 41.658228, "lon": -71.275736}, "estimated_drift": {"heading": 237.0, "speed": 0.9}, "significant_wave_height": 0.0, "start_location": {"lat": 41.658275, "lon": -71.275645}}, "end_time": "1722895675000000", "start_time": "1722895664000000", "type": "SURFACE_DRIFT"}, {"bot_id": 1, "drift": {"drift_duration": 10, "end_location": {"lat": 41.65826, "lon": -71.2757}, "estimated_drift": {"heading": 316.0, "speed": 0.6}, "significant_wave_height": 0.0, "start_location": {"lat": 41.658225, "lon": -71.275651}}, "end_time": "1722896712000000", "start_time": "1722896702000000", "type": "SURFACE_DRIFT"}, {"bot_id": 1, "drift": {"drift_duration": 10, "end_location": {"lat": 41.659469, "lon": -71.272064}, "estimated_drift": {"heading": 72.0, "speed": 0.7}, "significant_wave_height": 0.0, "start_location": {"lat": 41.659448, "lon": -71.272146}}, "end_time": "1722896904000000", "start_time": "1722896893000000", "type": "SURFACE_DRIFT"}]}}'
101  }
102  }];
103  Command command = 14 [(jaia.field).rest_api = {
104  presence: GUARANTEED,
105  doc: "Send a command to one or more bots. Expect a response of type 'command_result'."
106  example {
107  request: '{"target": {"all": true}, "command": {"type": "STOP"}, "api_key": "4vS6s2jnulxVjrKSB-__tQ"}'
108  response: '{"command_result": {"command_sent": true}, "request": {"api_key": "4vS6s2jnulxVjrKSB-__tQ", "command": {"bot_id": 1, "time": "1722895468966813", "type": "STOP"}, "target": {"all": true}}, "target": {"hubs": [1], "bots": [2, 1]}}'
109  }
110  }];
111  CommandForHub command_for_hub = 15 [(jaia.field).rest_api = {
112  presence: GUARANTEED,
113  doc: "Send a command to the hub. Expect a response of type 'command_result'."
114  example {
115  request: '{"target": {"all": true}, "command_for_hub": {"type": "SET_HUB_LOCATION", "hub_location": {"lat": 41.7, "lon": -70.3}}, "api_key": "4vS6s2jnulxVjrKSB-__tQ"}'
116  response: '{"command_result": {"command_sent": true}, "request": {"api_key": "4vS6s2jnulxVjrKSB-__tQ", "command_for_hub": {"hub_id": 1, "hub_location": {"lat": 41.7, "lon": -70.3}, "time": "1722895686821358", "type": "SET_HUB_LOCATION"}, "target": {"all": true}}, "target": {"hubs": [1]}}'
117  }
118  }];
119  }
120 }
121 
122 message APIResponse
123 {
124  message Nodes
125  {
126  repeated int32 hubs = 1 [(jaia.field).rest_api.presence = GUARANTEED];
127  repeated int32 bots = 2 [(jaia.field).rest_api.presence = GUARANTEED];
128  }
129  optional Nodes target = 1 [(jaia.field).rest_api.presence = GUARANTEED];
130  message Statuses
131  {
132  repeated BotStatus bots = 1
133  [(jaia.field).rest_api.presence = GUARANTEED];
134  repeated HubStatus hubs = 2
135  [(jaia.field).rest_api.presence = GUARANTEED];
136  }
137 
138  message Metadatas
139  {
140  repeated DeviceMetadata hubs = 1
141  [(jaia.field).rest_api.presence = GUARANTEED];
142  }
143 
144  message TaskPackets
145  {
146  repeated TaskPacket packets = 1
147  [(jaia.field).rest_api.presence = GUARANTEED];
148  }
149 
150  oneof action
151  {
152  APIError error = 10 [(jaia.field).rest_api = {
153  presence: GUARANTEED,
154  doc: "Error with API Request. This can be sent in response to any failed Request action."
155  }];
156  Statuses status = 11 [(jaia.field).rest_api = {
157  presence: GUARANTEED,
158  doc: "Bot/Hub status. This is sent in response to a successful Request 'status' action."
159  }];
160  Metadatas metadata = 12 [(jaia.field).rest_api = {
161  presence: GUARANTEED,
162  doc: "Metadata response. This is sent in response to a successful Request 'metadata' action."
163  }];
164  TaskPackets task_packets = 13 [(jaia.field).rest_api = {
165  presence: GUARANTEED,
166  doc: "Task packet response. This is sent in response to a successful Request 'task_packet' action."
167  }];
168  CommandResult command_result = 14 [(jaia.field).rest_api = {
169  presence: GUARANTEED,
170  doc: "Command result. This is sent in response to a successful Request 'command' or 'command_for_hub' action."
171  }];
172  }
173 
174  // copy of original request
175  required APIRequest request = 20
176  [(jaia.field).rest_api = { presence: GUARANTEED }];
177 }
178 
179 message APIConfig
180 {
181  message StreamingEndpoint
182  {
183  required int32 hub_id = 1;
184  required string hostname = 2;
185  required int32 port = 3;
186  }
187 
188  repeated StreamingEndpoint streaming_endpoint = 1;
189 
190  optional int32 flask_bind_port = 2 [default = 9092];
191 
192  // set true if no API key is required
193  optional bool no_key_required = 3 [default = false];
194 
195  message APIKey
196  {
197  required string private_key = 1;
198 
199  enum Permission
200  {
201  ALL = 0 [(jaia.ev).rest_api = {
202  permitted_action: [
203  'status',
204  'metadata',
205  'task_packets',
206  'command',
207  'command_for_hub'
208  ]
209  }];
210  READ = 1 [(jaia.ev).rest_api = {
211  permitted_action: [ 'status', 'metadata', 'task_packets' ]
212  }];
213  WRITE = 2 [(jaia.ev).rest_api = {
214  permitted_action: [ 'command', 'command_for_hub' ]
215  }];
216  STATUS = 3
217  [(jaia.ev).rest_api = { permitted_action: [ 'status' ] }];
218  METADATA = 4
219  [(jaia.ev).rest_api = { permitted_action: [ 'metadata' ] }];
220  TASK_PACKETS = 5
221  [(jaia.ev).rest_api = { permitted_action: [ 'task_packets' ] }];
222  COMMAND = 6
223  [(jaia.ev).rest_api = { permitted_action: [ 'command' ] }];
224  COMMAND_FOR_HUB = 7 [
225  (jaia.ev).rest_api = { permitted_action: [ 'command_for_hub' ] }
226  ];
227  }
228 
229  repeated Permission permission = 2;
230  }
231  repeated APIKey key = 4;
232 }