printer_event_handler 1.4.0

A cross-platform printer status monitoring library for Windows and Linux
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.4.0] - 2025-01-06

### Added

#### Graceful Shutdown Support
- **CancellationToken support** - All monitoring functions now accept optional `CancellationToken` for graceful shutdown
- **Responsive cancellation** - Uses `tokio::select!` for immediate cancellation response during sleep intervals
- **Clean resource cleanup** - Monitoring tasks can be stopped gracefully without task abortion
- **Re-exported CancellationToken** - `tokio_util::sync::CancellationToken` now exported from main crate for convenience

#### Enhanced Monitor Architecture
- **Cloneable PrinterMonitor** - `PrinterMonitor` now implements `Clone` trait for efficient sharing
- **Arc-based backend** - Backend changed from `Box<dyn PrinterBackend>` to `Arc<dyn PrinterBackend>` for shared ownership
- **Efficient multi-printer monitoring** - Multiple monitors can now share the same backend connection
- **No duplicate connections** - Fixed issue where each monitored printer created a new backend instance

### Fixed

#### Code Quality Improvements
- **Edition compatibility** - Fixed Rust edition from non-existent "2024" to "2021"
- **Library logging** - Replaced `println!` with proper `log::info!()` macros in library code
- **PartialEq completeness** - Added missing `is_default` field to printer equality comparison
- **Mutex contention** - Fixed mutex contention by releasing locks before invoking callbacks

#### Testing Infrastructure
- **Comprehensive test coverage** - Added 52 tests covering all modules and platforms
- **Platform-specific tests** - Tests for both Windows (`#[cfg(windows)]`) and Unix (`#[cfg(unix)]`)
- **Cancellation token tests** - New tests for cancellation behavior and graceful shutdown
- **Clone verification** - Tests ensuring `PrinterMonitor` is properly cloneable

### Changed

#### API Updates - BREAKING CHANGE
- **Monitoring function signatures** - All monitoring functions now require `cancel_token: Option<CancellationToken>` parameter:
  - `monitor_printer(printer_name, interval_ms, cancel_token, callback)`
  - `monitor_printer_changes(printer_name, interval_ms, cancel_token, callback)`
  - `monitor_property(printer_name, property, interval_ms, cancel_token, callback)`
  - `monitor_multiple_printers(printer_names, interval_ms, cancel_token, callback)`
- **Pass None for no cancellation** - Existing code can pass `None` to maintain previous behavior

#### Behavioral Improvements
- **Initial state handling** - Callbacks no longer invoked on initial state capture to avoid empty changes
- **Lock-free callbacks** - Callbacks now execute outside of internal locks to prevent contention with slow user code

### Dependencies
- **tokio-util 0.7** - Added for `CancellationToken` support
- **tokio sync feature** - Added "sync" feature to tokio dependency

### Migration Guide

**Before (v1.3.2 and earlier):**
```rust
// No cancellation support
monitor.monitor_printer("Printer", 30000, |current, previous| {
    // callback logic
}).await?;
```

**After (v1.4.0+):**
```rust
use printer_event_handler::CancellationToken;

// With cancellation support
let cancel_token = CancellationToken::new();
let token_clone = cancel_token.clone();

let handle = tokio::spawn(async move {
    monitor.monitor_printer("Printer", 30000, Some(token_clone), |current, previous| {
        // callback logic
    }).await
});

// Later: cancel monitoring gracefully
cancel_token.cancel();
handle.await??;

// Or without cancellation (backward compatible)
monitor.monitor_printer("Printer", 30000, None, |current, previous| {
    // callback logic
}).await?;
```

**Cloneable Monitor:**
```rust
// Efficient sharing across tasks
let monitor = PrinterMonitor::new().await?;
let monitor_clone = monitor.clone(); // Cheap Arc clone

tokio::spawn(async move {
    monitor_clone.list_printers().await
});
```

### Technical Details
- **Performance** - No performance degradation; cancellation checks are lightweight
- **Memory efficiency** - Arc-based sharing reduces memory overhead for multi-printer monitoring
- **Backward compatibility** - Passing `None` for cancel_token maintains existing behavior
- **Cross-platform** - All improvements work identically on Windows and Linux

### Benefits
- **Production-ready** - Graceful shutdown enables proper service lifecycle management
- **Resource efficient** - Shared backend connections reduce system resource usage
- **Better testing** - Comprehensive test suite improves reliability and maintainability
- **Modern async patterns** - Follows Tokio best practices for cancellation and shutdown

## [1.3.2] - 2025-08-19

### Changed

