// Cisco Spaces Firehose API — Protocol Buffer Schema v2.0
//
// This file defines all event types, messages, and the gRPC service for the
// Cisco Spaces Firehose streaming API. Use it to generate client stubs and
// message classes for your language of choice.
//
// Documentation: see the accompanying Markdown guides in this directory.
//
// Usage:
//   protoc --python_out=. --grpc_python_out=. spaces_firehose_spec_v2.0.proto
//   protoc --java_out=. --grpc-java_out=. spaces_firehose_spec_v2.0.proto
//   protoc --go_out=. --go-grpc_out=. spaces_firehose_spec_v2.0.proto

syntax = "proto3";

package firehose_api_v1;

option java_multiple_files = true;
option java_package = "com.cisco.spaces.firehose.schema.service";
option java_outer_classname = "FirehoseProtos";
option objc_class_prefix = "Spaces";


// ═══════════════════════════════════════════════════════════════════════════
// gRPC Service
// ═══════════════════════════════════════════════════════════════════════════

// Server-streaming RPC. Pass API key as gRPC metadata (key: "x-api-key").
service Firehose {
  rpc GetEvents(EventsStreamRequest) returns (stream EventRecord);
}

// Request message for GetEvents.
message EventsStreamRequest {
  int32 min_partition = 1;  // Start of partition range (1–12). Default: 1.
  int32 max_partition = 2;  // End of partition range (1–12). Default: 12.
  int64 from_timestamp = 3; // Epoch ms to resume from. 0 = latest only.
  int32 replica_id = 4;     // On-prem replica ID. Not applicable for cloud.
}


// ═══════════════════════════════════════════════════════════════════════════
// Event Types
// ═══════════════════════════════════════════════════════════════════════════

enum EventType {
  DEVICE_ENTRY = 0 [deprecated = true]; // Reserved for proto3 zero-value; do not use
  PROFILE_UPDATE = 3;
  LOCATION_CHANGE = 4;
  KEEP_ALIVE = 5;
  APP_ACTIVATION = 6;
  DEVICE_LOCATION_UPDATE = 8;
  DEVICE_RSSI_UPDATE = 11;
  AP_TOPOLOGY_CHANGE = 12;
  DEVICE_PRESENCE = 15;
  USER_PRESENCE = 16;
  IOT_TELEMETRY = 18;
  IOT_USER_ACTION = 19;
  DEVICE_COUNT = 20;
  CAMERA_COUNT = 21;
  RAW_CAMERA_COUNT = 22;
  BLE_RSSI_UPDATE = 23;
  NETWORK_TELEMETRY = 24;
  LOCATION_ANCHOR_UPDATE = 25;
  NETWORK_STATUS_UPDATE = 26;
  WEBEX_TELEMETRY = 27;
  DEVICE_ASSOCIATION = 30;
  SPACE_OCCUPANCY = 31;
  SPACE_OCCUPANCY_CHANGE = 32;
  BUILDING_FEATURE = 33;
  WIFI_DEVICE_UPDATE = 101;
  ASSET_LOCATION_UPDATE = 102;
}


// ═══════════════════════════════════════════════════════════════════════════
// Event Record (top-level message streamed to clients)
// ═══════════════════════════════════════════════════════════════════════════

message EventRecord {
  string record_uid = 1;           // Unique event ID — use for deduplication
  int64 record_timestamp = 2;      // Epoch ms when event was generated
  string spaces_tenant_id = 3;     // Cisco Spaces tenant ID
  string spaces_tenant_name = 4;   // Cisco Spaces tenant display name
  string partner_tenant_id = 5;    // Partner tenant ID
  EventType event_type = 6;        // Event category

  oneof event {
    Device device_profile_update = 10;
    LocationChange location_hierarchy_change = 11;
    DeviceLocation device_location_update = 12;
    AppActivation app_activation = 13;
    DeviceRSSIUpdate device_rssi_update = 16;
    APTopology ap_topology_change = 17;
    DevicePresence device_presence = 20;
    UserPresence user_presence = 21;
    IOTTelemetry iot_telemetry = 23;
    IOTUserAction iot_user_action = 24;
    DeviceCounts device_counts = 25;
    CameraCounts camera_counts = 26;
    RawCameraCounts raw_camera_counts = 27;
    BLERSSIUpdate ble_rssi_update = 28;
    NetworkTelemetry network_telemetry = 29;
    LocationAnchorUpdate location_anchor_update = 30;
    NetworkStatusUpdate network_status_update = 31;
    WebexTelemetryUpdate webex_telemetry_update = 32;
    DeviceAssociation device_association = 35;
    SpaceOccupancy space_occupancy = 36;
    SpaceOccupancyChange space_occupancy_change = 37;
    BuildingFeature building_feature = 38;
    WiFiDeviceUpdate wifi_device_update = 101;
    AssetLocationUpdate asset_location_update = 102;
  }
}


// ═══════════════════════════════════════════════════════════════════════════
// Wi-Fi Events
// ═══════════════════════════════════════════════════════════════════════════

