• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

cbruiz / printhor / 13775596467

10 Mar 2025 09:59PM UTC coverage: 90.713% (-0.02%) from 90.734%
13775596467

push

github

web-flow
Review/motion optimizations (#36)

* Module refactoring and light doc improvement
* Bump embassy upstream

184 of 218 new or added lines in 16 files covered. (84.4%)

11 existing lines in 1 file now uncovered.

14837 of 16356 relevant lines covered (90.71%)

733512.36 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.71
/printhor-hwa-common/src/event_bus.rs
1
//! The state manager controller.
2
//!
3
//! This module provides a global asynchronous event bus.
4
use crate as hwa;
5
use core::fmt::Formatter;
6
use core::ops::{BitAnd, BitOr};
7
use hwa::event_bus_channel::{EventBusChannelController, EventBusSubscriber};
8
use printhor_hwa_utils::*;
9

10
#[const_env::from_env("EVENT_BUS_NUM_SUBSCRIBERS")]
11
const EVENT_BUS_NUM_SUBSCRIBERS: usize = 6;
12

13
pub type EventBusPubSubType<M> =
14
    embassy_sync::pubsub::PubSubChannel<M, EventFlags, 1, EVENT_BUS_NUM_SUBSCRIBERS, 1>;
15
pub type EventBusPublisherType<M> =
16
    embassy_sync::pubsub::Publisher<'static, M, EventFlags, 1, EVENT_BUS_NUM_SUBSCRIBERS, 1>;
17
pub type EventBusSubscriberType<'a, M> =
18
    embassy_sync::pubsub::Subscriber<'a, M, EventFlags, 1, EVENT_BUS_NUM_SUBSCRIBERS, 1>;
19

20
//#region "Event Flags"
21

22
bitflags::bitflags! {
23
    /// Structure representing a collection of event flags.
24
    ///
25
    /// `EventFlags` is a bitflags structure used to define different states and conditions
26
    /// within the system. Each event flag represents a specific state or condition, and
27
    /// multiple flags can be combined using bitwise operations to track composite states.
28
    ///
29
    /// # Variants
30
    ///
31
    /// - `NOTHING`: Special flag meaning no expectations.
32
    /// - `SYS_ALARM`: System alarm flag.
33
    /// - `SYS_BOOTING`: System is booting.
34
    /// - `SYS_BOOT_FAILURE`: System boot failure.
35
    /// - `SYS_READY`: System is ready.
36
    /// - `ATX_ON`: ATX power is on.
37
    /// - `HOMING`: Homing operation in progress.
38
    /// - `MOVING`: System is moving.
39
    /// - `MOV_QUEUE_EMPTY`: Movement queue is empty.
40
    /// - `MOV_QUEUE_FULL`: Movement queue is full.
41
    /// - `JOB_PRINTING`: Job printing in progress.
42
    /// - `JOB_PAUSED`: Job is paused.
43
    /// - `JOB_COMPLETED`: Job completed.
44
    /// - `DRY_RUN`: Do nothing. Just interpret.
45
    /// - `HOT_BED_TEMP_OK`: HotBed temperature is okay.
46
    /// - `HOT_END_TEMP_OK`: HotEnd temperature is okay.
47
    ///
48
    /// # Examples
49
    ///
50
    /// Basic usage:
51
    ///
52
    /// ```rust
53
    /// use printhor_hwa_common as hwa;
54
    /// use hwa::EventFlags;
55
    ///
56
    /// let mut flags = EventFlags::empty();
57
    ///
58
    /// // Set the SYS_READY and ATX_ON flags
59
    /// flags.insert(EventFlags::SYS_READY | EventFlags::ATX_ON);
60
    ///
61
    /// // Check if a specific flag is set
62
    /// if flags.contains(EventFlags::SYS_READY) {
63
    ///     // Do something if the system is ready
64
    /// }
65
    ///
66
    /// // Remove a flag
67
    /// flags.remove(EventFlags::ATX_ON);
68
    /// ```
69
    #[derive(Clone, Copy, PartialEq)]
70
    pub struct EventFlags: u16 {
71
        /// Special flag meaning no expectations
72
        const NOTHING          =  0b0000000000000000;
73
        /// System alarm flag
74
        const SYS_ALARM        =  0b1000000000000000;
75
        /// System is booting
76
        const SYS_BOOTING      =  0b0100000000000000;
77
        /// System boot failure
78
        const SYS_BOOT_FAILURE =  0b0010000000000000;
79
        /// System is ready
80
        const SYS_READY        =  0b0001000000000000;
81
        /// ATX power is on
82
        const ATX_ON           =  0b0000100000000000;
83
        /// Homing operation in progress
84
        const HOMING          =   0b0000010000000000;
85
        /// System is moving
86
        const MOVING           =  0b0000001000000000;
87
        /// Movement queue is empty
88
        const MOV_QUEUE_EMPTY  =  0b0000000100000000;
89
        /// Movement queue is full
90
        const MOV_QUEUE_FULL   =  0b0000000010000000;
91
        /// Job printing in progress
92
        const JOB_PRINTING     =  0b0000000001000000;
93
        /// Job is paused
94
        const JOB_PAUSED       =  0b0000000000100000;
95
        /// Job completed
96
        const JOB_COMPLETED    =  0b0000000000010000;
97
        /// Dry Run (do nothing. Just interpret)
98
        const DRY_RUN          =  0b0000000000001000;
99
        /// HotBed temperature is okay
100
        const HOT_BED_TEMP_OK   = 0b0000000000000100;
101
        /// HotEnd temperature is okay
102
        const HOT_END_TEMP_OK   = 0b0000000000000010;
103
    }
104
}
105

106
#[cfg(feature = "with-defmt")]
107
impl defmt::Format for EventFlags {
108
    fn format(&self, fmt: defmt::Formatter) {
109
        let mut first = true;
110
        for (flag_name, _) in self.iter_names() {
111
            if !first {
112
                defmt::write!(fmt, " ");
113
            } else {
114
                first = false;
115
            }
116
            defmt::write!(fmt, "{}", flag_name)
117
        }
118
    }
119
}
120

121
impl core::fmt::Debug for EventFlags {
122
    fn fmt(&self, fmt: &mut Formatter<'_>) -> core::fmt::Result {
8✔
123
        let mut first = true;
8✔
124
        for (flag_name, _flag_bits) in self.iter_names() {
24✔
125
            if !first {
24✔
126
                core::write!(fmt, " ")?;
16✔
127
            } else {
8✔
128
                first = false;
8✔
129
            }
8✔
130
            core::write!(fmt, "{}", flag_name)?;
24✔
131
        }
132
        Ok(())
8✔
133
    }
8✔
134
}
135
//#endregion
136

137
//#region "Event Status"
138

139
/// Represents the status of an event with associated flags and mask.
140
///
141
/// The `EventStatus` structure holds two primary fields:
142
/// - `flags`: Contains the status of relevant bit values (set or unset) for the bits set in mask.
143
/// - `mask`: Defines which bits in the `flags` field are relevant for event matching.
144
#[derive(Clone, Copy)]
145
pub struct EventStatus {
146
    /// Contains the status of relevant bit values (set or unset) for the bits set in mask.
147
    pub flags: EventFlags,
148
    /// Defines which bits in the `flags` field are relevant for event matching.
149
    pub mask: EventFlags,
150
}
151

152
impl EventStatus {
153
    /// Updates the `flags` and `mask` of the current `EventStatus` by complementing and
154
    /// bitwise ANDing with the provided `flags` for `flags`, and bitwise ORing with the
155
    /// provided `flags` for `mask`.
156
    ///
157
    /// This method applies a bitwise AND between the current `flags` and the complement of
158
    /// the provided `flags`, and applies a bitwise OR between the current `mask` and the
159
    /// provided `flags`. This allows selective modification of the current event state and
160
    /// its relevance mask.
161
    ///
162
    /// # Parameters
163
    ///
164
    /// - `flags`: The `EventFlags` value to apply for the updates.
165
    ///
166
    /// # Returns
167
    ///
168
    /// A new `EventStatus` with updated `flags` and `mask` based on the provided `flags`.
169
    ///
170
    /// # Examples
171
    ///
172
    /// ```
173
    /// use printhor_hwa_common as hwa;
174
    /// use hwa::EventFlags;
175
    /// use hwa::EventStatus;
176
    ///
177
    /// // Initial EventStatus with no flags set
178
    /// let mut event_status = EventStatus::new();
179
    ///
180
    /// // EventStatus updated to exclude certain flags and add to the mask
181
    /// let updated_event_status = event_status.and_not_containing(EventFlags::SYS_BOOTING);
182
    /// ```
183
    #[allow(unused)]
184
    #[inline]
185
    pub const fn new() -> Self {
8✔
186
        Self {
8✔
187
            flags: EventFlags::empty(),
8✔
188
            mask: EventFlags::empty(),
8✔
189
        }
8✔
190
    }
8✔
191

192
    /// Returns an `EventStatus` instance with all bits set in the `flags` and `mask` fields.
193
    ///
194
    /// This method initializes the `flags` field with the value provided by
195
    /// the `flags` parameter and sets the `mask` field with the same value.
196
    /// It essentially creates an `EventStatus` where all bits in `flags` are
197
    /// considered relevant for event checks.
198
    ///
199
    /// # Parameters
200
    ///
201
    /// - `flags`: An `EventFlags` value that represents the current state or
202
    /// condition of the event, used to initialize both the `flags` and `mask` fields.
203
    ///
204
    /// # Returns
205
    ///
206
    /// An `EventStatus` instance where `flags` is set to the provided `EventFlags` value
207
    /// and `mask` is set to the same value, indicating that all bits in `flags` are relevant.
208
    ///
209
    /// # Examples
210
    ///
211
    /// ```
212
    /// use printhor_hwa_common as hwa;
213
    /// use hwa::EventFlags;
214
    /// use hwa::EventStatus;
215
    ///
216
    /// // An event containging SYS_BOOTING flag
217
    /// let event_status = EventStatus::containing(EventFlags::SYS_BOOTING);
218
    /// ```
219
    #[inline]
220
    pub const fn containing(flags: EventFlags) -> Self {
1,269,328✔
221
        Self { flags, mask: flags }
1,269,328✔
222
    }
1,269,328✔
223

224
    /// Returns an `EventStatus` instance with the complement of the provided `flags` set in the `flags` field
225
    /// and the original `flags` set in the `mask` field.
226
    ///
227
    /// This method initializes the `flags` field with the complement of the value provided by
228
    /// the `flags` parameter and sets the `mask` field with the original value.
229
    /// It creates an `EventStatus` where all bits not in the provided `flags` are considered relevant
230
    /// for event checks.
231
    ///
232
    /// # Parameters
233
    ///
234
    /// - `flags`: An `EventFlags` value that represents the current state or
235
    /// condition of the event, used to initialize the `flags` and `mask` fields.
236
    ///
237
    /// # Returns
238
    ///
239
    /// An `EventStatus` instance where `flags` is set to the complement of the provided `EventFlags` value
240
    /// and `mask` is set to the original value, indicating that all bits not in `flags` are relevant.
241
    ///
242
    /// # Examples
243
    ///
244
    /// ```
245
    /// use printhor_hwa_common as hwa;
246
    /// use hwa::EventFlags;
247
    /// use hwa::EventStatus;
248
    ///
249
    /// // An event not containing the SYS_BOOTING flag
250
    /// let event_status = EventStatus::not_containing(EventFlags::SYS_BOOTING);
251
    /// ```
252
    #[inline]
253
    pub const fn not_containing(flags: EventFlags) -> Self {
1,246,161✔
254
        Self {
1,246,161✔
255
            flags: flags.complement(),
1,246,161✔
256
            mask: flags,
1,246,161✔
257
        }
1,246,161✔
258
    }
1,246,161✔
259

260
    /// Returns a new `EventStatus` instance with the complement of the provided `flags` bitwise AND
261
    /// with the current `flags` field, and the provided `flags` bitwise OR with the current `mask` field.
262
    ///
263
    /// This method computes a new `flags` field by taking the bitwise AND of the current `flags` and the
264
    /// complement of the provided `flags`. The `mask` field is updated by taking the bitwise OR of the
265
    /// current `mask` and the provided `flags`.
266
    ///
267
    /// # Parameters
268
    ///
269
    /// - `flags`: An `EventFlags` value that will be used to update the `flags` and `mask` fields.
270
    ///
271
    /// # Returns
272
    ///
273
    /// An `EventStatus` instance where the `flags` field is the result of the current `flags` AND the complement
274
    /// of the provided `EventFlags`, and the `mask` field is the result of the current `mask` OR the provided
275
    /// `EventFlags`.
276
    ///
277
    /// # Examples
278
    ///
279
    /// ```
280
    /// use printhor_hwa_common as hwa;
281
    /// use hwa::EventFlags;
282
    /// use hwa::EventStatus;
283
    ///
284
    /// let current_status = EventStatus::containing(EventFlags::SYS_BOOTING)
285
    ///     .and_not_containing(EventFlags::SYS_READY);
286
    /// ```
287
    #[allow(unused)]
288
    #[inline]
289
    pub fn and_containing(&self, flags: EventFlags) -> Self {
20,643✔
290
        Self {
20,643✔
291
            flags: self.flags.bitor(flags),
20,643✔
292
            mask: self.mask.bitor(flags),
20,643✔
293
        }
20,643✔
294
    }
20,643✔
295

296
    /// Returns a new `EventStatus` instance with the provided `flags` removed from the current `flags` field,
297
    /// and the provided `flags` bitwise OR with the current `mask` field.
298
    ///
299
    /// This method computes a new `flags` field by taking the bitwise AND of the current `flags` and the
300
    /// complement of the provided `flags`. The `mask` field is updated by taking the bitwise OR of the
301
    /// current `mask` and the provided `flags`.
302
    ///
303
    /// # Parameters
304
    ///
305
    /// - `flags`: An `EventFlags` value that represents the current state or condition of the event,
306
    /// which will be used to update the `flags` and `mask` fields.
307
    ///
308
    /// # Returns
309
    ///
310
    /// An `EventStatus` instance where the `flags` field is the result of the current `flags` AND the
311
    /// complement of the provided `EventFlags`, and the `mask` field is the result of the current `mask` OR
312
    /// the provided `EventFlags`.
313
    ///
314
    /// # Examples
315
    ///
316
    /// ```
317
    /// use printhor_hwa_common as hwa;
318
    /// use hwa::EventFlags;
319
    /// use hwa::EventStatus;
320
    ///
321
    /// let current_status = EventStatus::containing(EventFlags::SYS_BOOTING)
322
    ///     .and_not_containing(EventFlags::SYS_READY);
323
    /// ```
324
    #[allow(unused)]
325
    #[inline]
326
    pub fn and_not_containing(&self, flags: EventFlags) -> Self {
33✔
327
        Self {
33✔
328
            flags: self.flags.bitand(flags.complement()),
33✔
329
            mask: self.mask.bitor(flags),
33✔
330
        }
33✔
331
    }
33✔
332
}
333

334
cfg_if::cfg_if! {
335
    if #[cfg(feature="with-defmt")] {
336
        impl defmt::Format for EventStatus {
337
            fn format(&self, fmt: defmt::Formatter) {
338
                let mut first = true;
339
                for (flag_name, flag_bits) in self.mask.iter_names() {
340
                    if !first {
341
                        defmt::write!(fmt, " & ");
342
                    }
343
                    else {
344
                        first = false;
345
                    }
346
                    if self.flags.contains(flag_bits) {
347
                        defmt::write!(fmt, "{}", flag_name);
348
                    }
349
                    else {
350
                        defmt::write!(fmt, "!{}", flag_name);
351
                    }
352
                }
353
            }
354
        }
355
    }
356
}
357
impl core::fmt::Debug for EventStatus {
UNCOV
358
    fn fmt(&self, fmt: &mut Formatter<'_>) -> core::fmt::Result {
×
UNCOV
359
        let mut first = true;
×
UNCOV
360
        for (flag_name, flag_bits) in self.mask.iter_names() {
×
UNCOV
361
            if !first {
×
362
                core::write!(fmt, " & ")?;
×
UNCOV
363
            } else {
×
UNCOV
364
                first = false;
×
UNCOV
365
            }
×
UNCOV
366
            if self.flags.contains(flag_bits) {
×
367
                core::write!(fmt, "{}", flag_name)?;
×
368
            } else {
UNCOV
369
                core::write!(fmt, "!{}", flag_name)?;
×
370
            }
371
        }
UNCOV
372
        Ok(())
×
UNCOV
373
    }
×
374
}
375

