1use std::time::SystemTime;
2use std::env;
3use std::process;
4use chrono::{TimeZone, Utc};
5use timex_datalink::PacketGenerator;
6use timex_datalink::NotebookAdapter;
7use timex_datalink::protocol_4::{
8 Protocol4,
9 alarm::Alarm,
10 eeprom::{
11 Anniversary,
12 Appointment,
13 List,
14 PhoneNumber,
15 Eeprom,
16 phone_number::PhoneType,
17 list::Priority,
18 NotificationMinutes,
19 },
20 time::{Time, DateFormat},
21 sound_options::SoundOptions,
22 sound_theme::SoundTheme,
23 wrist_app::WristApp,
24 start::Start,
25 sync::Sync,
26 end::End,
27};
28use timex_datalink::char_encoders::{CharString, EepromString, PhoneString};
29
30fn main() {
31 let args: Vec<String> = env::args().collect();
33 let serial_port = match args.len() {
34 1 => {
35 println!("Usage: {} <serial_port_path>", args[0]);
36 println!(" Example: {} /dev/ttyUSB0", args[0]);
37 process::exit(1);
38 },
39 _ => args[1].clone(),
40 };
41 let appointments = vec![
43 Appointment {
44 time: system_time_from_date(2022, 10, 31, 19, 0, 0),
45 message: EepromString::new("Scare the neighbors"),
46 },
47 Appointment {
48 time: system_time_from_date(2022, 11, 24, 17, 0, 0),
49 message: EepromString::new("Feed the neighbors"),
50 },
51 Appointment {
52 time: system_time_from_date(2022, 12, 25, 14, 0, 0),
53 message: EepromString::new("Spoil the neighbors"),
54 },
55 ];
56
57 let anniversaries = vec![
59 Anniversary {
60 time: system_time_from_date(1985, 7, 3, 0, 0, 0),
61 anniversary: EepromString::new("Release of Back to the Future"),
62 },
63 Anniversary {
64 time: system_time_from_date(1968, 4, 6, 0, 0, 0),
65 anniversary: EepromString::new("Release of 2001"),
66 },
67 ];
68
69 let phone_numbers = vec![
71 PhoneNumber {
72 name: EepromString::new("Marty McFly"),
73 number: PhoneString::new("1112223333"),
74 phone_type: PhoneType::Home,
75 },
76 PhoneNumber {
77 name: EepromString::new("Doc Brown"),
78 number: PhoneString::new("4445556666"),
79 phone_type: PhoneType::Cell,
80 },
81 ];
82
83 let lists = vec![
85 List {
86 list_entry: EepromString::new("Muffler bearings"),
87 priority: Some(Priority::Two),
88 },
89 List {
90 list_entry: EepromString::new("Headlight fluid"),
91 priority: Some(Priority::Four),
92 },
93 ];
94
95 let time1 = SystemTime::now();
97
98 let mut protocol = Protocol4::new();
100
101 protocol.add(Sync { length: 100 });
103 protocol.add(Start {});
104
105 protocol.add(Time {
107 zone: 1,
108 is_24h: false,
109 date_format: DateFormat::MonthDashDayDashYear,
110 time: time1,
111 name: CharString::new("PDT", true),
112 });
113
114 protocol.add(Time {
115 zone: 2,
116 is_24h: true,
117 date_format: DateFormat::MonthDashDayDashYear,
118 time: time1,
119 name: CharString::new("GMT", true),
120 });
121
122 protocol.add(Alarm {
124 number: 1,
125 audible: true,
126 time: system_time_from_time(9, 0),
127 message: CharString::new("Wake up", false),
128 });
129
130 protocol.add(Alarm {
131 number: 2,
132 audible: true,
133 time: system_time_from_time(9, 5),
134 message: CharString::new("For real", false),
135 });
136
137 protocol.add(Alarm {
138 number: 3,
139 audible: false,
140 time: system_time_from_time(9, 10),
141 message: CharString::new("Get up", false),
142 });
143
144 protocol.add(Alarm {
145 number: 4,
146 audible: true,
147 time: system_time_from_time(18, 0), message: CharString::new("Or not", false),
149 });
150
151 protocol.add(Alarm {
152 number: 5,
153 audible: false,
154 time: system_time_from_time(14, 0), message: CharString::new("Told you", false),
156 });
157
158 protocol.add(SoundOptions {
160 hourly_chime: true,
161 button_beep: true,
162 });
163
164 protocol.add(SoundTheme {
165 sound_theme_data: vec![0x00, 0x01, 0x02, 0x03],
167 });
168
169 let eeprom = Eeprom {
171 appointments,
172 anniversaries,
173 lists,
174 phone_numbers,
175 appointment_notification_minutes: Some(NotificationMinutes::FifteenMinutes),
176 };
177 protocol.add(eeprom);
178
179 protocol.add(WristApp {
180 wrist_app_data: vec![0x00, 0x01, 0x02, 0x03],
182 });
183
184 protocol.add(End {});
186
187 let all_packets = protocol.packets();
189
190 println!("Created Protocol4 structure with all components");
192 println!("- Generated {} packet groups", all_packets.len());
193
194 for (i, packet) in all_packets.iter().enumerate() {
196 let preview: Vec<u8> = packet.iter().take(6).cloned().collect();
198 println!("Packet group {}: {} bytes, starts with {:02X?}...", i, packet.len(), preview);
199 }
200
201 println!("\nTransmitting data to the watch on port: {}", serial_port);
202
203 let adapter = NotebookAdapter::new(
205 serial_port,
206 None, None, true, );
210
211 match adapter.write(&all_packets) {
212 Ok(_) => println!("\nSuccessfully transmitted data to the watch!"),
213 Err(e) => {
214 eprintln!("\nError transmitting data: {}", e);
215 process::exit(1);
216 }
217 }
218}
219
220fn system_time_from_date(year: i32, month: u32, day: u32, hour: u32, min: u32, sec: u32) -> SystemTime {
222 let naive_dt = chrono::NaiveDate::from_ymd_opt(year, month, day)
224 .unwrap()
225 .and_hms_opt(hour, min, sec)
226 .unwrap();
227
228 let dt = Utc.from_utc_datetime(&naive_dt);
229
230 if dt.timestamp() >= 0 {
232 SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(dt.timestamp() as u64)
233 } else {
234 SystemTime::UNIX_EPOCH - std::time::Duration::from_secs((-dt.timestamp()) as u64)
235 }
236}
237
238fn system_time_from_time(hour: u32, min: u32) -> SystemTime {
240 let naive_dt = chrono::NaiveDate::from_ymd_opt(2000, 1, 1)
243 .unwrap()
244 .and_hms_opt(hour, min, 0)
245 .unwrap();
246
247 let dt = Utc.from_utc_datetime(&naive_dt);
248
249 SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(dt.timestamp() as u64)
251}