message DeviceLocation {
  Device device = 1;
  Location location = 2;
  string ssid = 3;
  string raw_user_id = 4;
  string visit_id = 5;
  int64 last_seen = 6;
  string device_classification = 7;
  string map_id = 8;
  float x_pos = 9;
  float y_pos = 10;
  double confidence_factor = 11;
  double latitude = 12;
  double longitude = 13;
  float unc = 14;
  int32 max_detected_rssi = 15;
  string ipv4 = 16;
  repeated string ipv6 = 17;
}

message WiFiDeviceUpdate {
  string client_mac = 1;
  Location location = 2;
  int64 last_seen = 3;
  int32 max_detected_rssi = 4;
  string ap_mac = 5;
}

enum DevicePresenceEventType {
  DEVICE_ENTRY_EVENT = 0;
  DEVICE_IN_ACTIVE_EVENT = 1;
  DEVICE_ACTIVE_EVENT = 2;
  DEVICE_EXIT_EVENT = 3;
  DEVICE_SSID_CHANGE_EVENT = 4;
  DEVICE_RAW_USER_ID_CHANGE_EVENT = 5;
}

message DevicePresence {
  DevicePresenceEventType presence_event_type = 1;
  bool was_in_active = 2;
  Device device = 3;
  Location location = 4;
  string ssid = 5;
  string raw_user_id = 6;
  string visit_id = 7;
  int32 days_since_last_visit = 8;
  int64 entry_timestamp = 9;
  string entry_date_time = 10;
  int64 exit_timestamp = 11;
  string exit_date_time = 12;
  int32 visit_duration_minutes = 13;
  string time_zone = 14;
  string device_classification = 15;
  string visit_classification = 16;
  int32 active_devices_count = 17;
  int32 in_active_devices_count = 18;
  OccupancyAnalytics occupancy_analytics = 19;
}

message OccupancyAnalytics {
  OccupancyResult result = 1;                  // Overall result (INCLUDE/EXCLUDE only)
  OccupancyFilterResult ssid = 2;              // SSID filter result
  OccupancyFilterResult manufacturer = 3;      // Manufacturer filter result
  OccupancyFilterResult user_name_pattern = 4; // UserName pattern filter result

  enum OccupancyFilterResult {
    INCLUDE = 0;
    EXCLUDE = 1;
    IMPLICIT_INCLUDE = 2;
    IMPLICIT_EXCLUDE = 3;
  }
}

enum OccupancyResult {
  INCLUDE = 0;
  EXCLUDE = 1;
}

enum UserPresenceEventType {
  USER_ENTRY_EVENT = 0;
  USER_IN_ACTIVE_EVENT = 1;
  USER_ACTIVE_EVENT = 2;
  USER_EXIT_EVENT = 3;
}

message UserPresence {
  UserPresenceEventType presence_event_type = 1;
  bool was_in_active = 2;
  User user = 3;
  Location location = 4;
  string raw_user_id = 5;
  string visit_id = 6;
  int64 entry_timestamp = 7;
  string entry_date_time = 8;
  int64 exit_timestamp = 9;
  string exit_date_time = 10;
  int32 visit_duration_minutes = 11;
  string time_zone = 12;
  UserCount active_users_count = 13;
  UserCount in_active_users_count = 14;
  Connection connection = 15;

  message UserCount {
    int32 users_with_user_id = 1;
    int32 users_without_user_id = 2;
    int32 total_users = 3;
  }
}

enum Connection {
  CONN_WIRELESS = 0;
  CONN_WIRED = 1;
}

message DeviceCounts {
  Location location = 1;
  int64 associated_count = 2;
  int64 estimated_probing_count = 3;
  double probing_randomized_percentage = 4;
  int32 associated_delta = 5;
  int32 probing_delta = 6;
  double estimated_density = 7;
  double estimated_capacity_percentage = 8;
  int32 user_count = 12;
  int32 wireless_user_count = 13;
  int32 wired_user_count = 14;
  int32 rfid_tag_count = 15;
  int32 ble_tag_count = 16;
}

message DeviceAssociation {
  AssociationEvent event = 1;
  Device device = 2;
  Location location = 3;
  string ssid = 4;
  string raw_user_id = 5;
  string ipv4 = 6;
  repeated string ipv6 = 7;
  string device_classification = 8;
  OccupancyAnalytics occupancy_analytics = 9;

  enum AssociationEvent {
    ASSOCIATE = 0;
    DISASSOCIATE = 1;
  }
}

message DeviceRSSIUpdate {
  RSSINotification rssi_notification = 1;
  Location location = 2;

  message RSSINotification {
    string mac_address = 1;
    int32 transmit_power = 2;
    repeated APRSSIMeasurement ap_rssi_measurements = 3;
    repeated CCXTagPayload ccx_tag_payload_list = 4;

    message CCXTagPayload {
      int64 timestamp = 1;
      int32 fragment_number = 2;
      int32 sequence_number = 3;
      bytes data = 4;
    }

    message APRSSIMeasurement {
      string ap_mac_address = 1;
      int32 if_slot_id = 2;
      int32 band_id = 3;
      int32 antenna_id = 4;
      int32 rssi = 5;
      int64 timestamp = 6;
    }
  }
}