376
//#endregion
377

378
//#region "Event Bus"
379

380
/// A struct representing a reference to the `Event Bus`.
381
///
382
/// The [GenericEventBus] provides various methods to interact with the internal pub-sub channel,
383
/// including publishing events, getting the current status, checking specific flags,
384
/// and subscribing to event notifications.
385
///
386
/// # Generics
387
///
388
/// * `H` is the MutexStrategy (an instance of the trait [AsyncMutexStrategy]) to choose the locking strategy.
389
/// * `M` is the MutexType (an instance of the trait [hwa::AsyncRawMutex]) of the inner pub-sub mechanism.
390
///
391
/// # Examples
392
///
393
/// ```rust
394
/// use printhor_hwa_common as hwa;
395
///
396
/// type ChannelControllerMutexType = hwa::AsyncCsMutexType;
397
/// type PubSubMutexType = hwa::AsyncCsMutexType;
398
/// type ResourceType = hwa::EventBusChannelController<PubSubMutexType>;
399
/// type MutexStrategyType = hwa::AsyncStandardStrategy<ChannelControllerMutexType, ResourceType>;
400
///
401
/// let _controller = hwa::GenericEventBus::new(
402
///     hwa::make_static_async_controller!(
403
///         "EventBus",
404
///         MutexStrategyType,
405
///         hwa::EventBusChannelController::new(
406
///             hwa::make_static_ref!(
407
///                 "EventBusChannel",
408
///                 hwa::EventBusPubSubType<PubSubMutexType>,
409
///                 hwa::EventBusPubSubType::new(),
410
///             )
411
///         ),
412
///     )
413
/// );
414
/// ```
415
///
416
/// # Fields
417
///
418
/// * `instance` - A reference to the controller wrapping the `GenericEventBus`.
419
pub struct GenericEventBus<H, M>
420
where
421
    H: AsyncMutexStrategy<Resource = EventBusChannelController<M>> + 'static,
