{
  "asyncapi": "3.1.0",
  "id": "urn:waraps.api-sensors",
  "info": {
    "title": "WARA-PS Sensors MQTT API",
    "version": "1.0.3",
    "description": "### Overview\nSensor data channels for WARA-PS agent telemetry. These channels publish real-time sensor readings from agents at configurable rates.\n\n### Channels\n- **Position** — WGS84 coordinates (latitude, longitude, altitude). Recommended for all moving agents.\n- **Speed** — Speed over ground (m/s). Recommended for moving agents.\n- **Heading** — Heading in degrees relative to north.\n- **Course** — Course over ground in degrees relative to north.\n- **Battery State** — Voltage, current, and charge level. Optional for battery-powered agents.\n- **Energy Level** — Energy as percentage of full. Recommended for all agents.\n- **Waypoints** — Remaining mission waypoints in WGS84 format.\n- **Control System Version** — Software version of the agent's control system.\n- **Cargo** — List of collected cargo items.\n- **Armable** — Whether the agent can be armed.\n- **Mode** — Current operating mode (e.g., GUIDED, MANUAL).\n- **State** — Arming state (e.g., armed, disarmed).\n- **IP Address** — Agent's network address.\n- **Video Server URL** — URL for camera feed restreaming.",
    "contact": {
      "name": "waraps.org",
      "url": "https://portal.waraps.org/",
      "email": "info@waraps.org"
    },
    "license": {
      "name": "Apache 2.0",
      "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
    }
  },
  "defaultContentType": "application/json",
  "servers": {
    "localhost": {
      "host": "localhost:1883",
      "protocol": "mqtt",
      "protocolVersion": "3.1.1+",
      "description": "Development MQTT broker",
      "variables": {
        "port": {
          "enum": [
            "1882",
            "1883"
          ],
          "default": "1883",
          "description": "The port used for connecting to the locally hosted MQTT broker"
        }
      },
      "security": []
    },
    "production": {
      "host": "broker.waraps.org:8883",
      "protocol": "mqtt",
      "protocolVersion": "3.1.1+",
      "description": "Production MQTT broker",
      "variables": {
        "port": {
          "enum": [
            "8883"
          ],
          "default": "8883",
          "description": "The port used for connecting to the production MQTT broker"
        }
      },
      "security": [
        {
          "$ref": "#/components/securitySchemes/tls"
        }
      ]
    }
  },
  "channels": {
    "positionSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/position",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendPositionSensor.message": {
          "$ref": "#/components/messages/PositionSensorMessage"
        }
      },
      "description": "Sends position sensor data. Recommended for all moving agents.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    },
    "speedSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/speed",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendSpeedSensor.message": {
          "$ref": "#/components/messages/SpeedSensorMessage"
        }
      },
      "description": "Sends speed sensor data. Recommended for moving agents.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    },
    "headingSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/heading",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendHeadingSensor.message": {
          "$ref": "#/components/messages/HeadingSensorMessage"
        }
      },
      "description": "Sends heading sensor data. Recommended for moving agents or agents with a direction.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    },
    "courseSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/course",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendCourseSensor.message": {
          "$ref": "#/components/messages/CourseSensorMessage"
        }
      },
      "description": "Sends course sensor data. Recommended for moving agents.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    },
    "batteryStatusSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/battery_status",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendBatteryStatusSensor.message": {
          "$ref": "#/components/messages/BatteryStatusSensorMessage"
        }
      },
      "description": "Sends battery state sensor data. Optional for battery-powered agents.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    },
    "energyLevelSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/energy_level",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendEnergyLevelSensor.message": {
          "$ref": "#/components/messages/EnergyLevelSensorMessage"
        }
      },
      "description": "Sends energy level sensor data. Recommended for all agents.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    },
    "waypointsSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/waypoints",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendWaypointsSensor.message": {
          "$ref": "#/components/messages/WaypointsSensorMessage"
        }
      },
      "description": "Sends remaining waypoints sensor data. Recommended for moving agents.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    },
    "controlSystemVersionSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/control_system_version",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendControlSystemVersionSensor.message": {
          "$ref": "#/components/messages/ControlSystemVersionSensorMessage"
        }
      },
      "description": "Sends control system version sensor data. Optional.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    },
    "cargoSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/cargo",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendCargoSensor.message": {
          "$ref": "#/components/messages/CargoSensorMessage"
        }
      },
      "description": "Sends cargo sensor data. Optional for cargo-holding agents.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    },
    "armableSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/armable",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendArmableSensor.message": {
          "$ref": "#/components/messages/ArmableSensorMessage"
        }
      },
      "description": "Sends armable status sensor data. Recommended for all agents.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    },
    "modeSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/mode",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendModeSensor.message": {
          "$ref": "#/components/messages/ModeSensorMessage"
        }
      },
      "description": "Sends operating mode sensor data. Recommended for all agents.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    },
    "stateSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/state",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendStateSensor.message": {
          "$ref": "#/components/messages/StateSensorMessage"
        }
      },
      "description": "Sends arming state sensor data. Recommended for all agents.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    },
    "ipAddressSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/ip_address",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendIPAddressSensor.message": {
          "$ref": "#/components/messages/IPAddressSensorMessage"
        }
      },
      "description": "Sends IP address sensor data. Optional.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    },
    "videoserverUrlSensorChannel": {
      "address": "{AgentBaseTopic}/sensor/videoserver_url",
      "bindings": {
        "$ref": "#/components/channelBindings/SensorMqttSettings"
      },
      "messages": {
        "sendVideoserverUrlSensor.message": {
          "$ref": "#/components/messages/VideoserverUrlSensorMessage"
        }
      },
      "description": "Sends video server URL sensor data. Required for agents with camera streaming.",
      "parameters": {
        "AgentBaseTopic": {
          "$ref": "#/components/parameters/AgentBaseTopic"
        }
      }
    }
  },
  "operations": {
    "sendPositionSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/positionSensorChannel"
      },
      "summary": "Sends position sensor data",
      "messages": [
        {
          "$ref": "#/channels/positionSensorChannel/messages/sendPositionSensor.message"
        }
      ]
    },
    "sendSpeedSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/speedSensorChannel"
      },
      "summary": "Sends speed sensor data",
      "messages": [
        {
          "$ref": "#/channels/speedSensorChannel/messages/sendSpeedSensor.message"
        }
      ]
    },
    "sendHeadingSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/headingSensorChannel"
      },
      "summary": "Sends heading sensor data",
      "messages": [
        {
          "$ref": "#/channels/headingSensorChannel/messages/sendHeadingSensor.message"
        }
      ]
    },
    "sendCourseSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/courseSensorChannel"
      },
      "summary": "Sends course sensor data",
      "messages": [
        {
          "$ref": "#/channels/courseSensorChannel/messages/sendCourseSensor.message"
        }
      ]
    },
    "sendBatteryStatusSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/batteryStatusSensorChannel"
      },
      "summary": "Sends battery state sensor data",
      "messages": [
        {
          "$ref": "#/channels/batteryStatusSensorChannel/messages/sendBatteryStatusSensor.message"
        }
      ]
    },
    "sendEnergyLevelSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/energyLevelSensorChannel"
      },
      "summary": "Sends energy level sensor data",
      "messages": [
        {
          "$ref": "#/channels/energyLevelSensorChannel/messages/sendEnergyLevelSensor.message"
        }
      ]
    },
    "sendWaypointsSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/waypointsSensorChannel"
      },
      "summary": "Sends waypoints sensor data",
      "messages": [
        {
          "$ref": "#/channels/waypointsSensorChannel/messages/sendWaypointsSensor.message"
        }
      ]
    },
    "sendControlSystemVersionSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/controlSystemVersionSensorChannel"
      },
      "summary": "Sends control system version sensor data",
      "messages": [
        {
          "$ref": "#/channels/controlSystemVersionSensorChannel/messages/sendControlSystemVersionSensor.message"
        }
      ]
    },
    "sendCargoSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/cargoSensorChannel"
      },
      "summary": "Sends cargo sensor data",
      "messages": [
        {
          "$ref": "#/channels/cargoSensorChannel/messages/sendCargoSensor.message"
        }
      ]
    },
    "sendArmableSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/armableSensorChannel"
      },
      "summary": "Sends armable status sensor data",
      "messages": [
        {
          "$ref": "#/channels/armableSensorChannel/messages/sendArmableSensor.message"
        }
      ]
    },
    "sendModeSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/modeSensorChannel"
      },
      "summary": "Sends mode sensor data",
      "messages": [
        {
          "$ref": "#/channels/modeSensorChannel/messages/sendModeSensor.message"
        }
      ]
    },
    "sendStateSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/stateSensorChannel"
      },
      "summary": "Sends state sensor data",
      "messages": [
        {
          "$ref": "#/channels/stateSensorChannel/messages/sendStateSensor.message"
        }
      ]
    },
    "sendIPAddressSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/ipAddressSensorChannel"
      },
      "summary": "Sends IP address sensor data",
      "messages": [
        {
          "$ref": "#/channels/ipAddressSensorChannel/messages/sendIPAddressSensor.message"
        }
      ]
    },
    "sendVideoserverUrlSensor": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/videoserverUrlSensorChannel"
      },
      "summary": "Sends video server URL sensor data",
      "messages": [
        {
          "$ref": "#/channels/videoserverUrlSensorChannel/messages/sendVideoserverUrlSensor.message"
        }
      ]
    }
  },
  "components": {
    "channelBindings": {
      "SensorMqttSettings": {
        "mqtt": {
          "qos": 0,
          "retain": false
        }
      }
    },
    "securitySchemes": {
      "tls": {
        "type": "X509",
        "x-securityScheme": "tls",
        "description": "TLS client certificate for secure connection"
      },
      "apiKeyAuth": {
        "type": "apiKey",
        "in": "user",
        "description": "An API key is required for connecting to the MQTT broker"
      }
    },
    "parameters": {
      "AgentBaseTopic": {
        "description": "Full agent topic path: {organization}/{category}/{domain}/{real_sim}/{agent_name}. See AgentBaseTopic schema for structure.",
        "location": "$message.payload#/name"
      },
      "Organization": {
        "enum": [
          "waraps",
          "saab",
          "liu"
        ],
        "description": "The organization/owner of the agent."
      },
      "Category": {
        "enum": [
          "unit",
          "service",
          "general"
        ],
        "description": "The category of the agent."
      },
      "Domain": {
        "enum": [
          "air",
          "ground",
          "surface",
          "subsurface",
          "space",
          "virtual"
        ],
        "description": "The domain of the agent."
      },
      "RealSim": {
        "enum": [
          "real",
          "simulation"
        ],
        "description": "Indicates if agent is real or simulation"
      },
      "AgentName": {
        "description": "The name/ID of the agent"
      }
    },
    "schemas": {
      "AgentBaseTopic": {
        "description": "Base topic string composed of organization, category, domain, real_sim, agent_name",
        "type": "string",
        "properties": {
          "organization": {
            "enum": [
              "waraps",
              "saab",
              "liu"
            ]
          },
          "category": {
            "enum": [
              "unit",
              "service",
              "general"
            ]
          },
          "domain": {
            "enum": [
              "air",
              "ground",
              "surface",
              "subsurface",
              "space",
              "virtual"
            ]
          },
          "real_sim": {
            "enum": [
              "real",
              "simulation"
            ]
          },
          "agent_name": {
            "type": "string"
          }
        },
        "required": [
          "organization",
          "category",
          "domain",
          "real_sim",
          "agent_name"
        ],
        "example": "waraps/sensor/surface/simulation/SimUSV1",
        "pattern": "{organization}/{category}/{domain}/{real_sim}/{agent_name}"
      },
      "HeadingSensor": {
        "type": "number",
        "example": 137.2,
        "description": "Heading (deg) in relation to north."
      },
      "CourseSensor": {
        "type": "number",
        "example": 147.3,
        "description": "Course (deg) over ground (COG) in relation to north."
      },
      "SpeedSensor": {
        "type": "number",
        "example": 2.5,
        "description": "Speed over ground (SOG) in meters per second (mps)"
      },
      "BatteryStatusSensor": {
        "type": "object",
        "description": "Battery state with voltage, current, and charge information. All fields required.",
        "properties": {
          "voltage": {
            "type": "number",
            "example": 12.6,
            "description": "Voltage (V). Depends on number of cells."
          },
          "current": {
            "type": "number",
            "example": 15.7,
            "description": "Current (A)."
          },
          "charge": {
            "type": "number",
            "example": 85,
            "description": "Energy level (%) of full."
          }
        },
        "required": [
          "voltage",
          "current",
          "charge"
        ]
      },
      "EnergyLevelSensor": {
        "type": "number",
        "example": 85,
        "description": "Energy level, percentage (%) of full."
      },
      "ControlSystemVersionSensor": {
        "type": "string",
        "description": "Version of the control system software running the agent.",
        "example": "APM:Rover-4.5.7"
      },
      "CargoSensor": {
        "type": "array",
        "description": "Array of cargo item identifiers or names.",
        "items": {
          "type": "string",
          "example": "medicin"
        }
      },
      "ArmableSensor": {
        "type": "string",
        "description": "Agent armable status published as string, true if agent can be armed.",
        "example": "true"
      },
      "StateSensor": {
        "type": "string",
        "description": "Agent arming state published as raw string.",
        "example": "armed"
      },
      "ModeSensor": {
        "type": "string",
        "description": "Agent mode published as raw string.",
        "example": "GUIDED"
      },
      "IPAddressSensor": {
        "type": "string",
        "description": "IPv4 or IPv6 address of the agent.",
        "example": "192.168.1.10"
      },
      "VideoserverUrlSensor": {
        "type": "string",
        "description": "Video server streaming URL. All fields required.",
        "example": "wss://ome.waraps.org::3334/app/SimUSV1",
        "required": [
          "ip_address"
        ]
      },
      "GeoPoint": {
        "type": "object",
        "description": "WGS84 geographic point with latitude, longitude, and altitude. Latitude, longitude, and altitude are required; rostype is optional.",
        "properties": {
          "latitude": {
            "$ref": "#/components/schemas/Latitude"
          },
          "longitude": {
            "$ref": "#/components/schemas/Longitude"
          },
          "altitude": {
            "$ref": "#/components/schemas/Altitude"
          },
          "rostype": {
            "type": "string",
            "description": "Optional ROS message type identifier",
            "example": "GeoPoint"
          }
        },
        "required": [
          "latitude",
          "longitude",
          "altitude"
        ]
      },
      "GeoPoints": {
        "type": "array",
        "minItems": 2,
        "description": "An array of WGS84 formatted objects including latitude, longitude and altitude.",
        "items": {
          "$ref": "#/components/schemas/GeoPoint"
        }
      },
      "Latitude": {
        "type": "number",
        "description": "WGS84 latitude, seven or more decimals for centimeter precision.",
        "example": 57.7611363,
        "format": "float"
      },
      "Longitude": {
        "type": "number",
        "description": "WGS84 longitude, seven or more decimals for centimeter precision.",
        "example": 16.6805011,
        "format": "float"
      },
      "Altitude": {
        "type": "number",
        "description": "WGS84 altitude, meters with centimeter precision in relation to ellipsoid.",
        "example": 47.81,
        "format": "float"
      }
    },
    "messages": {
      "PositionSensorMessage": {
        "name": "position",
        "description": "Message containing position sensor data in WGS84 format where altitude is in relation to ellipsoid.",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/GeoPoint"
        }
      },
      "SpeedSensorMessage": {
        "name": "speed",
        "description": "Message containing speed sensor data.",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/SpeedSensor"
        }
      },
      "HeadingSensorMessage": {
        "name": "heading",
        "description": "Message containing heading sensor data.",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/HeadingSensor"
        }
      },
      "CourseSensorMessage": {
        "name": "course",
        "description": "Message containing course sensor data.",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/CourseSensor"
        }
      },
      "BatteryStatusSensorMessage": {
        "name": "battery_status",
        "description": "Message containing battery state sensor data.",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/BatteryStatusSensor"
        }
      },
      "EnergyLevelSensorMessage": {
        "name": "energy_level",
        "description": "Message containing energy level sensor data as a percentage. Independent of power source type.",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/EnergyLevelSensor"
        }
      },
      "WaypointsSensorMessage": {
        "name": "waypoints",
        "description": "Message containing the remaining waypoints of a mission. Waypoints in WGS84 format and altitude over ellipsoid.",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/GeoPoints"
        }
      },
      "ControlSystemVersionSensorMessage": {
        "name": "control_system_version",
        "description": "Message containing control system version data.",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/ControlSystemVersionSensor"
        }
      },
      "CargoSensorMessage": {
        "name": "cargo",
        "description": "Message containing identifications/names of collected cargos.",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/CargoSensor"
        }
      },
      "ArmableSensorMessage": {
        "name": "armable",
        "description": "Message indicating if the agent is armable.",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/ArmableSensor"
        }
      },
      "StateSensorMessage": {
        "name": "state",
        "description": "Message containing the agent's arming state (e.g., armed or disarmed).",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/StateSensor"
        }
      },
      "ModeSensorMessage": {
        "name": "mode",
        "description": "Message containing the agent's current operating mode (e.g., GUIDED, MANUAL, LOITER).",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/ModeSensor"
        }
      },
      "IPAddressSensorMessage": {
        "name": "ip_address",
        "description": "Message containing IP address data.",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/IPAddressSensor"
        }
      },
      "VideoserverUrlSensorMessage": {
        "name": "videoserver_url",
        "description": "Message containing the video server URL for restreaming the agent camera feed.",
        "contentType": "application/json",
        "payload": {
          "$ref": "#/components/schemas/VideoserverUrlSensor"
        }
      }
    }
  }
}