message NetworkTelemetry {
  NetworkHealth network_health = 1;
  repeated NetworkPerformance network_performance = 2;
  Location location = 3;

  message NetworkHealth {
    repeated NetworkAvailability network_availability = 1;
    repeated APTelemetry ap_telemetries = 2;

    message NetworkAvailability {
      int32 num_of_tests = 1;
      int32 num_of_success = 2;
      double success_percentage = 3;
      int32 num_of_dns_lookup = 4;
      int32 num_of_dns_lookup_success = 5;
      double dns_lookup_success_percentage = 6;
      string band = 7;
    }

    message APTelemetry {
      APTelemetryType ap_telemetry_type = 1;
      double average = 2;
      int32 min = 3;
      int32 max = 4;
    }

    enum APTelemetryType {
      NONE = 0;
      CLIENTS_PER_AP = 1;
      SNR = 2;
      CHANNEL_UTILIZATION = 3;
      RSSI = 4;
    }
  }

  message NetworkPerformance {
    double avg_upload_bandwidth_mbps = 1;
    double avg_download_bandwidth_mbps = 2;
    double avg_packet_loss_percentage = 3;
    int32 avg_rtt_ms = 4;
    int32 avg_dns_lookup_time_ms = 5;
    string band = 6;
    double jitter = 7;
    double mos = 8;
  }
}

message NetworkStatusUpdate {
  NetworkDeviceType device_type = 1;
  NetworkDeviceStatus status = 2;
  int64 last_heard = 3;

  oneof device {
    ConnectorInfo connector_info = 4;
    ControllerInfo controller_info = 5;
  }

  enum NetworkDeviceType {
    NDT_UNKNOWN = 0;
    NDT_CONNECTOR = 1;
    NDT_CONTROLLER = 2;
  }

  enum NetworkDeviceStatus {
    NDS_UNKNOWN = 0;
    NDS_CONNECTED = 1;
    NDS_DISCONNECTED = 2;
    NDS_ACTIVE = 3;
    NDS_INACTIVE = 4;
  }

  message ConnectorInfo {
    string id = 1;
    string name = 2;
    string ip_address = 3;
    string ova_version = 4;
    string docker_version = 5;
  }

  message ControllerInfo {
    string id = 1;
    string name = 2;
    string ip_address = 3;
    string version = 4;
    string connector_id = 5;
    string connector_name = 6;
    string type = 7;
  }
}


// ═══════════════════════════════════════════════════════════════════════════
// IoT Events
// ═══════════════════════════════════════════════════════════════════════════

enum IOTDeviceType {
  IOT_DEVICE_UNKNOWN = 0;
  IOT_BLE_DEVICE = 1;
  IOT_RFID_TAG = 2;
  IOT_ZIGBEE_DEVICE = 3;
  IOT_WIRED_DEVICE = 4;
  IOT_TELE_PRESENCE_DEVICE = 5;
  IOT_AP_SENSOR = 6;
  IOT_MT_SENSOR = 7;
  IOT_UWB_TAG = 8;
}

enum IOTActionType {
  IOT_ACTION_UNKNOWN = 0;
  IOT_ACTION_DOUBLE_TAP = 1;
  IOT_ACTION_BUTTON_CLICK = 2;
}

message DeviceInfo {
  IOTDeviceType device_type = 1;
  string device_id = 2;
  string device_mac_address = 3;
  repeated string group = 4;
  string device_name = 5;
  string firmware_version = 6;
  string raw_device_id = 7;
  string manufacturer = 8;
  string company_id = 9;
  string service_uuid = 10;
  string label = 11;
  string vendor_id = 12;
  string device_model = 13;
}

message DevicePosition {
  float x_pos = 1;
  float y_pos = 2;
  double latitude = 3;
  double longitude = 4;
  double confidence_factor = 5;
  string map_id = 6;
  string location_id = 7;
  int64 last_located_time = 8;
  ComputeType compute_type = 9;
}

enum ComputeType {
  CT_UNKNOWN = 0;
  CT_RSSI = 1;
  CT_TDOA = 2;
}

