syntax = "proto2"; // we must use proto2 to serialize default values on the wire package xiaomi; // FIXME: The generated class is very large, so Android Studio stops recognizing it // set idea.max.intellisense.filesize=5000 in idea.properties // by clicking Help -> Edit Custom Properties option java_package = "nodomain.freeyourgadget.gadgetbridge.proto.xiaomi"; option java_outer_classname = "XiaomiProto"; message Command { required uint32 type = 1; optional uint32 subtype = 2; optional Auth auth = 3; optional System system = 4; optional Watchface watchface = 6; optional Health health = 10; optional Calendar calendar = 14; optional Music music = 20; optional Notification notification = 9; optional Weather weather = 12; optional Schedule schedule = 19; // command type 21 optional Phonebook phonebook = 23; // type 22 optional DataUpload dataUpload = 24; optional uint32 status = 100; // 0 on success on some } // // Auth // message Auth { optional string userId = 7; optional uint32 status = 8; // 1, 26 optional PhoneNonce phoneNonce = 30; optional WatchNonce watchNonce = 31; // 1, 27 optional AuthStep3 authStep3 = 32; optional AuthStep4 authStep4 = 33; } message PhoneNonce { required bytes nonce = 1; } message WatchNonce { required bytes nonce = 1; required bytes hmac = 2; } message AuthStep3 { required bytes encryptedNonces = 1; required bytes encryptedDeviceInfo = 2; // AuthDeviceInfo } message AuthStep4 { required uint32 unknown1 = 1; optional uint32 unknown2 = 2; } message AuthDeviceInfo { required uint32 unknown1 = 1; // 0 - needs to be serialized explicitly required float phoneApiLevel = 2; required string phoneName = 3; // phone model required uint32 unknown3 = 4; // 224 required string region = 5; // 2-letter, upper case } // // System // message System { // 2, 1 optional Power power = 2; // 2, 2 optional DeviceInfo deviceInfo = 3; // 2, 3 optional Clock clock = 4; // 2, 18 optional uint32 findDevice = 5; // 0 // 2, 29 get | 2, 39 set optional DisplayItems displayItems = 10; // 2, 34 optional DoNotDisturb dndStatus = 11; // 2, 39 optional WorkoutTypes workoutTypes = 14; // 2, 5 optional FirmwareInstallRequest firmwareInstallRequest = 16; optional FirmwareInstallResponse firmwareInstallResponse = 17; // 2, 9 get | 2, 21 set optional Password password = 19; // 2, 7 get | 2, 8 set optional Camera camera = 15; // 2, 6 optional Language language = 20; // 2, 51 get | 2, 52 create optional WidgetScreens widgetScreens = 28; // 2, 53 optional WidgetParts widgetParts = 29; // 2, 14 optional MiscSettingGet miscSettingGet = 34; // 2, 15 optional MiscSettingSet miscSettingSet = 35; // 2, 43 optional PhoneSilentModeGet phoneSilentModeGet = 36; // 2, 44 returning to watch, 2, 45 setting from watch optional PhoneSilentModeSet phoneSilentModeSet = 37; // 2, 46 optional VibrationPatterns vibrationPatterns = 38; // 2, 47 optional VibrationNotificationType vibrationSetPreset = 39; // 2, 58 optional CustomVibrationPattern vibrationPatternCreate = 40; // 2, 59 optional VibrationTest vibrationTestCustom = 41; // 2, 47 optional VibrationPatternAck vibrationPatternAck = 43; // 2, 78 optional BasicDeviceState basicDeviceState = 48; // 2, 79 optional DeviceState deviceState = 49; } message Power { optional Battery battery = 1; } message Battery { optional uint32 level = 1; optional uint32 state = 2; optional LastCharge lastCharge = 3; } message LastCharge { optional uint32 state = 1; // 2 optional uint32 timestampSeconds = 2; } message DeviceInfo { required string serialNumber = 1; required string firmware = 2; optional string unknown3 = 3; // "" ? required string model = 4; } message Clock { required Date date = 1; required Time time = 2; required TimeZone timezone = 3; optional bool isNot24hour = 4; } message Date { required uint32 year = 1; required uint32 month = 2; required uint32 day = 3; } message Time { required uint32 hour = 1; required uint32 minute = 2; optional uint32 second = 3; optional uint32 millisecond = 4; } message TimeZone { // offsets are in blocks of 15 min optional sint32 zoneOffset = 1; optional sint32 dstOffset = 2; required string name = 3; } message DisplayItems { repeated DisplayItem displayItem = 1; } message DisplayItem { optional string code = 1; optional string name = 2; optional bool disabled = 3; optional uint32 isSettings = 4; optional uint32 unknown5 = 5; // 1 optional bool inMoreSection = 6; // rarely used in official app } message Camera { required bool enabled = 1; } message Language { optional string code = 1; // pt_pt, en_us } message WorkoutTypes { repeated WorkoutType workoutType = 1; optional uint32 unknown2 = 2; // 1 } message WorkoutType { optional uint32 type = 1; optional uint32 unknown2 = 2; // 1 } message WidgetScreens { repeated WidgetScreen widgetScreen = 1; optional uint32 isFullList = 2; // 1 to overwrite the full list optional WidgetsCapabilities widgetsCapabilities = 3; // only in response } message WidgetsCapabilities { optional uint32 minWidgets = 1; // 1 optional uint32 maxWidgets = 2; // 7 // bitmap: // - 0b0000_0011_0000_0000 (768) on bands // - 0b0000_0000_0000_0111 (7) on some square/round devices (Watch S1 Active) // - 0b0000_0000_1000_0111 (135) on some square/round devices (Redmi Watch 4) // - 0b0111_1100_0000_0000 (31744) on portrait devices (Band 8 Pro) optional uint32 supportedLayoutStyles = 3; } message WidgetScreen { optional uint32 id = 1; // starts at 1 optional uint32 layout = 2; // 256 for split, 512 for tall repeated WidgetPart widgetPart = 3; } message WidgetParts { repeated WidgetPart widgetPart = 1; } message WidgetPart { optional uint32 type = 1; // 1 for small 1x1, 2 for wide 2x1, 3 for tall 1x2 optional uint32 function = 2; // matches command type optional uint32 id = 3; // they all seem unique optional string title = 4; // not set on create optional uint32 subType = 5; // usually 0 if no subtype optional string appId = 6; // "" on get optional string unknown7 = 7; // "" on get } message DoNotDisturb { optional uint32 status = 1; // 0 enabled, 2 disabled } message MiscSettingGet { optional uint32 setting = 1; // 2 dndSync } message MiscSettingSet { optional MiscNotificationSettings miscNotificationSettings = 1; optional DndSync dndSync = 2; optional WearingMode wearingMode = 3; } message MiscNotificationSettings { optional uint32 wakeScreen = 1; // 0 ignore 1 enable 2 disable optional uint32 onlyWhenPhoneLocked = 2; // 0 ignore 1 enable 2 disable } message DndSync { optional uint32 enabled = 1; // 0/1 } message WearingMode { // 0 Band Mode (wristband) // 1 Pebble Mode (show buckle) // 2 Necklace mode (neck strap) optional uint32 mode = 1; } message FirmwareInstallRequest { optional uint32 unknown1 = 1; // 0 optional uint32 unknown2 = 2; // 0 optional string version = 3; optional string md5 = 4; } message FirmwareInstallResponse { optional uint32 status = 1; // 0 } message Password { optional uint32 state = 1; // 1 disabled, 2 enabled optional string password = 2; optional uint32 unknown3 = 3; // 0 when set on ret } message PhoneSilentModeGet { optional uint32 unknown1 = 1; // 1 } message PhoneSilentModeSet { optional PhoneSilentMode phoneSilentMode = 1; } message PhoneSilentMode { optional bool silent = 1; } message VibrationPatterns { repeated VibrationNotificationType notificationType = 1; optional uint32 unknown2 = 2; // 50, max patterns? repeated CustomVibrationPattern customVibrationPattern = 3; } message CustomVibrationPattern { optional uint32 id = 1; optional string name = 2; repeated Vibration vibration = 3; optional uint32 unknown4 = 4; // 1 on creation } message VibrationNotificationType { // 1 incoming calls // 2 events // TODO confirm which one is events, which one is schedule // 3 alarms // 4 notifications // 5 standing reminder // 6 sms // 7 goal // 8 events // TODO confirm which one is events, which one is schedule optional uint32 notificationType = 1; optional uint32 preset = 2; } message VibrationTest { repeated Vibration vibration = 1; } message VibrationPatternAck { optional uint32 status = 1; // 0 } message Vibration { optional uint32 vibrate = 1; // 0/1 optional uint32 ms = 2; } message DeviceActivityState { optional uint32 activityType = 1; optional uint32 currentActivityState = 2; } message BasicDeviceState { required bool isCharging = 1; // true when connected to charger optional uint32 batteryLevel = 2; required bool isWorn = 3; // true when the device detects it's being worn required bool isUserAsleep = 4; // true when the device detected its user is asleep optional DeviceActivityState activityState = 5; } message DeviceState { optional uint32 chargingState = 1; // 1 charging, 2 not charging optional uint32 wearingState = 2; // 1 wearing, 2 not wearing optional uint32 sleepState = 3; // 1 sleep detected, 2 no sleep detected optional uint32 warningState = 4; // ? optional DeviceActivityState activityState = 5; } // // Watchface // message Watchface { optional WatchfaceList watchfaceList = 1; // 4, 2 delete | 4, 1 set optional string watchfaceId = 2; optional uint32 ack = 4; // 1 // 4, 4 optional uint32 installStatus = 5; // 0 not installed, 2 already installed optional WatchfaceInstallStart watchfaceInstallStart = 6; optional WatchfaceInstallFinish watchfaceInstallFinish = 7; } message WatchfaceList { repeated WatchfaceInfo watchface = 1; } message WatchfaceInfo { optional string id = 1; optional string name = 2; optional bool active = 3; optional bool canDelete = 4; optional uint32 unknown5 = 5; // 0 optional uint32 unknown6 = 6; // 0 optional uint32 unknown11 = 11; // 0 } message WatchfaceInstallStart { optional string id = 1; optional uint32 size = 2; } message WatchfaceInstallFinish { optional string id = 1; optional uint32 unknown2 = 2; // 2 optional uint32 unknown3 = 3; // 0 optional uint32 unknown4 = 4; // 0 } // // Health // message Health { optional UserInfo userInfo = 1; // 8, 2 get today | 8, 3 get past optional bytes activityRequestFileIds = 2; // optional bytes activitySyncAckFileIds = 3; optional ActivitySyncRequestToday activitySyncRequestToday = 5; optional SpO2 spo2 = 7; optional HeartRate heartRate = 8; // 8, 12 get | 8, 13 set optional StandingReminder standingReminder = 9; optional Stress stress = 10; optional GoalNotification goalNotification = 13; // 8, 35 get | 8, 36 set optional VitalityScore vitalityScore = 14; // 8, 26 optional WorkoutStatusWatch workoutStatusWatch = 20; // 8, 30 optional WorkoutOpenWatch workoutOpenWatch = 25; optional WorkoutOpenReply workoutOpenReply = 26; // 7, 43 optional GoalsConfig goalsConfig = 38; // 7, 48 optional WorkoutLocation workoutLocation = 40; // 8,45 enable | 8, 46 disable | 8, 47 periodic optional RealTimeStats realTimeStats = 39; } message UserInfo { optional uint32 height = 1; // cm optional float weight = 2; // kg optional uint32 birthday = 3; // YYYYMMDD optional uint32 gender = 4; // 1 male, 2 female optional uint32 maxHeartRate = 5; optional uint32 goalCalories = 6; optional uint32 goalSteps = 7; optional uint32 goalStanding = 9; // hours optional uint32 goalMoving = 11; // minutes } message ActivitySyncRequestToday { optional uint32 unknown1 = 1; // 0 most of the time, sometimes 1 } message SpO2 { optional uint32 unknown1 = 1; // 1 optional bool allDayTracking = 2; optional Spo2AlarmLow alarmLow = 4; } message Spo2AlarmLow { optional bool alarmLowEnabled = 1; optional uint32 alarmLowThreshold = 2; // 90, 85, 80 } message HeartRate { optional bool disabled = 1; // 0 enabled 1 disabled optional uint32 interval = 2; // 0 smart 1 10 30 optional bool alarmHighEnabled = 3; optional uint32 alarmHighThreshold = 4; // 100, 110, ... 150 optional AdvancedMonitoring advancedMonitoring = 5; optional uint32 unknown7 = 7; // 1 optional HeartRateAlarmLow heartRateAlarmLow = 8; optional uint32 breathingScore = 9; // 1 on, 2 off } message AdvancedMonitoring { required bool enabled = 1; } message HeartRateAlarmLow { optional bool alarmLowEnabled = 1; optional uint32 alarmLowThreshold = 2; // 40, 45, 50 } message StandingReminder { optional bool enabled = 1; optional HourMinute start = 2; optional HourMinute end = 3; optional bool dnd = 4; optional HourMinute dndStart = 6; optional HourMinute dndEnd = 7; } message Stress { optional bool allDayTracking = 1; optional RelaxReminder relaxReminder = 2; } message GoalNotification { optional bool enabled = 1; optional uint32 unknown2 = 2; // 1 } message RelaxReminder { optional bool enabled = 1; optional uint32 unknown2 = 2; // 0 } message VitalityScore { optional bool sevenDay = 1; optional bool dailyProgress = 2; } message WorkoutStatusWatch { optional uint32 timestamp = 1; // seconds optional uint32 sport = 3; optional uint32 status = 4; // 0 started, 1 resumed, 2 paused, 3 finished optional bytes activityFileIds = 5; optional uint32 unknown6 = 6; // 2 optional uint32 unknown10 = 10; // 0 } message WorkoutOpenWatch { // This is only called when gps is needed? // 1 outdoor running, 2 walking, 3 hiking, 4 trekking, 5 trail run, 6 outdoor cycling optional uint32 sport = 1; optional uint32 unknown2 = 2; // 2 } message WorkoutOpenReply { // 3 2 10 when no gps permissions at all // 5 2 10 when no all time gps permission // ... // 0 * * when phone gps is working fine // 0 2 10 // 0 2 2 optional uint32 unknown1 = 1; optional uint32 unknown2 = 2; // always 2? optional uint32 unknown3 = 3; } message GoalsConfig { repeated Goal currentGoals = 1; repeated Goal supportedGoals = 2; } message Goal { // 1 steps? // 2 calories? // 3 moving time // 4 standing time optional uint32 id = 1; } message WorkoutLocation { optional uint32 unknown1 = 1; // 10, sometimes 2? optional uint32 timestamp = 2; // seconds optional double longitude = 3; optional double latitude = 4; optional double altitude = 5; optional float speed = 6; optional float bearing = 7; optional float horizontalAccuracy = 8; optional float verticalAccuracy = 9; } message RealTimeStats { optional uint32 steps = 1; optional uint32 calories = 2; optional uint32 unknown3 = 3; // increases during activity optional uint32 heartRate = 4; optional uint32 unknown5 = 5; // 0 probably moving time optional uint32 standingHours = 6; } // // Calendar // message Calendar { optional CalendarSync calendarSync = 2; } message CalendarSync { repeated CalendarEvent event = 1; optional bool disabled = 2; } message CalendarEvent { optional string title = 1; optional string description = 2; optional string location = 3; optional uint32 start = 4; // unix epoch sec optional uint32 end = 5; // unix epoch sec optional bool allDay = 6; optional uint32 notifyMinutesBefore = 7; } // // Music // message Music { // 18, 1 optional MusicInfo musicInfo = 1; // 18, 2 optional MediaKey mediaKey = 2; } message MusicInfo { required uint32 state = 1; // 0 not playing, 1 playing, 2 paused optional uint32 volume = 2; optional string track = 4; optional string artist = 5; optional uint32 position = 6; optional uint32 duration = 7; } message MediaKey { required uint32 key = 1; // 0 play, 1 pause, 3 prev, 4 next, 5 vol optional uint32 volume = 2; // 100 vol+, 0 vol- } // // Notification // message Notification { // 7, 8 optional NotificationId openOnPhone = 2; optional Notification2 notification2 = 3; optional NotificationDismiss notificationDismiss = 4; optional bool screenOnOnNotifications = 7; optional uint32 unknown8 = 8; // 1 on canned replies request? // 7, 9 get | 7, 12 set optional CannedMessages cannedMessages = 9; // 7, 13 optional NotificationReply notificationReply = 12; // 7, 14 optional uint32 notificationReplyStatus = 13; // 0 on success, 1 on failure // 7, 15 optional NotificationIconPackage notificationIconReply = 14; // 7, 15 optional NotificationIconRequest notificationIconRequest = 15; // 7, 16 optional NotificationIconPackage notificationIconQuery = 16; } message Notification2 { optional Notification3 notification3 = 1; } message Notification3 { optional string package = 1; optional string appName = 2; optional string title = 3; optional string unknown4 = 4; optional string body = 5; optional string timestamp = 6; optional uint32 id = 7; optional bool isCall = 8; optional bool repliesAllowed = 11; // only for calls? optional string key = 12; // "0|||null|12345" optional bool openOnPhone = 13; // 1 to show "Open on phone", needs key } message NotificationDismiss { repeated NotificationId notificationId = 1; } message NotificationId { optional uint32 id = 1; optional string package = 2; // truncated optional string key = 4; // sometimes "" } message CannedMessages { optional uint32 minReplies = 1; repeated string reply = 2; optional uint32 maxReplies = 3; } message NotificationIconRequest { optional uint32 unknown1 = 1; // 0 probably format optional uint32 unknown2 = 2; // 3 probably format optional uint32 size = 3; } message NotificationReply { optional uint32 unknown1 = 1; // 1 optional string message = 2; optional uint32 unknown3 = 3; // 1 optional string number = 4; } message NotificationIconPackage { optional string package = 1; } // // Weather // message Weather { optional WeatherCurrent current = 1; optional WeatherForecast forecast = 2; // response to 10, 5 (get location list) | payload of 10, 6 (set, update location list) | payload of 10, 8 (remove) optional WeatherLocations locations = 4; // indication payload of 10, 3 (requested update) | payload of 10, 7 (set current, add to list) optional WeatherLocation location = 5; // 10, 10 optional WeatherPrefs prefs = 6; } message WeatherCurrent { optional WeatherMetadata metadata = 1; required uint32 weatherCondition = 2; optional WeatherUnitValue temperature = 3; optional WeatherUnitValue humidity = 4; optional WeatherUnitValue wind = 5; optional WeatherUnitValue uv = 6; optional WeatherUnitValue aqi = 7; optional WeatherWarnings warning = 8; // Seems to be an array? optional float pressure = 9; } message WeatherMetadata { required string publicationTimestamp = 1; required string cityName = 2; required string locationName = 3; optional string locationKey = 4; optional bool isCurrentLocation = 5; // default location? } message WeatherUnitValue { required string unit = 1; required sint32 value = 2; } message WeatherWarnings { repeated WeatherWarning warning = 1; } message WeatherWarning { required string type = 1; required string level = 2; optional string title = 3; optional string description = 4; optional string id = 5; } message WeatherLocations { repeated WeatherLocation location = 1; } message WeatherForecast { required WeatherMetadata metadata = 1; required ForecastEntries entries = 2; } message ForecastEntries { repeated ForecastEntry entry = 1; } message ForecastEntry { optional WeatherUnitValue aqi = 1; optional WeatherRange conditionRange = 2; optional WeatherRange temperatureRange = 3; optional string temperatureSymbol = 4; optional WeatherSunriseSunset sunriseSunset = 5; optional WeatherUnitValue wind = 6; } message WeatherRange { required sint32 from = 1; required sint32 to = 2; } message WeatherSunriseSunset { required string sunrise = 1; required string sunset = 2; } message WeatherLocation { required string code = 1; optional string name = 2; } message WeatherPrefs { optional uint32 temperatureScale = 1; // 1 celsius 2 fahrenheit optional uint32 weatherWarningsEnabled = 2; // 0 = unsupported, 1 = enabled, 2 = disabled } // // Schedule // message Schedule { // 17, 0 get optional Alarms alarms = 1; // 17, 1 optional AlarmDetails createAlarm = 2; // 17, 3 -> returns 17, 5 optional Alarm editAlarm = 3; optional uint32 ackId = 4; // id of created or edited alarm and reminder // 17, 4 optional AlarmDelete deleteAlarm = 5; // 17, 8 get | 17, 9 set optional SleepMode sleepMode = 9; // 17, 14 get: 10 -> 2: 50 // max reminders? optional Reminders reminders = 10; // 17,10 get/ret | 17,11 create | 17,13 delete optional WorldClocks worldClocks = 11; optional uint32 worldClockStatus = 13; // 0 on edit and create // 17, 15 optional ReminderDetails createReminder = 14; // 17, 17 optional Reminder editReminder = 15; // 17, 18 optional ReminderDelete deleteReminder = 17; } message Alarms { optional uint32 maxAlarms = 2; // 10 optional uint32 unknown3 = 3; // 0 optional uint32 unknown4 = 4; // 1 repeated Alarm alarm = 1; } message Alarm { optional uint32 id = 1; // starts at 1 optional AlarmDetails alarmDetails = 2; } message AlarmDetails { optional HourMinute time = 2; optional uint32 repeatMode = 3; // 0 once, 1 daily, 5 weekly optional uint32 repeatFlags = 4; // only if weekly: 31 during week, 1 monday, 2 tuesday, 3 mon tue optional bool enabled = 5; optional uint32 smart = 7; // 1 smart, 2 normal } message AlarmDelete { repeated uint32 id = 1; } message SleepMode { required bool enabled = 1; optional SleepModeSchedule schedule = 2; } message SleepModeSchedule { optional HourMinute start = 1; optional HourMinute end = 2; optional uint32 unknown3 = 3; // 0 } message Reminders { repeated Reminder reminder = 1; optional uint32 maxReminders = 2; } message Reminder { optional uint32 id = 1; optional ReminderDetails reminderDetails = 2; } message ReminderDetails { optional Date date = 1; optional Time time = 2; optional uint32 repeatMode = 3; // 0 once, 1 daily, weekly (every monday), 7 monthly, 8 yearly optional uint32 repeatFlags = 4; // 64 for unset, day flags on weekly optional string title = 5; } message ReminderDelete { repeated uint32 id = 1; } message WorldClocks { repeated string worldClock = 1; } message HourMinute { required uint32 hour = 1; required uint32 minute = 2; } // // Data Upload (watchface, notification icons, firmware) // message DataUpload { // 22, 0 optional DataUploadRequest dataUploadRequest = 1; optional DataUploadAck dataUploadAck = 2; } message DataUploadRequest { optional uint32 type = 1; // 16 for watchface, 50 for notification icons, 32 for firmware? optional bytes md5sum = 2; optional uint32 size = 3; } message DataUploadAck { optional bytes md5sum = 1; optional uint32 unknown2 = 2; // 0 optional uint32 resumePosition = 4; optional uint32 chunkSize = 5; // 4096 on Redmi Watch 3 Active, Nonexistent on Mi Band 8 } message ContactInfo { optional string displayName = 1; optional string phoneNumber = 2; } message ContactList { repeated ContactInfo contactInfo = 1; } message Phonebook { optional string requestedPhoneNumber = 2; optional ContactInfo contactInfo = 3; optional ContactList contactList = 4; }