422
    M: hwa::AsyncRawMutex + 'static,
423
{
424
    channel_controller: StaticAsyncController<H>,
425
}
426

427
impl<H, M> Clone for GenericEventBus<H, M>
428
where
429
    H: AsyncMutexStrategy<Resource = EventBusChannelController<M>> + 'static,
430
    M: hwa::AsyncRawMutex + 'static,
431
{
432
    fn clone(&self) -> Self {
66✔
433
        GenericEventBus::new(self.channel_controller.clone())
66✔
434
    }
66✔
435
}
436

437
impl<H, M> GenericEventBus<H, M>
438
where
439
    H: AsyncMutexStrategy<Resource = EventBusChannelController<M>> + 'static,
440
    M: hwa::AsyncRawMutex + 'static,
441
{
442
    pub const fn new(channel_controller: StaticAsyncController<H>) -> Self {
93✔
443
        Self { channel_controller }
93✔
444
    }
93✔
445

446
    /// Publishes an event to the event bus asynchronously, updating the status flags if there are changes.
447
    ///
448
    /// The method takes an `EventStatus` struct which contains the event flags and a mask. It computes
449
    /// the incoming bits, identifies changes against the current status, and updates the status flags
450
    /// accordingly. If there are changes, it publishes the new status immediately using the publisher.
451
    ///
452
    /// # Arguments
453
    ///
454
    /// * `event` - An `EventStatus` instance containing the event flags and mask.
455
    ///
456
    /// # Examples
457
    ///
458
    /// Basic usage:
459
    ///
460
    /// ```rust
461
    /// use printhor_hwa_common as hwa;
462
    /// use hwa::{GenericEventBus, EventFlags, EventStatus};
463
    ///
464
    /// // A Holdable mutex requires a Sync MutexType
465
    /// type ChannelControllerMutexType = hwa::AsyncCsMutexType;
466
    /// type PubSubMutexType = hwa::AsyncCsMutexType;
467
    /// type ResourceType = hwa::EventBusChannelController<PubSubMutexType>;
468
    /// type EventBusMutexStrategyType = hwa::AsyncHoldableStrategy<ChannelControllerMutexType, ResourceType>;
469
    ///
470
    /// async fn assumed_initialization(event_bus: GenericEventBus<EventBusMutexStrategyType, PubSubMutexType>) {
471
    ///     event_bus.publish_event(EventStatus::not_containing(EventFlags::SYS_READY)).await
472
    /// }
473
    /// // [...]
474
    /// async fn event_routine(event_bus: GenericEventBus<EventBusMutexStrategyType, PubSubMutexType>) {
475
    ///     // Update the event bus notifying that System is NOW ready
476
    ///     event_bus.publish_event(EventStatus::containing(EventFlags::SYS_READY)).await;
477
    /// }
478
    /// ```
479
    ///
480
    pub async fn publish_event(&self, event: EventStatus) {
1,684,968✔
481
        let mut req = self.channel_controller.lock().await;
1,684,968✔
482
        req.publish_event(event);
1,684,968✔
483
    }
1,684,968✔
484

485
    pub async fn get_status(&self) -> EventFlags {
440,726✔
486
        let req = self.channel_controller.lock().await;
440,726✔
487
        req.get_status()
440,726✔
488
    }
440,726✔
489

490
    /// Checks if the specified flags are set in the current status.
491
    ///
492
    /// This method locks the event bus instance, retrieves the current status,
493
    /// and checks if all bits specified in the `flags` argument are set.
494
    ///
495
    /// # Arguments
496
    ///
497
    /// * `flags` - An `EventFlags` instance containing the flags to check.
498
    ///
499
    /// # Returns
500
    ///
501
    /// `true` if all specified flags are set; `false` otherwise.
502
    ///
503
    /// # Examples
504
    ///
505
    /// Basic usage:
506
    ///
507
    /// ```rust
508
    /// use printhor_hwa_common as hwa;
509
    /// use hwa::{GenericEventBus, EventFlags, EventStatus};    ///
510
    ///
511
    /// type ChannelControllerMutexType = hwa::AsyncNoopMutexType;
512
    /// type PubSubMutexType = hwa::AsyncNoopMutexType;
513
    /// type ResourceType = hwa::EventBusChannelController<PubSubMutexType>;
514
    /// type EventBusMutexStrategyType = hwa::AsyncStandardStrategy<ChannelControllerMutexType, ResourceType>;
515
    ///
516
    ///
517
    /// async fn assumed_initialization(event_bus: GenericEventBus<EventBusMutexStrategyType, PubSubMutexType>) {
518
    ///     event_bus.publish_event(EventStatus::not_containing(EventFlags::SYS_READY)).await
519
    /// }
520
    ///
521
    /// async fn checking_routine(event_bus: GenericEventBus<EventBusMutexStrategyType, PubSubMutexType>) {
522
    ///     if event_bus.has_flags(EventFlags::SYS_READY).await {
523
    ///         // System is ready
524
    ///         // ...
525
    ///     }
526
    ///     else {
527
    ///         // System is not *CURRENTLY* ready
528
    ///         // ...
529
    ///     }
530
    /// }
531
    ///
532
    /// ```
533
    pub async fn has_flags(&self, flags: EventFlags) -> bool {
414,866✔
534
        let req = self.channel_controller.lock().await;
414,866✔
535
        req.get_status().bitand(flags).eq(&flags)
414,866✔
536
    }
414,866✔
537

538
    pub async fn subscriber(&self) -> EventBusSubscriber<'static, M> {
28✔
539
        let mut req = self.channel_controller.lock().await;
28✔
540
        let inner = req.subscriber().expect("Exceeded");
28✔
541
        EventBusSubscriber::new(inner, req.get_status())
28✔
542
    }