message IOTTelemetry {
  DeviceInfo device_info = 1;
  DevicePosition detected_position = 2;
  DevicePosition placed_position = 3;
  Location location = 4;
  Temperature temperature = 5;
  Accelerometer accelerometer = 6;
  Illuminance illuminance = 7;
  int64 device_rtc_time = 8;
  Battery battery = 10;
  LastUserAction last_user_action = 11;
  iBeacon i_beacon = 12;
  Eddystone eddy_stone = 13;
  int32 raw_header = 14;
  bytes raw_payload = 15;
  int32 sequence_num = 16;
  PIRTrigger pir_trigger = 17;
  AirPressure air_pressure = 18;
  VendorInfo vendor_info = 19;
  CCXData ccx_data = 20;
  TPData tp_data = 21;
  Humidity humidity = 22;
  AirQuality air_quality = 23;
  CarbonEmissions carbon_emissions = 24;
  AmbientLight ambient_light = 25;
  Voltage voltage = 26;
  IllumSolarCell illum_solar_cell = 27;
  IllumSensor illum_sensor = 28;
  OccupancyStatus occupancy_status = 29;
  MagnetContact magnet_contact = 30;
  int32 max_detected_rssi = 31;
  PushButton push_button = 32;
  IndoorAirQuality indoor_air_quality = 33;
  TVOC tvoc = 34;
  AmbientNoise ambient_noise = 35;
  repeated DevicePosition all_computed_positions = 37;
  MassConcentration mass_concentration = 38;

  message IndoorAirQuality { float air_quality_index = 1; }
  message TVOC { int32 value_in_ppb = 2; }
  message PushButton {
    PushButtonAction action = 1;
    repeated string action_button_labels = 2;
  }
  enum PushButtonAction { PBA_PRESS = 0; PBA_RELEASE = 1; }
  message TPData {
    bool presence = 1;
    int64 people_count = 2;
    int32 standby_state = 3;
    int32 ambient_noise = 4;
    int32 dryness_score = 5;
    int32 active_calls = 6;
    int32 presentation_state = 7;
    int64 time_stamp = 8;
    float air_quality_index = 9;
    float temperature_in_celsius = 10;
    int32 humidity_in_percentage = 11;
    int32 sound_level = 12;
    string ambient_light = 13;
    int32 reverberation_time = 14;
    bool close_proximity = 15;
    string air_quality_status = 16;
  }
  message Humidity { int32 humidity_in_percentage = 1; int32 raw_humidity = 2; }
  message AirQuality { float air_quality_index = 1; int32 air_quality_ppb = 2; string air_quality_status = 20; }
  message CarbonEmissions { int32 co2_ppm = 1; }
  message AmbientLight { int32 value_lx = 1; }
  message AmbientNoise { int32 value = 1; }
  message PIRTrigger { int64 timestamp = 1; }
  message AirPressure { float pressure = 1; }
  message VendorInfo { int32 manufacturer_id = 1; }
  message Voltage { float value_mv = 1; }
  message IllumSolarCell { int32 value_lx = 1; }
  message IllumSensor { int32 value_lx = 1; }
  message OccupancyStatus {
    Status status = 1;
    enum Status { OCCUPIED = 0; NOT_OCCUPIED = 1; }
  }
  message MagnetContact {
    ContactType contact_type = 1;
    enum ContactType { OPEN = 0; CLOSED = 1; }
  }
  message iBeacon {
    string beacon_mac_address = 1;
    string uuid = 2;
    int32 major = 3;
    int32 minor = 4;
    int32 advertized_tx_power = 5;
  }
  message Eddystone {
    string beacon_mac_address = 1;
    oneof frame { string uid = 2; string namespace = 3; string url = 4; }
  }
  message Temperature { double temperature_in_celsius = 1; double raw_temperature = 2; }
  message Illuminance {
    double value = 1;
    IlluminanceUnit unit = 2;
    enum IlluminanceUnit { PERCENTAGE = 0; LUX = 1; }
  }
  message Battery {
    float value = 1;
    BatteryUnit unit = 2;
    int64 last_retrieved = 15;
    enum BatteryUnit { PERCENTAGE = 0; MILLI_VOLTS = 1; }
  }
  message Accelerometer { double x = 1; double y = 2; double z = 3; int64 last_movement_timestamp = 4; int32 counter = 5; }
  message LastUserAction { IOTActionType type = 1; int64 timestamp = 2; }
  message MassConcentration {
    MassConcentrationType type = 1;
    int32 value = 2;
    string unit = 3;
    enum MassConcentrationType { MCT_PM_2_5 = 0; MCT_PM_10 = 1; }
  }
}

message CCXData {
  repeated Telemetry telemetries = 1;
  Battery battery = 2;
  Vendor vendor = 3;
  int64 last_beacon_time = 4;
  int32 last_beacon_sequence_number = 5;

  message Telemetry {
    CCXTelemetryType type = 1;
    string unit = 2;
    string value = 3;
    int64 last_received_time = 4;
    int32 last_received_seq_num = 5;
    enum CCXTelemetryType {
      CCX_TELEMETRY_TEMPERATURE = 0;
      CCX_TELEMETRY_HUMIDITY = 1;
      CCX_TELEMETRY_GPS = 2;
      CCX_TELEMETRY_MOTION = 3;
      CCX_TELEMETRY_DISTANCE = 4;
      CCX_TELEMETRY_FUEL = 5;
      CCX_TELEMETRY_QUANTITY = 6;
      CCX_TELEMETRY_PRESSURE = 7;
      CCX_TELEMETRY_STATUS = 8;
      CCX_TELEMETRY_EPC = 9;
      CCX_TELEMETRY_MOTIONPROB = 10;
      CCX_TELEMETRY_UNKNOWN = 11;
    }
  }
  message Battery {
    int32 tolerance = 1;
    int32 percent_remaining = 2;
    int32 days_remaining = 3;
    int64 age = 4;
    int64 last_received_time = 5;
    int32 last_received_seq_num = 6;
  }
  message Vendor {
    int32 id = 1;
    int32 element_id = 2;
    bytes data = 3;
    int64 last_received_time = 4;
    int32 last_received_seq_num = 5;
  }
}

