Protocol3

Struct Protocol3 

Source
pub struct Protocol3 { /* private fields */ }
Expand description

Main Protocol 3 structure

This struct acts as a container for all Protocol 3 models that implement the PacketGenerator trait. It collects and orders packets from all models for transmission to the Timex Datalink watch.

Implementations§

Source§

impl Protocol3

Source

pub fn new() -> Self

Create a new empty Protocol3 instance

Examples found in repository?
examples/protocol3_example.rs (line 49)
35fn main() {
36    // Get the serial port from command line arguments
37    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() // Empty string for preview mode
44        },
45        _ => args[1].clone(),
46    };
47
48    // Create a new Protocol 3 instance
49    let mut protocol = Protocol3::new();
50    
51    // Define the appointments
52    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    // Define the anniversaries
68    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    // Define the phone numbers
80    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    // Define the lists
94    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    // Add each component to the protocol
106    protocol.add(Sync::default());
107    protocol.add(Start);
108    
109    // Add time settings - local time in zone 1
110    let time1 = SystemTime::now();
111    // Convert to DateTime for display
112    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    // Add time settings - UTC time in zone 2
125    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    // Add alarms
135    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    // Create a new EEPROM instance with all data
176    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    // Add the EEPROM to the protocol
184    protocol.add(eeprom);
185    
186    // Use absolute paths for the fixture files (commented out since not used)
187    // let base_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
188    
189    // // Load a sound theme from the example SPC file
190    // println!("Loading sound theme from EXAMPLE.SPC...");
191    // let spc_path = base_path.join("fixtures").join("EXAMPLE.SPC");
192    // let sound_theme = match SoundTheme::from_spc_file(&spc_path) {
193    //     Ok(theme) => theme,
194    //     Err(e) => {
195    //         println!("Warning: Could not load SPC file: {}. Using simulated data.", e);
196    //         // Create a placeholder with minimal data for the example
197    //         SoundTheme::new(vec![0; 32])
198    //     }
199    // };
200    // protocol.add(sound_theme);
201    
202    // Add sound options
203    protocol.add(SoundOptions {
204        hourly_chime: true,
205        button_beep: true,
206    });
207    
208    // // Load a wrist app from the example ZAP file
209    // println!("Loading wrist app from EXAMPLE.ZAP...");
210    // let zap_path = base_path.join("fixtures").join("EXAMPLE.ZAP");
211    // let wrist_app = match WristApp::from_zap_file(&zap_path) {
212    //     Ok(app) => app,
213    //     Err(e) => {
214    //         println!("Warning: Could not load ZAP file: {}. Using simulated data.", e);
215    //         // Create a simulated wrist app with demo data
216    //         let demo_data = vec![
217    //             49, 53, 48, 32, 100, 97, 116, 97, 58, 32, 76, 111, 114, 101, 109, 32,
218    //             105, 112, 115, 117, 109, 32, 100, 111, 108, 111, 114, 32, 115, 105, 116, 32,
219    //             97, 109, 101, 116, 44, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117,
220    //             114, 32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 32, 101, 108, 105,
221    //             116, 44, 32, 115, 101, 100, 32, 100, 111, 32, 101, 105, 117, 115, 109, 111,
222    //             100, 32, 116, 101, 109, 112, 111, 114, 32, 105, 110, 99, 105, 100, 105, 100,
223    //             117, 110, 116, 32, 117, 116, 32, 108, 97, 98, 111, 114, 101, 32, 101, 116,
224    //             32, 100, 111, 108, 111, 114, 101, 32, 109, 97, 103, 110, 97, 32, 97, 108,
225    //             105, 113, 117, 97, 46
226    //         ];
227    //         WristApp::new(demo_data)
228    //     }
229    // };
230    // protocol.add(wrist_app);
231    
232    // Add end command
233    protocol.add(End);
234    
235    // Generate all packets
236    let packets = protocol.packets();
237    
238    // Print number of packets
239    println!("Generated {} packets for Protocol 3", packets.len());
240    
241    // Print packet summary
242    println!("\nPacket summary:");
243    for (i, packet) in packets.iter().enumerate().take(5) {
244        // Only print first few bytes to avoid overwhelming output
245        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 a serial port was provided, transmit the data
256    if !serial_port.is_empty() {
257        println!("\nTransmitting data to the watch on port: {}", serial_port);
258        
259        // Create the notebook adapter and send the packets
260        let adapter = NotebookAdapter::new(
261            serial_port,
262            Some(0.014), // Use faster sleep times for the example
263            Some(0.08), // Use faster sleep times for the example
264            true, // Enable verbose output
265        );
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}
Source

pub fn add<T: PacketGenerator + 'static>(&mut self, model: T)

Add a model to the protocol

Examples found in repository?
examples/protocol3_example.rs (line 106)
35fn main() {
36    // Get the serial port from command line arguments
37    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() // Empty string for preview mode
44        },
45        _ => args[1].clone(),
46    };
47
48    // Create a new Protocol 3 instance
49    let mut protocol = Protocol3::new();
50    
51    // Define the appointments
52    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    // Define the anniversaries
68    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    // Define the phone numbers
80    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    // Define the lists
94    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    // Add each component to the protocol
106    protocol.add(Sync::default());
107    protocol.add(Start);
108    
109    // Add time settings - local time in zone 1
110    let time1 = SystemTime::now();
111    // Convert to DateTime for display
112    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    // Add time settings - UTC time in zone 2
125    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    // Add alarms
135    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    // Create a new EEPROM instance with all data
176    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    // Add the EEPROM to the protocol
184    protocol.add(eeprom);
185    
186    // Use absolute paths for the fixture files (commented out since not used)
187    // let base_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
188    
189    // // Load a sound theme from the example SPC file
190    // println!("Loading sound theme from EXAMPLE.SPC...");
191    // let spc_path = base_path.join("fixtures").join("EXAMPLE.SPC");
192    // let sound_theme = match SoundTheme::from_spc_file(&spc_path) {
193    //     Ok(theme) => theme,
194    //     Err(e) => {
195    //         println!("Warning: Could not load SPC file: {}. Using simulated data.", e);
196    //         // Create a placeholder with minimal data for the example
197    //         SoundTheme::new(vec![0; 32])
198    //     }
199    // };
200    // protocol.add(sound_theme);
201    
202    // Add sound options
203    protocol.add(SoundOptions {
204        hourly_chime: true,
205        button_beep: true,
206    });
207    
208    // // Load a wrist app from the example ZAP file
209    // println!("Loading wrist app from EXAMPLE.ZAP...");
210    // let zap_path = base_path.join("fixtures").join("EXAMPLE.ZAP");
211    // let wrist_app = match WristApp::from_zap_file(&zap_path) {
212    //     Ok(app) => app,
213    //     Err(e) => {
214    //         println!("Warning: Could not load ZAP file: {}. Using simulated data.", e);
215    //         // Create a simulated wrist app with demo data
216    //         let demo_data = vec![
217    //             49, 53, 48, 32, 100, 97, 116, 97, 58, 32, 76, 111, 114, 101, 109, 32,
218    //             105, 112, 115, 117, 109, 32, 100, 111, 108, 111, 114, 32, 115, 105, 116, 32,
219    //             97, 109, 101, 116, 44, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117,
220    //             114, 32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 32, 101, 108, 105,
221    //             116, 44, 32, 115, 101, 100, 32, 100, 111, 32, 101, 105, 117, 115, 109, 111,
222    //             100, 32, 116, 101, 109, 112, 111, 114, 32, 105, 110, 99, 105, 100, 105, 100,
223    //             117, 110, 116, 32, 117, 116, 32, 108, 97, 98, 111, 114, 101, 32, 101, 116,
224    //             32, 100, 111, 108, 111, 114, 101, 32, 109, 97, 103, 110, 97, 32, 97, 108,
225    //             105, 113, 117, 97, 46
226    //         ];
227    //         WristApp::new(demo_data)
228    //     }
229    // };
230    // protocol.add(wrist_app);
231    
232    // Add end command
233    protocol.add(End);
234    
235    // Generate all packets
236    let packets = protocol.packets();
237    
238    // Print number of packets
239    println!("Generated {} packets for Protocol 3", packets.len());
240    
241    // Print packet summary
242    println!("\nPacket summary:");
243    for (i, packet) in packets.iter().enumerate().take(5) {
244        // Only print first few bytes to avoid overwhelming output
245        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 a serial port was provided, transmit the data
256    if !serial_port.is_empty() {
257        println!("\nTransmitting data to the watch on port: {}", serial_port);
258        
259        // Create the notebook adapter and send the packets
260        let adapter = NotebookAdapter::new(
261            serial_port,
262            Some(0.014), // Use faster sleep times for the example
263            Some(0.08), // Use faster sleep times for the example
264            true, // Enable verbose output
265        );
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}

Trait Implementations§

Source§

impl PacketGenerator for Protocol3

Source§

fn packets(&self) -> Vec<Vec<u8>>

Generate packets as a vector of vectors of bytes Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.