1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-27 23:40:31 +02:00
Gadgetbridge/app/src/main/proto/xiaomi.proto
MrYoranimo 0b731611b9 Xiaomi: refactor WidgetManager for Redmi Watch 4
The Redmi Watch 4 reports both an unsupported widget type and layout
style:

- The firmware supports a screen layout for a single full screens
  widget, which is defined by layout ID 128;
- A full screen widget is a single 2x2 part, which is not supported.

This commit adds support for both the new layout and the new widget
type.

Furthermore, this commit refactors the XiaomiWidgetManager. Previously,
the supported layouts were determined by the types of parts supported by
the device. However, the supported layouts are reported by the device
through a bitfield in the widget capabilities message of which the purpose
was unknown, which is now used to determine the supported layouts.
2024-04-12 20:54:49 +02:00

975 lines
23 KiB
Protocol Buffer

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|<package>|<id 2 complement>|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;
}