#### Millisecond Precision Intervals - BREAKING CHANGE
- **Parameter change**: All monitoring functions now use milliseconds instead of seconds for interval parameters
- **Function signatures updated**: `interval_secs: u64``interval_ms: u64` in all monitoring methods:
  - `monitor_printer(printer_name, interval_ms, callback)`
  - `monitor_printer_changes(printer_name, interval_ms, callback)`
  - `monitor_property(printer_name, property, interval_ms, callback)`
  - `monitor_multiple_printers(printer_names, interval_ms, callback)`

### Added

#### Enhanced Monitoring Precision
- **Sub-second monitoring**: Can now monitor printer changes at intervals less than 1 second
- **Millisecond granularity**: Precise control over monitoring frequency (100ms, 500ms, etc.)
- **Common interval examples**: Documentation includes common millisecond values for different use cases
- **High-frequency monitoring**: Support for rapid change detection in time-sensitive applications

### Updated

#### Documentation and Examples
- **README.md**: Updated all examples to use millisecond values (30000ms instead of 30s)
- **Code examples**: All monitoring examples updated with millisecond intervals
- **CLI application**: Updated to use 60000ms (60 seconds) instead of 60s
- **Library documentation**: Updated inline documentation and code examples
- **Examples directory**: All example files updated to use millisecond precision

### Migration Guide

**Before (v1.3.1 and earlier - seconds):**
```rust
// 30 seconds interval (using seconds)
monitor.monitor_printer("Printer", 30, callback).await?;
monitor.monitor_property("Printer", property, 60, callback).await?;
```

**After (v1.3.2+ - milliseconds):**
```rust
// 30 seconds = 30000 milliseconds
monitor.monitor_printer("Printer", 30000, callback).await?;
monitor.monitor_property("Printer", property, 60000, callback).await?;

// New precision capabilities:
monitor.monitor_printer("Printer", 500, callback).await?;  // 0.5 seconds
monitor.monitor_printer("Printer", 100, callback).await?;  // 0.1 seconds
```

**Migration Steps:**
1. Multiply all existing interval values by 1000
2. Consider if you need higher precision monitoring (sub-second intervals)
3. Update any hardcoded interval values in your code

### Technical Details
- **Performance**: No performance impact - same underlying `Duration::from_millis()` usage
- **Precision**: Can now handle intervals as low as 1ms (though not recommended for printer monitoring)
- **Backward compatibility**: Breaking change - requires code updates for interval values
- **Cross-platform**: Works identically on Windows and Linux

### Benefits
- **Fine-grained control**: Monitor rapid printer state changes in real-time applications
- **Flexible intervals**: Choose optimal monitoring frequency for different use cases
- **Better responsiveness**: Detect printer changes faster when needed
- **Production flexibility**: Adjust monitoring precision based on system requirements

## [1.3.1] - 2025-08-19

### Added

#### Type-Safe Property Monitoring
- **`MonitorableProperty` enum** - New strongly-typed enum for specifying properties to monitor
- **Type-safe `monitor_property()` API** - Replaces string-based property names with enum variants
- **Complete property coverage** - All 12 monitorable printer properties available as enum variants:
  - `Name` - Printer name changes
  - `Status` - PrinterStatus enum changes (recommended)
  - `State` - PrinterState enum changes (legacy Windows)
  - `ErrorState` - ErrorState enum changes
  - `IsOffline` - Online/offline status changes
  - `IsDefault` - Default printer designation changes
  - `PrinterStatusCode` - Raw PrinterStatus code changes (1-7)
  - `PrinterStateCode` - Raw PrinterState code changes (.NET flags)
  - `DetectedErrorStateCode` - Raw DetectedErrorState code changes (0-11)
  - `ExtendedDetectedErrorStateCode` - Raw ExtendedDetectedErrorState code changes
  - `ExtendedPrinterStatusCode` - Raw ExtendedPrinterStatus code changes
  - `WmiStatus` - WMI Status property changes

### Enhanced

#### Developer Experience
- **IDE auto-completion** - MonitorableProperty enum provides IntelliSense support
- **Compile-time validation** - Invalid property names caught at compile time instead of runtime
- **Self-documenting code** - Each enum variant includes descriptive documentation
- **Helper methods** - `as_str()`, `description()`, and `all()` methods for convenience

#### API Improvements
- **Backward compatible** - Internal string conversion maintains existing functionality
- **Future-proof design** - Easy to add new properties while maintaining API stability
- **Better error prevention** - Eliminates typos in property name strings

### Updated

#### Documentation
- **README.md** - Added complete MonitorableProperty documentation with usage examples
- **Library documentation** - Updated main example to showcase type-safe property monitoring
- **Examples** - Updated `property_monitoring.rs` to use new enum-based API
- **API Reference** - Added MonitorableProperty to core types documentation