message IOTUserAction {
  DeviceInfo device_info = 1;
  DevicePosition detected_position = 2;
  DevicePosition placed_position = 3;
  Location location = 4;
  IOTActionType action_type = 5;
  int32 action_count = 6;
  int64 action_timestamp = 7;
  int64 action_id = 8;
  repeated DevicePosition all_computed_positions = 10;
}

message BLERSSIUpdate {
  BLERSSINotification rssi_notification = 1;
  Location location = 2;

  message BLERSSINotification {
    string mac_address = 1;
    repeated APRSSIMeasurement ap_rssi_measurements = 2;
    BLEPayload ble_payload = 3;
    repeated string group = 4;

    message APRSSIMeasurement {
      string ap_mac_address = 1;
      int32 if_slot_id = 2;
      int32 band_id = 3;
      int32 antenna_id = 4;
      int32 rssi = 5;
      int64 timestamp = 6;
    }

    message BLEPayload {
      int64 timestamp = 1;
      bytes data = 2;
    }
  }
}


// ═══════════════════════════════════════════════════════════════════════════
// Camera Events
// ═══════════════════════════════════════════════════════════════════════════

message CameraCounts {
  Location location = 1;
  int64 count = 4;
  int64 count_delta = 5;
}

message RawCameraCounts {
  Location location = 1;
  string camera_id = 2;
  string camera_zone_id = 3;
  int64 count = 4;
}


// ═══════════════════════════════════════════════════════════════════════════
// Webex Events
// ═══════════════════════════════════════════════════════════════════════════

message WebexTelemetryUpdate {
  WebexDeviceInfo device_info = 1;
  Location location = 2;
  repeated WebexTelemetry telemetries = 3;

  message WebexDeviceInfo {
    string device_id = 1;
    string mac_address = 2;
    string ip_address = 3;
    string product = 4;
    string display_name = 5;
    string serial_number = 6;
    string software_version = 7;
    string workspace_id = 8;
    string org_id = 9;
  }

  message WebexTelemetry {
    oneof telemetry {
      int32 people_count = 1;
      bool presence = 2;
      int32 stand_by_state = 3;
      int32 ambient_noise = 4;
      int32 sound_level = 5;
      float air_quality = 6;
      string air_quality_status = 7;
      float ambient_temp = 8;
      int32 relative_humidity = 9;
      string ambient_light = 10;
      int32 reverberation_time = 11;
      bool close_proximity = 12;
      int32 active_calls = 13;
      int32 presentation_state = 14;
    }
  }
}


// ═══════════════════════════════════════════════════════════════════════════
// Location & Topology Events
// ═══════════════════════════════════════════════════════════════════════════

enum ChangeType {
  ADD = 0;
  REMOVE = 1;
  MOVE = 2;
  UPDATE = 3;
}

message LocationChange {
  ChangeType change_type = 1;
  Location location = 2;
  LocationDetails location_details = 3;
}

message LocationAnchorUpdate {
  UpdateType change_type = 1;
  Location location = 2;
  LocationAnchorInfo location_anchor_info = 3;

  enum UpdateType {
    ADD_UPDATE = 0;
    DELETE = 1;
  }
}

message LocationAnchorInfo {
  string identifier = 1;
  string uuid = 2;
  int32 major = 3;
  int32 minor = 4;
  int32 tx_power = 5;
  int32 adv_tx_power = 6;
  int32 frequency = 7;
  string x_pos = 8;
  string y_pos = 9;
  string z_pos = 10;
  double latitude = 11;
  double longitude = 12;
  string map_id = 13;
}

