syntax = "proto3";

package gw;

option go_package = "github.com/chirpstack/chirpstack/api/go/v4/gw";
option java_package = "io.chirpstack.api.gw";
option java_multiple_files = true;
option java_outer_classname = "GatewayProto";

import "chirpstack-api/common/common.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/struct.proto";


enum CodeRate {
    CR_UNDEFINED = 0;
    CR_4_5 = 1;
    CR_4_6 = 2;
    CR_4_7 = 3;
    CR_4_8 = 4;
}

message UplinkFrame {
    // PHYPayload.
    bytes phy_payload = 1;

    // TX meta-data.
    UplinkTxParams tx_params = 2;

    // RX meta-data.
    UplinkRxParams rx_params = 3;
}

message DownlinkFrame {
    // Gateway ID.
    string gateway_id = 1;

    // Downlink ID.
    uint32 downlink_id = 2;

    // Downlink frame items.
    // This makes it possible to send multiple downlink opportunities to the
    // gateway at once (e.g. RX1 and RX2 in LoRaWAN). The first item has the
    // highest priority, the last the lowest. The gateway will emit at most
    // one item.
    repeated DownlinkFrameItem items = 3;
}

message UplinkTxParams {
    // Frequency (Hz).
    uint32 frequency = 1;

    // Modulation.
    Modulation modulation = 2;
}

message Modulation {
    oneof parameters {
        // LoRa.
        LoraModulationParams lora = 1;

        // FSK.
        FskModulationParams fsk = 2;

        // LR-FHSS.
        LrFhssModulationParams lr_fhss = 3;
    }
}

message LoraModulationParams {
    // Bandwidth (Hz).
    uint32 bandwidth = 1;

    // Spreading-factor.
    uint32 spreading_factor = 2;

    // Polarization inversion.
    bool polarization_inversion = 3;

    // Code-rate.
    CodeRate code_rate = 4;
}

message FskModulationParams {
    // Frequency deviation.
    uint32 frequency_deviation = 1;

    // FSK datarate (bits / sec).
    uint32 datarate = 2;
}

message LrFhssModulationParams {
    // Operating channel width (OCW) in Hz.
    uint32 operating_channel_width = 1;

    // Code-rate.
    CodeRate code_rate = 2;

    // Hopping grid number of steps.
    uint32 grid_steps = 3;
}

message UplinkRxParams {
    // Gateway ID (EUI).
    string gateway_id = 1;

    // Uplink ID (UUID).
    uint32 uplink_id = 2;

    // Rx time.
    google.protobuf.Timestamp time = 3;

    // RX time since GPS epoch (only set when the gateway has a GPS module).
    google.protobuf.Duration time_since_gps_epoch = 4;

    // Fine-timestamp.
    // This timestamp can be used for TDOA based geolocation.
    google.protobuf.Duration fine_time_since_gps_epoch = 5;

    // RSSI.
    int32 rssi = 6;

    // SNR.
    // Note: only available for LoRa modulation.
    float snr = 7;

    // Board.
    uint32 board = 8;

    // Antenna.
    uint32 antenna = 9;

    // Location.
    common.Location location = 10;

    // Gateway specific context.
    // This value must be returned to the gateway on (Class-A) downlink.
    bytes context = 11;

    // Properties.
    google.protobuf.Struct properties = 12;
}

message DownlinkFrameItem {
    // PHYPayload.
    bytes phy_payload = 1;

    // Tx parameters.
    DownlinkTxParams tx_params = 2;
}

message DownlinkTxParams {
    // Tx frequency (Hz).
    uint32 frequency = 1;

    // Tx power (dBm).
    int32 power = 2;

    // Modulation.
    Modulation modulation = 3;

    // The board identifier for emitting the frame.
    uint32 board = 4;

    // The antenna identifier for emitting the frame.
    uint32 antenna = 5;

    // Downlink timing.
    DownlinkTiming timing = 6;

    // Gateway specific context.
    // In case of a Class-A downlink, this must contain a copy of the uplink context.
    bytes context = 7;
}

message DownlinkTiming {
    oneof parameters {
        // Immediately timing information.
        DownlinkTimingImmediately immediately = 1;

        // Delay timing information.
        DownlinkTimingDelay delay = 2;

        // GPS epoch timing information.
        DownlinkTimingGpsEpoch gps_epoch = 3;
    }
}

message DownlinkTimingImmediately {
    // No fields implemented yet.
}

message DownlinkTimingDelay {
    // Delay relative to provided context.
    google.protobuf.Duration delay = 1;
}

message DownlinkTimingGpsEpoch {
    // Duration since GPS epoch.
    google.protobuf.Duration time_since_gps_epoch = 1;
}
