1use std::time::SystemTime;
2use std::env;
3use std::process;
4use timex_datalink::{
5 Protocol3, PacketGenerator, NotebookAdapter,
6 protocol_3::{
7 Sync, Start, End, Time, Alarm, SoundOptions,
8 eeprom::{Eeprom, Appointment, Anniversary, PhoneNumber, List}
9 },
10 char_encoders::CharString,
11 protocol_3::time::DateFormat,
12};
13use chrono::{DateTime, Utc, TimeZone};
14
15fn system_time_from_date(year: i32, month: u32, day: u32, hour: u32, min: u32) -> SystemTime {
17 let naive_dt = chrono::NaiveDate::from_ymd_opt(year, month, day)
18 .unwrap()
19 .and_hms_opt(hour, min, 0)
20 .unwrap();
21
22 let dt = Utc.from_utc_datetime(&naive_dt);
23
24 if dt.timestamp() < 0 {
25 SystemTime::UNIX_EPOCH
28 } else {
29 SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(dt.timestamp() as u64)
30 }
31}
32
33fn main() {
36 let args: Vec<String> = env::args().collect();
38 let serial_port = match args.len() {
39 1 => {
40 println!("Serial port not specified. Running in preview mode only.");
41 println!("Usage: {} <serial_port_path>", args[0]);
42 println!(" Example: {} /dev/ttyUSB0", args[0]);
43 String::new() },
45 _ => args[1].clone(),
46 };
47
48 let mut protocol = Protocol3::new();
50
51 let appointments = vec![
53 Appointment::new(
54 system_time_from_date(2022, 10, 31, 19, 0),
55 "Scare the neighbors".to_string()
56 ),
57 Appointment::new(
58 system_time_from_date(2022, 11, 24, 17, 0),
59 "Feed the neighbors".to_string()
60 ),
61 Appointment::new(
62 system_time_from_date(2022, 12, 25, 14, 0),
63 "Spoil the neighbors".to_string()
64 ),
65 ];
66
67 let anniversaries = vec![
69 Anniversary::new(
70 system_time_from_date(1985, 7, 3, 0, 0),
71 "Release of Back to the Future".to_string()
72 ),
73 Anniversary::new(
74 system_time_from_date(1968, 4, 6, 0, 0),
75 "Release of 2001".to_string()
76 ),
77 ];
78
79 let phone_numbers = vec![
81 PhoneNumber::new(
82 "Marty McFly".to_string(),
83 "1112223333".to_string(),
84 Some("H".to_string())
85 ),
86 PhoneNumber::new(
87 "Doc Brown".to_string(),
88 "4445556666".to_string(),
89 Some("C".to_string())
90 ),
91 ];
92
93 let lists = vec![
95 List::new(
96 "Muffler bearings".to_string(),
97 Some(2)
98 ),
99 List::new(
100 "Headlight fluid".to_string(),
101 Some(4)
102 ),
103 ];
104
105 protocol.add(Sync::default());
107 protocol.add(Start);
108
109 let time1 = SystemTime::now();
111 let duration = time1.duration_since(SystemTime::UNIX_EPOCH).unwrap();
113 let dt1 = DateTime::<Utc>::from_timestamp(duration.as_secs() as i64, 0).unwrap();
114 println!("Setting local time to: {}", dt1.format("%Y-%m-%d %H:%M:%S"));
115
116 protocol.add(Time {
117 zone: 1,
118 is_24h: false,
119 date_format: DateFormat::MonthDashDayDashYear,
120 time: time1,
121 name: CharString::new("HOME", true),
122 });
123
124 let time2 = SystemTime::now();
126 protocol.add(Time {
127 zone: 2,
128 is_24h: true,
129 date_format: DateFormat::MonthDashDayDashYear,
130 time: time2,
131 name: CharString::new("UTC", true),
132 });
133
134 protocol.add(Alarm {
136 number: 1,
137 audible: true,
138 hour: 9,
139 minute: 0,
140 message: CharString::new("Wake up", true),
141 });
142
143 protocol.add(Alarm {
144 number: 2,
145 audible: true,
146 hour: 9,
147 minute: 5,
148 message: CharString::new("For real", true),
149 });
150
151 protocol.add(Alarm {
152 number: 3,
153 audible: false,
154 hour: 9,
155 minute: 10,
156 message: CharString::new("Get up", true),
157 });
158
159 protocol.add(Alarm {
160 number: 4,
161 audible: true,
162 hour: 9,
163 minute: 15,
164 message: CharString::new("Or not", true),
165 });
166
167 protocol.add(Alarm {
168 number: 5,
169 audible: false,
170 hour: 11,
171 minute: 30,
172 message: CharString::new("Told you", true),
173 });
174
175 let mut eeprom = Eeprom::new();
177 eeprom.appointments = appointments;
178 eeprom.anniversaries = anniversaries;
179 eeprom.phone_numbers = phone_numbers;
180 eeprom.lists = lists;
181 eeprom.appointment_notification_minutes = Some(15);
182
183 protocol.add(eeprom);
185
186 protocol.add(SoundOptions {
204 hourly_chime: true,
205 button_beep: true,
206 });
207
208 protocol.add(End);
234
235 let packets = protocol.packets();
237
238 println!("Generated {} packets for Protocol 3", packets.len());
240
241 println!("\nPacket summary:");
243 for (i, packet) in packets.iter().enumerate().take(5) {
244 let preview_len = std::cmp::min(packet.len(), 16);
246 let preview: Vec<u8> = packet.iter().take(preview_len).cloned().collect();
247 println!("Packet {}: {} bytes, starts with {:02X?}{}",
248 i + 1, packet.len(), preview,
249 if packet.len() > preview_len { "..." } else { "" });
250 }
251 if packets.len() > 5 {
252 println!("... and {} more packets", packets.len() - 5);
253 }
254
255 if !serial_port.is_empty() {
257 println!("\nTransmitting data to the watch on port: {}", serial_port);
258
259 let adapter = NotebookAdapter::new(
261 serial_port,
262 Some(0.014), Some(0.08), true, );
266
267 match adapter.write(&packets) {
268 Ok(_) => println!("\nSuccessfully transmitted data to the watch!"),
269 Err(e) => {
270 eprintln!("\nError transmitting data: {}", e);
271 process::exit(1);
272 }
273 }
274 } else {
275 println!("\nNo serial port specified. Run with a serial port to transmit data to the watch:");
276 println!("Example: cargo run --example protocol3_example /dev/ttyUSB0");
277 }
278}