message APTopology {
  Location location = 1;
  Dimension dimension = 2;
  MapDetails map_details = 3;
  repeated Obstacle obstacles = 4;
  repeated AccessPoint access_points = 5;
  string aes_id = 6;
  int32 floor_number = 7;

  message Obstacle {
    ObstacleType type = 1;
    int32 attenuation = 2;
    repeated MapCoordinate map_coordinates = 3;
  }

  enum ObstacleType {
    OBSTACLE_TYPE_UNKNOWN = 0;
    OBSTACLE_TYPE_THICK_WALL = 1;
    OBSTACLE_TYPE_NORMAL_WALL = 2;
    OBSTACLE_TYPE_THICK_DOOR = 3;
    OBSTACLE_TYPE_NORMAL_DOOR = 4;
    OBSTACLE_TYPE_CUBICLE = 5;
    OBSTACLE_TYPE_GLASS = 6;
  }

  message AccessPoint {
    double angle_radians = 1;
    ApType ap_type = 2;
    string switch_name = 3;
    string name = 4;
    string radio_mac_address = 5;
    string eth_mac_address = 6;
    string ip_address = 7;
    int32 num_of_slots = 8;
    MapCoordinate map_coordinate = 9;
    ApMode ap_mode = 10;
    repeated ApInterface ap_interfaces = 11;
    string aes_id = 12;
  }

  enum ApType {
    AP_TYPE_OTHER = 0;
    AP_TYPE_5212 = 1;
    AP_TYPE_5312 = 2;
    AP_TYPE_MIMO = 3;
    AP_TYPE_UNKNOWN = 4;
    AP_TYPE_1100 = 5;
    AP_TYPE_1130 = 6;
    AP_TYPE_1240 = 7;
    AP_TYPE_1200 = 8;
    AP_TYPE_1310 = 9;
    AP_TYPE_1500 = 10;
    AP_TYPE_3502I = 18;
    AP_TYPE_3502E = 19;
    AP_TYPE_1552 = 22;
    AP_TYPE_HALO = 999;
  }

  enum ApMode {
    AP_MODE_LOCAL = 0;
    AP_MODE_MONITOR = 1;
    AP_MODE_REAP = 2;
    AP_MODE_ROGUE_DETECTOR = 3;
    AP_MODE_SNIFFER = 4;
    AP_MODE_BRIDGE = 5;
  }

  enum Band {
    BAND_UNKNOWN = 0;
    BAND_IEEE_802_11_A = 1;
    BAND_IEEE_802_11_B = 2;
  }

  message MapCoordinate {
    double x = 1;
    double y = 2;
    double z = 3;
  }

  message ApInterface {
    Band band = 1;
    int32 slot_number = 2;
    int32 channel_assignment = 3;
    int32 channel_number = 4;
    int32 tx_power_level = 5;
    string antenna_pattern = 6;
    double antenna_angle_radians = 7;
    double antenna_elev_angle_radians = 8;
    int32 antenna_gain = 9;
    int32 antenna_diversity = 10;
    AntennaMode antenna_mode = 11;
    int32 antenna_type = 12;
    int32 tx_power_control = 13;
    bool dual_band_slot = 14;
  }

  enum AntennaMode {
    ANTENNA_MODE_OTHER = 0;
    ANTENNA_MODE_SECTOR_A = 1;
    ANTENNA_MODE_SECTOR_B = 2;
    ANTENNA_MODE_OMNI = 3;
  }
}

message NetworkTopology {
  string spaces_tenant_id = 1;
  string spaces_tenant_name = 2;
  string partner_tenant_id = 3;
  repeated APTopology ap_topology_list = 4;
  repeated ErrorTopology error_ap_topology_list = 5;
}

message ErrorTopology {
  Location location = 1;
  string aes_id = 2;
  int32 floor_number = 3;
  string error_code = 4;
  string error_description = 5;
}


// ═══════════════════════════════════════════════════════════════════════════
// Occupancy Events
// ═══════════════════════════════════════════════════════════════════════════

message SpaceOccupancy {
  Location location = 1;
  Space space = 2;
  int64 window_start_timestamp = 3;
  string window_start_date_time = 4;
  string time_zone = 5;
  int32 peak_people_count = 7;
  bool people_presence = 8;
  bool booking_status = 9;
}

message SpaceOccupancyChange {
  Location location = 1;
  Space space = 2;
  int32 people_count = 4;
  bool people_presence = 5;
  bool booking_status = 6;
}

message Space {
  string id = 1;
  string name = 2;
  string floor_id = 3;
  LegacySpaceType type = 4 [deprecated = true];
  SpaceType space_type = 5;
  int32 capacity = 6;
  OccupancyType occupancy_type = 7;

  enum LegacySpaceType { OTHER = 0; ROOM = 1; WORK_STATION = 2; }
  enum OccupancyType { NONE = 0; PRESENCE = 1; PEOPLE_COUNT = 2; BOTH = 3; }
}

message SpaceType {
  bool is_private = 1;
  Type type = 2;

  oneof sub_type {
    MeetingRoom meeting_room = 10;
    Clinical clinical = 11;
    Amenity amenity = 13;
  }

  enum Type { UNKNOWN = 0; MEETING_ROOM = 1; WORK_STATION = 2; AMENITY = 3; CLINICAL = 20; }
  enum MeetingRoom { MR_MEETING_ROOM = 0; }
  enum Amenity { AMN_OTHER = 0; AMN_HELP_DESK = 1; AMN_INFORMATION_KIOSK = 2; AMN_CHILD_CARE = 3; AMN_MOTHERS_ROOM = 4; AMN_RECEPTION = 5; AMN_WAITING_AREA = 7; }
  enum Clinical { CL_OTHER = 0; CL_CONSULTATION_ROOM = 1; CL_PATIENT_ROOM = 2; CL_EXAMINATION_ROOM = 4; CL_TREATMENT_ROOM = 5; CL_PREPARATION_ROOM = 6; CL_LABORATORY = 8; CL_PHARMACY = 9; CL_EMERGENCY = 10; CL_IMAGING = 11; CL_BLOOD_DRAW = 12; CL_NURSE_STATION = 13; }
}