28✔
543
}
544

545
#[cfg(test)]
546
mod test {
547

548
    use crate as hwa;
549
    use core::future;
550
    use core::future::Future;
551
    use hwa::{EventFlags, EventStatus};
552
    use std::sync::RwLock;
553
    use std::task::Poll;
554

555
    #[test]
556
    fn test_flags() {
8✔
557
        let flags = EventFlags::all();
8✔
558
        hwa::info!("all flags: {:?}", flags);
8✔
559
        let event_status = EventStatus::not_containing(EventFlags::SYS_BOOTING);
8✔
560
        hwa::info!("event status: {:?}", event_status);
8✔
561
    }
8✔
562

563
    type ChannelControllerMutexType = hwa::AsyncCsMutexType;
564
    type PubSubMutexType = hwa::AsyncCsMutexType;
565
    type ResourceType = hwa::EventBusChannelController<PubSubMutexType>;
566
    type MutexStrategyType = hwa::AsyncHoldableStrategy<ChannelControllerMutexType, ResourceType>;
567

568
    #[futures_test::test]
569
    async fn test_manual() {
8✔
570
        use crate as printhor_hwa_utils;
571

572
        let controller = hwa::GenericEventBus::new(hwa::make_static_async_controller!(
8✔
573
            "EventBus",
574
            MutexStrategyType,
575
            hwa::EventBusChannelController::new(hwa::make_static_ref!(
8✔
576
                "EventBusChannel",
577
                hwa::EventBusPubSubType<PubSubMutexType>,
578
                hwa::EventBusPubSubType::new(),
8✔
579
            )),
8✔
580
        ));
8✔
581

8✔
582
        let cloned_controller = controller.clone();
8✔
583

8✔
584
        controller
8✔
585
            .publish_event(EventStatus::containing(EventFlags::SYS_ALARM))
8✔
586
            .await;
8✔
587
        let st1 = controller.get_status().await;
8✔
588
        let st2 = cloned_controller.get_status().await;
8✔
589
        assert_eq!(st1, st2, "State is common across EventBus cloned instance");
8✔
590
    }
16✔
591

592
    static EVENT_BUS: RwLock<Option<hwa::GenericEventBus<MutexStrategyType, PubSubMutexType>>> =
593
        RwLock::new(None);
594

595
    fn initialize() {
8✔
596
        let mut global = EVENT_BUS.write().unwrap();
8✔
597

8✔
598
        if global.is_none() {
8✔
599
            global.replace(hwa::GenericEventBus::new(
8✔
600
                hwa::make_static_async_controller!(
8✔
601
                    "EventBus",
602
                    MutexStrategyType,
603
                    hwa::EventBusChannelController::new(hwa::make_static_ref!(
8✔
604
                        "EventBusChannel",
605
                        hwa::EventBusPubSubType<PubSubMutexType>,
606
                        hwa::EventBusPubSubType::new(),
8✔
607
                    )),
608
                ),
609
            ));
610
        }
×
611
    }
8✔
612

613
    #[futures_test::test]
614
    async fn test_event_bus() {
8✔
615
        initialize();
8✔
616
        let mg = EVENT_BUS.read().unwrap();
8✔
617
        let event_bus = mg.as_ref().unwrap();
8✔
618

8✔
619
        let event_status = EventStatus::new()
8✔
620
            .and_containing(EventFlags::SYS_BOOTING)
8✔
621
            .and_not_containing(EventFlags::SYS_BOOT_FAILURE);
8✔
622
        hwa::info!("{:?}", event_status);
8✔
623
        hwa::info!("{:?}", event_status);
8✔
624
        event_bus.publish_event(event_status).await;
8✔
625

626
        assert!(
8✔
627
            event_bus.has_flags(EventFlags::SYS_BOOTING).await,
8✔
628
            "StateChecks [1]: Initially, flag SYS_BOOTING is set"
×
629
        );
630
        assert!(
8✔
631
            !event_bus.has_flags(EventFlags::SYS_BOOT_FAILURE).await,
8✔
632
            "StateChecks [1]: Initially, flag SYS_BOOT_FAILURE is not set"
×
633
        );
634
        let mut subscriber = event_bus.subscriber().await;
8✔
635

636
        let the_flags = subscriber.get_status().await;
8✔
637
        assert_eq!(
8✔
638
            the_flags,
639
            EventFlags::SYS_BOOTING,
640
            "StateChecks [1]: flag SYS_BOOTING read from a lately created subscriber"
×
641
        );
642

643
        let the_flags = subscriber.get_status().await;
8✔
644
        assert_eq!(
8✔
645
            the_flags,
646
            EventFlags::SYS_BOOTING,
647
            "StateChecks [1]: Again, flag SYS_BOOTING read from a lately created subscriber (idempotence test)"
×
648
        );
649

650
        future::poll_fn(|cx| {
8✔
651
            {
8✔
652
                let pinned_subscriber_future1 =
8✔
653
                    core::pin::pin!(subscriber.ft_wait_while(EventFlags::SYS_BOOTING));
8✔
654
                let p1 = pinned_subscriber_future1.poll(cx);
8✔
655
                assert_eq!(
8✔
656
                    p1,
657
                    Poll::Pending,
658
                    "StateChecks [1]: Subscriber would wait WHILE SYS_BOOTING"
×
659
                );
660
            }
661

662
            {
663
                let pinned_subscriber_future2 =
8✔
664
                    core::pin::pin!(subscriber.ft_wait_until_reset(EventFlags::SYS_BOOTING));
8✔
665
                let p2 = pinned_subscriber_future2.poll(cx);
8✔
666
                assert_eq!(
8✔
667
                    p2,
668
                    Poll::Pending,
669
                    "StateChecks [1]: Subscriber would wait UNTIL SYS_BOOTING is reset"
×
670
                );
671
            }
672
            {
673
                let pinned_subscriber_future3 =
8✔
674
                    core::pin::pin!(subscriber.ft_wait_until(EventFlags::SYS_READY));
8✔
675
                let p3 = pinned_subscriber_future3.poll(cx);
8✔
676
                assert_eq!(
8✔
677
                    p3,
678
                    Poll::Pending,
679
                    "StateChecks [1]: Subscriber would wait UNTIL SYS_READY"
×
680
                );
681
                Poll::Ready(())
8✔
682
            }
8✔
683
        })
8✔
684
        .await;
8✔
685

686
        future::poll_fn(|cx| {
8✔
687
            let status = EventStatus::not_containing(EventFlags::SYS_BOOTING);
8✔
688
            let mut pinned_subscriber_future = core::pin::pin!(subscriber.ft_wait_for(status));
8✔
689
            let p1 = pinned_subscriber_future.as_mut().poll(cx);
8✔
690
            assert_eq!(
8✔
691
                p1,
692
                Poll::Pending,
693
                "StateChecks [1]: Subscriber would wait FOR !SYS_BOOTING"
×
694
            );
695

696
            {
697
                let mut pinned_publisher_future = core::pin::pin!(event_bus.publish_event(status));
8✔
698
                let p2 = pinned_publisher_future.as_mut().poll(cx);
8✔
699
                assert_ne!(
8✔
700
                    p2,
701
                    Poll::Pending,
702
                    "StateChecks [2]: Publisher allows to publish immediately !SYS_BOOTING"
×
703
                );
704
            }
705

706
            let p3 = pinned_subscriber_future.as_mut().poll(cx);
8✔
707
            assert_ne!(
8✔
708
                p3,
709
                Poll::Pending,
710
                "StateChecks [3]: Subscriber now does NOT wait FOR !SYS_BOOTING"
×
711
            );
712

713
            Poll::Ready(())
8✔
714
        })
8✔
715
        .await;
8✔
716
    }
16✔
717
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc