// make sure to be up to date with the version from: upload timeseries

// all fields with optional have a presence bit -> we can check with has_value() if the field is set
// all normal fields are optional anyway in protobuf3 but without the presence bit
// it makes sense to set the presence bit for all fields that are not always set

syntax = "proto3";

message CombinedData {
  uint32 abs_timestamp = 1;
  repeated Device devices = 2;
  repeated GatewayPointLegacy gateway_points_legacy = 3;
  repeated PositionPoint position_points = 4;
  repeated WindPoint wind_points = 5;
  Uplink uplink = 6;
}

message Device {
  // 0: "P2", 1: "P1", 2: "P2pro", 3: "P2proCs", 4: "OLS"
  uint32 type = 1;
  uint32 serial_number = 2;                           // default value 0 is a irregular value
  repeated DevicePoint device_points = 3;
  repeated UiCurve ui_curve = 4; // could be multiple, but will probably be only one from time to time
}

message DevicePoint {
  uint32 timestamp = 1;                               // sec. since abs. time stamp
  optional uint32 device_status = 2;                  // bits
  optional uint32 ldsa = 3;                           // um^2/cm^3 * 100
  optional uint32 average_particle_diameter = 4;      // nm
  optional uint32 particle_number_concentration = 5;  // 1/cm^3
  optional int32 temperature = 6;                     // Celsius
  optional uint32 relative_humidity = 7;              // %
  optional uint32 battery_voltage = 8;                // V * 100
  optional uint32 particle_mass = 9;                  // ug/m^3 * 100
  optional uint32 corona_voltage = 10;                // V
  optional uint32 diffusion_current = 11;             // nA * 100
  optional uint32 deposition_voltage = 12;            // V
  optional uint32 flow = 13;                          // l/min * 1'000
  optional uint32 ambient_pressure = 14;              // hPa * 10
  optional int32 electrometer_offset = 15;            // mV * 10
  optional int32 electrometer_2_offset = 16;          // mV * 10
  optional uint32 electrometer_gain = 17;             // mV * 100
  optional uint32 electrometer_2_gain = 18;           // mV * 100
  optional int32 diffusion_current_offset = 19;       // nA * 100
  optional uint32 particle_number_10nm = 20;          // /cm^3/log(d)
  optional uint32 particle_number_16nm = 21;          // /cm^3/log(d)
  optional uint32 particle_number_26nm = 22;          // /cm^3/log(d)
  optional uint32 particle_number_43nm = 23;          // /cm^3/log(d)
  optional uint32 particle_number_70nm = 24;          // /cm^3/log(d)
  optional uint32 particle_number_114nm = 25;         // /cm^3/log(d)
  optional uint32 particle_number_185nm = 26;         // /cm^3/log(d)
  optional uint32 particle_number_300nm = 27;         // /cm^3/log(d)
  optional uint32 surface = 28;                       // um^2/cm^3 * 100
  optional uint32 sigma_size_dist = 29;               // gsd * 100 (geometric stddev)
  optional uint32 steps_inversion = 30;               // steps
  optional uint32 current_dist_0 = 31;                // mV * 100'000
  optional uint32 current_dist_1 = 32;                // mV * 100'000
  optional uint32 current_dist_2 = 33;                // mV * 100'000
  optional uint32 current_dist_3 = 34;                // mV * 100'000
  optional uint32 current_dist_4 = 35;                // mV * 100'000
  optional uint32 pump_current = 36;                  // mA * 1000
  optional uint32 pump_pwm = 37;                      // %
  optional int32 cs_status = 38;                      // 0=off, 1=on, -1=unknown
  optional int32 diffusion_current_stddev = 39;       // nA * 100
  optional uint32 diffusion_current_delay_on = 40;    // sec * 100
  optional uint32 diffusion_current_delay_off = 41;   // sec * 100
  optional uint32 pump_voltage = 42;                  // V * 100
  optional uint32 differential_pressure = 43;         // Pa * 10
  optional uint32 channel_pressure = 44;              // hPa * 10
  optional uint32 supply_voltage_5V = 45;             // V * 10
  optional uint32 positive_voltage_3V3 = 46;          // V * 10
  optional uint32 negative_voltage_3V3 = 47;          // V * 10
  optional uint32 usb_cc_voltage = 48;                // V * 10
  optional uint32 firmware_version = 49;              // number
}

message UiCurve {
  uint32 timestamp = 1;
  repeated uint32 U_values = 2; // V
  repeated uint32 I_values = 3; // nA * 100
}

message Uplink {
  // 0: "MSOM-Uplink"
  uint32 type = 1;
  uint32 serial_number = 2;                           // default value 0 is a irregular value
  repeated UplinkPoint uplink_points = 3;
}

message UplinkPoint {
  uint32 timestamp = 1;                               // sec. since abs. time stamp
  optional uint32 firmware_version = 2;               // number
  optional uint32 device_status = 3;                  // bits
  optional uint32 cellular_signal = 4;                // %
  optional uint32 battery_int_voltage = 5;            // V * 10
  optional uint32 voltage_in = 6;                     // V * 10
  optional uint32 usb_voltage_out = 7;                // V * 10
  optional uint32 usb_cc_voltage = 8;                 // V * 10
  optional int32 temperature_int = 9;                 // Celsius * 10
  optional uint32 relative_humidity_int = 10;         // %
  optional int32 temperature_ext_1 = 11;              // Celsius * 10
  optional uint32 relative_humidity_ext_1 = 12;       // %
  optional int32 temperature_ext_2 = 13;              // Celsius * 10
  optional uint32 relative_humidity_ext_2 = 14;       // %
  optional uint32 sraw_voc = 15;                      // ticks
  optional uint32 voc_index = 16;                     // 1-500
  optional uint32 ambient_pressure = 17;              // hPa * 10
  optional uint32 co2_ppm_1 = 18;                     // ppm
  optional uint32 co2_ppm_2 = 19;                     // ppm
  optional uint32 pm1_0_mass = 20;                    // ug/m^3 * 10
  optional uint32 pm2_5_mass = 21;                    // ug/m^3 * 10
  optional uint32 pm4_0_mass = 22;                    // ug/m^3 * 10
  optional uint32 pm10_0_mass = 23;                   // ug/m^3 * 10
  optional uint32 water_level_adc_percent = 24;       // adc value 0 ... 100
}

message GatewayPointLegacy {
  optional uint32 timestamp = 1;
  uint32 serial_number = 2;
  uint32 firmware_version = 3;
  uint32 free_memory = 4;
  uint32 free_heap = 5;
  uint32 largest_free_block_heap = 6;
  int32 cellular_signal = 7;
  uint32 battery_int_soc = 8;
  uint32 battery_ext_soc = 9;
  uint32 battery_ext_voltage = 10;
  uint32 charging_ext_voltage = 11;  // solar charging
}

message PositionPoint {
  optional uint32 timestamp = 1;
  float latitude = 2;
  float longitude = 3;
  // maybe use geohash to save space???
}

message WindPoint {
  optional uint32 timestamp = 1;
  optional uint32 wind_speed = 2;
  optional uint32 wind_angle = 3;
}