message BuildingFeature {
  ChangeType change_type = 1;
  string id = 2;
  string fid = 3;
  string name = 4;
  Location location = 5;
  string map_source_reference = 6;
  double area_sq_ft = 7;
  repeated Point points = 8;
  SpaceType space_type = 9;

  message Point { double lng = 1; double lat = 2; }
}


// ═══════════════════════════════════════════════════════════════════════════
// Asset Location Events
// ═══════════════════════════════════════════════════════════════════════════

message AssetInfo {
  AssetIdType id_type = 1;
  string id = 2;
  repeated string labels = 3;
  string category = 4;
  string department = 5;
  repeated AssetAttribute attributes = 6;
  AssetStatus status = 7;

  message AssetAttribute {
    string name = 1;
    string value = 2;
  }

  enum AssetIdType {
    AIT_UNKNOWN = 0;
    AIT_INTERNALLY_ASSIGNED = 1;
    AIT_EXTERNALLY_PROVIDED = 2;
  }

  enum AssetStatus {
    AS_UNSPECIFIED = 0;
    AS_IN_MOVE = 1;
    AS_AVAILABLE = 2;
    AS_OUT_OF_ORDER = 3;
  }
}

message AssetLocatorDeviceInfo {
  ALDeviceType type = 1;
  string mac_address = 2;
  string vendor_id = 3;
  string model = 4;

  enum ALDeviceType {
    ALDT_UNSPECIFIED = 0;
    ALDT_BLE = 1;
    ALDT_RFID = 2;
    ALDT_UWB = 3;
    ALDT_WIFI_CLIENT = 4;
  }
}

message AssetLocationUpdate {
  AssetInfo asset_info = 1;
  AssetLocatorDeviceInfo asset_locator_device_info = 2;
  DevicePosition position = 3;
  Location location = 4;
  repeated DevicePosition all_computed_positions = 5;
}


// ═══════════════════════════════════════════════════════════════════════════
// Activation Events
// ═══════════════════════════════════════════════════════════════════════════

message AppActivation {
  string spaces_tenant_name = 1;
  string spaces_tenant_id = 2;
  string partner_tenant_id = 3;
  string name = 4;
  string reference_id = 5;
  string instance_name = 6;
  repeated string mac_filters = 7;
  repeated string iot_groups = 8;
  string app_id = 9;
  string region = 10;
}


// ═══════════════════════════════════════════════════════════════════════════
// Common / Shared Messages
// ═══════════════════════════════════════════════════════════════════════════

message Location {
  string location_id = 1;
  string name = 2;
  repeated string inferred_location_types = 3;
  Location parent = 4;
  string source_location_id = 5;
  int32 floor_number = 6;
  int32 ap_count = 7;
}

message LocationDetails {
  string time_zone = 3;
  string city = 4;
  string state = 5;
  string country = 6;
  string category = 7;
  repeated Metadata metadata = 8;
  double latitude = 9;
  double longitude = 10;
  MapDetails map_details = 11;

  message Metadata {
    string key = 1;
    repeated string values = 2;
  }
}

message Dimension {
  float length = 1;
  float width = 2;
  float height = 3;
  float offset_x = 4;
  float offset_y = 5;
}

message MapDetails {
  string map_id = 1;
  int32 image_width = 2;
  int32 image_height = 3;
  string mime_type = 4;
  Dimension dimension = 5;
}

enum DeviceType {
  NOT_AVAILABLE = 0;
  MOBILE = 1;
  TABLET = 2;
  LAPTOP = 3;
  OTHER_DEVICE = 4;
}

message Device {
  string device_id = 1;
  string user_id = 2;
  repeated string tags = 3;
  string mobile = 4;
  string email = 5;
  Gender gender = 6;
  string first_name = 7;
  string last_name = 8;
  string postal_code = 9;
  repeated OptIn opt_ins = 10;
  repeated Attribute attributes = 11;
  string mac_address = 12;
  string manufacturer = 13;
  string os = 14;
  string os_version = 15;
  DeviceType type = 16;
  repeated SocialNetworkInfo social_network_info = 17;
  string device_model = 18;
  DHCPProfileInfo dhcp_profile_info = 19;
  string open_roaming_user_id = 20;

  enum OptIn { MOBILE_NUMBER = 0; EMAIL = 1; TERMS_AND_CONDITIONS = 2; }

  message DHCPProfileInfo {
    string dc_profile_name = 1;
    string dc_device_class_tag = 2;
    string dc_certainty_metric = 3;
    string dc_protocol_map = 4;
  }
}