#### Examples
- **`property_monitoring.rs`** - Now demonstrates type-safe property selection
- **Type-safe examples** - Shows usage of `MonitorableProperty::IsOffline` and `MonitorableProperty::Status`

### Migration Guide

**Before (v1.3.0 and earlier):**
```rust
monitor.monitor_property("Printer", "IsOffline", 60, |change| {
    println!("Change: {}", change.description());
}).await?;
```

**After (v1.3.1+):**
```rust
use printer_event_handler::MonitorableProperty;

monitor.monitor_property("Printer", MonitorableProperty::IsOffline, 60, |change| {
    println!("Change: {}", change.description());
}).await?;
```

### Technical Details
- **No breaking changes** - Existing string-based usage still works internally
- **Performance** - No runtime overhead, enum converts to string internally
- **Compile-time safety** - Invalid properties caught during compilation
- **Cross-platform** - Works identically on Windows and Linux

## [1.3.0] - 2025-01-18

### Fixed

#### PrinterState Accuracy - BREAKING INTERNAL CHANGE
- **Correct WMI Value Mapping** - Fixed critical issue where PrinterState enum used incorrect 0-25 range instead of actual WMI values
- **Real WMI Values** - PrinterState now correctly handles actual WMI values like 1024 (Printing), 16384 (Processing), 128 (Offline)
- **.NET PrintQueueStatus Implementation** - Replaced PrinterState with proper .NET PrintQueueStatus flag-based system
- **Bitwise Flag Support** - PrinterState now properly handles multiple concurrent states using bitwise flags
- **Priority-Based Selection** - When multiple flags are set, selects the most significant state (errors → active → idle)

#### Enhanced Property Monitoring
- **Property Change Detection** - Added `PropertyChange` enum for tracking individual property changes
- **Detailed Monitoring** - New `monitor_printer_changes()` method for granular change detection  
- **Property-Specific Monitoring** - New `monitor_property()` method for watching individual properties
- **Multi-Printer Monitoring** - New `monitor_multiple_printers()` method for concurrent monitoring
- **Property Change Collection** - New `PrinterChanges` struct for organizing detected changes

### Added

#### .NET PrintQueueStatus Flag Values
- **Complete Flag Coverage** - All 23 PrintQueueStatus flag values now supported:
  - `None` (0), `Paused` (1), `Error` (2), `PendingDeletion` (4)
  - `PaperJam` (8), `PaperOut` (16), `ManualFeed` (32), `PaperProblem` (64)
  - `Offline` (128), `IOActive` (256), `Busy` (512), `Printing` (1024)
  - `OutputBinFull` (2048), `NotAvailable` (4096), `Waiting` (8192)
  - `Processing` (16384), `Initializing` (32768), `WarmingUp` (65536)
  - `TonerLow` (131072), `NoToner` (262144), `PagePunt` (524288)
  - `UserInterventionRequired` (1048576), `OutOfMemory` (2097152)
  - `DoorOpen` (4194304), `ServerUnknown` (8388608), `PowerSave` (16777216)

#### Enhanced Status Detection
- **Smart Flag Interpretation** - Prioritized flag parsing (errors first, then active states, then idle)
- **Status Conversion Methods** - `is_error()` and `is_offline()` methods for PrinterState
- **PrinterStatus Mapping** - Improved `to_printer_status()` conversion for compatibility

### Enhanced
- **API Compatibility** - No breaking changes to public API despite internal restructure
- **Accurate Status Display** - CLI now shows correct status for real printer values
- **Comprehensive Examples** - New property_monitoring.rs example demonstrating advanced features
- **Documentation** - Updated README with accurate PrinterState flag values and examples

### Technical Details
- **Microsoft Documentation Compliance** - Now follows [.NET PrintQueueStatus]https://learn.microsoft.com/en-us/dotnet/api/system.printing.printqueuestatus specification
- **Backward Compatible** - All existing API methods work unchanged
- **Performance** - Enhanced priority-based flag parsing for efficient status determination
- **Testing** - All library tests updated and pass with new implementation

## [1.2.0] - 2025-01-18

### Added

#### Complete WMI Property Access
- **Raw Status Code Getters** - Access all numeric WMI status codes:
  - `printer_status_code()` → PrinterStatus (1-7, current/recommended property)
  - `printer_state_code()` → PrinterState (.NET PrintQueueStatus flags)
  - `detected_error_state_code()` → DetectedErrorState (0-11)
  - `extended_printer_status_code()` → ExtendedPrinterStatus 
  - `extended_detected_error_state_code()` → ExtendedDetectedErrorState
  - `wmi_status()` → Status property string ("OK", "Degraded", "Error", etc.)

#### Human-Readable Description Methods
- **Status Code Descriptions** - Get human-readable descriptions for all status codes:
  - `printer_status_description()` → "Idle", "Printing", "Other", etc.
  - `printer_state_description()` → "Paper Jam", "Toner Low", "Busy", etc.
  - `detected_error_state_description()` → "No Paper", "Jammed", etc.
  - `extended_printer_status_description()` → Extended status descriptions

#### Enhanced WMI Integration
- **Additional WMI Properties** - Now queries ExtendedDetectedErrorState and Status properties
- **Complete Property Storage** - Printer struct stores all raw WMI status codes
- **Comprehensive Constructor** - New `new_with_wmi()` method for complete WMI data

#### Improved Offline Detection
- **ExtendedPrinterStatus Support** - Uses ExtendedPrinterStatus=7 for offline detection
- **WMI Status Integration** - Uses Status property ("Degraded", "Error", etc.) for offline detection
- **Multi-Property Logic** - Enhanced offline detection using all available WMI properties

### Enhanced
- **Comprehensive WMI Coverage** - Complete access to all Win32_Printer properties
- **Debug Information** - CLI now displays detailed WMI information for analysis
- **Documentation** - Updated all documentation with new getter methods and examples

### Technical Details
- **API Expansion** - Added 10+ new getter methods for complete WMI property access
- **Backward Compatible** - All existing API methods preserved
- **Performance** - Single WMI query retrieves all properties efficiently

## [1.1.0] - 2025-01-17

### Added

#### Comprehensive Win32_Printer Support  
- **Complete PrinterState mapping** - Added support for 26 PrinterState values (0-25) based on Win32_Printer documentation:
  - `Paused` (1) - Printer paused
  - `Error` (2) - General error state
  - `PendingDeletion` (3) - Queued for deletion
  - `PaperJam` (4) - Paper jam detected
  - `PaperOut` (5) - Out of paper
  - `ManualFeed` (6) - Manual feed required
  - `PaperProblem` (7) - Paper-related issue
  - `IOActive` (9) - I/O operations active
  - `Busy` (10) - Printer busy
  - `OutputBinFull` (12) - Output tray full
  - `NotAvailable` (13) - Printer not available
  - `Waiting` (14) - Waiting for job
  - `Processing` (15) - Processing job
  - `Initialization` (16) - Initializing
  - `TonerLow` (18) - Low toner/ink
  - `NoToner` (19) - Out of toner/ink
  - `PagePunt` (20) - Page punt condition
  - `UserInterventionRequired` (21) - User action needed
  - `OutOfMemory` (22) - Memory full
  - `DoorOpen` (23) - Cover/door open
  - `ServerUnknown` (24) - Server status unknown
  - `PowerSave` (25) - Power save mode

#### Enhanced Error State Detection
- **Complete DetectedErrorState mapping** - Now supports all 12 DetectedErrorState values (0-11)
- **Fixed value 0 mapping** - Correctly maps DetectedErrorState=0 to `NoError` for better real-world compatibility
- **Added OutputBinFull support** - DetectedErrorState=11 now properly mapped

#### Improved Offline Detection
- **Enhanced offline logic** - Printers with status `Error`, `NotAvailable`, or `ServerUnknown` are now correctly marked as offline
- **Consistent status reporting** - Fixed issue where printers showed `Status: Offline` but `Offline: No`

### Fixed
- **PrinterState value 0** - Now correctly maps to `Idle` instead of falling through to `StatusUnknown`
- **PrinterState value 128** - Legacy offline state properly handled for backward compatibility
- **DetectedErrorState practical mapping** - Value 0 now maps to `NoError` instead of `UnknownError` for better user experience

### Enhanced
- **Fallback logic** - Improved PrinterState/PrinterStatus fallback when one field has unmapped values
- **Documentation** - Complete coverage of all supported status values in README.md and API docs
- **Cross-platform compatibility** - Linux backend remains fully functional with new Windows enum variants

### Technical Details
- **Microsoft Win32_Printer compliance** - Implementation based on [official documentation]https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-printer
- **No breaking changes** - All existing enum variants preserved, only additions made
- **Status mapping validation** - Enum values tested against available printer data

**Note**: The 0-25 range mapping was later discovered to be incorrect in v1.3.0. Actual WMI values use .NET PrintQueueStatus flags.

## [1.0.0] - 2024-XX-XX

### Added
- Initial release
- Cross-platform printer monitoring (Windows WMI, Linux CUPS)
- Basic printer status detection
- Async/await support with Tokio
- CLI interface for printer monitoring
- Core PrinterStatus and ErrorState enums
- Real-time printer monitoring capabilities

### Features
- Windows WMI backend for printer detection
- Linux CUPS backend with lpstat integration
- Printer discovery and enumeration
- Status change monitoring with callbacks
- Error state detection and reporting
- Cross-platform API compatibility