KubOS Service Outline

This guide covers an outline for the base schema that should be implemented in all hardware services. Your service can and should implement more mutations and queries beyond those specified in the required base. For general information about hardware services, their role, and how they work, check out the hardware services documentation.

All hardware services must follow the GraphQL spec. All mutation and query responses will return the “data” and/or “errors” fields. The “errors” field will contain all errors encountered while executing the request, including those which are generated by the underlying hardware. See the GraphQL spec for further information on the behavior of these fields. If there is any functionality in the below schema that is unable to be implemented by the service, return an error with the string "Not Implemented".

Queries

The queries in the schema below are intended to give a standard interface for mission applications. Each query listed is used in the automated systems within KubOS to ease the mission development process. Omitting any of the following queries will cause compatibility issues with the rest of the KubOS ecosystem. Adding additional queries is highly encouraged, especially if it will further ease integration with the underlying hardware. For example, a currentPosition query on a GPS service could provide faster access to apps that need it.

type Query {
    # Used for doing regular health checks on the service
    ping(): String
    # Used for aggregating current bus configuration
    config(): String
    # Used for aggregating current bus state
    power(): PowerState
    # Used for automated telemetry collection and distribution
    telemetry(): Telemetry
}

type PowerState {
    state: PowerStateEnum
    uptime: Int
}

type Telemetry {
    # All key value telemetry items for the hardware
    field1: Float
    # field2: whatever type
    # field3: whatever type
    # ...
}

enum PowerStateEnum {
    # Not all of these make sense for every kind of hardware, but implement to the best of your ability.
    ON
    OFF
    RESET
}

Mutations

Mutations are harder to standardize across all hardware, but make your best attempt to fully implement the short list of mutations below. As noted before, any that cannot be implemented must return a response: {"errors": ["Not Implemented"], "data": null}. The only exception to this rule is the noop() mutation, as it is essential for diagnosing hardware state and must be implemented.

type Mutation {
    # When the service receives a noop mutation, it should send a command
    # and make sure it sees the appropriate response from the hardware.
    noop(): Boolean
    controlPower(
        input: ControlPowerInput!
    ): ControlPowerPayload
    # Raw passthrough to the hardware for commands not implemented as mutations directly.
    commandRaw(
        input: CommandRawInput!
    ): IssueRawCommandPayload
}

type ControlPowerPayload {
    power: PowerState
}

input ControlPowerInput {
    state: PowerStateEnum!
}

enum PowerStateEnum {
    # Not all of these make sense for every kind of hardware, but implement to the best of your ability.
    ON
    OFF
    RESET
}

input CommandRawInput {
    # "command" must always be a UTF-8 string. Use "format" to encode as necessary.
    command: String!
    format: FormatEnum!
    # Number of bytes to be read from the hardware as a response.
    # Can be excluded if the hardware does not support it.
    read: Int
}

enum FormatEnum {
    HEX
    STR
}

type IssueRawCommandPayload {
    response: String
    # Format that the response will be in. Use HEX to pass binary data.
    format: FormatEnum
}

commandRaw mutation

Direct hardware commands are often issued in binary format, which GraphQL does not directly support. As a result, we have added the FormatEnum type, which can be used to specify how the input string should be decoded before being passed to the hardware. The HEX format indicates that the input string is already in hexadecimal format. EG: passing a hex string: 74657374636f6d6d616e64, causes the byte array: [0x74, 0x65, 0x73, 0x74, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64] to be passed to the hardware.

The STR format indicates the input string requires no decoding. EG: the string testcommand gets passed to the hardware as the byte array: [0x74, 0x65, 0x73, 0x74, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64].