message User {
  string user_id = 1;
  repeated string device_ids = 2;
  repeated string tags = 3;
  string mobile = 4;
  string email = 5;
  Gender gender = 6;
  string first_name = 7;
  string last_name = 8;
  string postal_code = 9;
  repeated Attribute attributes = 10;
  repeated SocialNetworkInfo social_network_info = 11;
  string open_roaming_user_id = 12;
}

enum Gender {
  GENDER_NOT_AVAILABLE = 0;
  MALE = 1;
  FEMALE = 2;
  OTHER = 3;
}

message Attribute {
  string name = 1;
  repeated string values = 2;
}

message SocialNetworkInfo {
  SocialNetwork social_network = 1;
  string social_handle = 2;
  oneof social_info {
    Facebook facebook = 3;
    Twitter twitter = 4;
    LinkedIn linked_in = 5;
  }
}

enum SocialNetwork {
  FACEBOOK = 0;
  TWITTER = 1;
  LINKEDIN = 2;
}

message Facebook {
  string id = 1;
  string first_name = 2;
  string last_name = 3;
  string middle_name = 4;
  string name = 5;
  string short_name = 6;
  string name_format = 7;
  string picture = 8;
  string email = 9;
  repeated Attribute attributes = 101;
}

message Twitter {
  string id = 1;
  string name = 2;
  string screen_name = 3;
  int32 friends_count = 4;
  int32 followers_count = 5;
  string profile_image_url = 6;
  string profile_banner_url = 7;
  string location = 8;
  int32 statuses_count = 9;
  string email = 10;
  bool profile_verified = 11;
  string utc_offset = 12;
  string time_zone = 13;
  bool geo_enabled = 14;
  string lang = 15;
  repeated Attribute attributes = 101;
}

message LinkedIn {
  string id = 1;
  string first_name = 2;
  string last_name = 3;
  string profile_picture = 4;
  string email = 5;
  repeated Attribute attributes = 101;
}

message MobileInfo {
  string number = 1;
  bool verified = 2;
  bool opted_in = 3;
}

message EmailInfo {
  string address = 1;
  bool verified = 2;
  bool opted_in = 3;
}


// ═══════════════════════════════════════════════════════════════════════════
// Supporting API Messages
// ═══════════════════════════════════════════════════════════════════════════

message LocationInfoRequest {
  string location_id = 1;
  string partner_tenant_id = 2;
}

message LocationInfo {
  Location location = 2;
  LocationDetails location_details = 3;
}

message FloorMapRequest {
  string map_id = 1;
  string partner_tenant_id = 2;
}

message FloorMap {
  MapDetails map_details = 1;
  bytes image_data = 2;
}

message EventFiltersRequest {
  string partner_tenant_id = 1;
  repeated string mac_filters = 2;
  repeated IBeaconFilter i_beacon_filters = 3;
  repeated EddystoneFilter eddystone_filters = 4;
  repeated string mac_oui_filters = 5;

  message IBeaconFilter {
    IBeaconFilterType filter_type = 1;
    string uuid = 2;
    int32 major = 3;
    int32 minor = 4;
    enum IBeaconFilterType { ANY_IBEACON = 0; UUID = 1; UUID_MAJOR_MINOR = 2; }
  }

  message EddystoneFilter {
    EddystoneFilterType filter_type = 1;
    string namespace = 2;
    string instance = 3;
    enum EddystoneFilterType { ANY_EDDYSTONE_UID = 0; NAMESPACE = 1; INSTANCE = 2; NAMESPACE_INSTANCE = 3; }
  }
}

message DisableFiltersRequest {
  string partner_tenant_id = 1;
}

message Health {
  int64 timestamp = 1;
  repeated ActiveConnection active_connections = 2;
  string protocol_version = 3;
  repeated AppActivation app_activations = 4;

  message ActiveConnection {
    ConnectionType connection_type = 1;
    int32 min_partition = 2;
    int32 max_partition = 3;
    int64 from_timestamp = 4;
    int32 replica_id = 5;
    int64 connected_timestamp = 6;
    int32 one_minute_rate = 7;
    string environment = 8;
  }

  enum ConnectionType {
    HTTP = 0;
    G_RPC = 1;
    WEB_SOCKET = 2;
  }
}

message GetDeviceRequest {
  string partner_tenant_id = 1;
  oneof id {
    string mac_address = 2;
    string device_id = 3;
  }
}

message SaveDeviceRequest {
  string partner_tenant_id = 1;
  oneof id {
    string mac_address = 2;
    string device_id = 3;
  }
  DeviceProfileData device_profile_data = 4;
}

message DeviceProfileData {
  string first_name = 1;
  string last_name = 2;
  Gender gender = 3;
  MobileInfo mobile = 4;
  EmailInfo email = 5;
  repeated SocialNetworkInfo social_network_info = 6;
  DeviceType type = 7;
  repeated string add_tags = 8;
  repeated string remove_tags = 9;
  repeated Attribute attributes = 10;
}
