Skip to content

Generated OperationalStatus for WindowCovering is wrong #282

@Luro02

Description

@Luro02

I am in the process of writing a matter application to control a window covering.

The import!(WindowCovering) macro generates the handler trait, which contains this required method:

pub trait ClusterAsyncHandler {
    // ...

    async fn operational_status(
        &self,
        ctx: &ReadContext<'_>,
    ) -> Result<OperationalStatus, rs_matter::error::Error>;

    // ...
}

The method corresponds to the attribute OperationalStatus with the data type OperationalStatusBitmap in the Matter Application Cluster Specification R1.4.

The specification defines the data type in section 5.3.5.3 as an 8-bit bitmap type where

  • the first 2 bits are "global operation state",
  • the next two are for "lift operational state"
  • and the next two for the "tilt operational state".

Then it defines that for each of the above bitranges how the two bits should be interpreted

  • 0b00 = Currently not moving
  • 0b01 = Currently opening
  • 0b10 = Currently closing

Assuming, I understand this correctly, the specification defines it like this:

enum CurrentMovement {
    NotMoving,
    Opening,
    Closing
}

struct OperationalStatus {
    global: CurrentMovement,
    lift: CurrentMovement,
    tilt: CurrentMovement,
}

Three states that indicate the status of the operations.


The definition doesn't specify the interpretations for each of the state bits:

bitmap OperationalStatus : bitmap8 {
kGlobal = 0x3;
kLift = 0xC;
kTilt = 0x30;
}

That is why the macro then generates something like this:

bitflags::bitflags! {
    struct OperationalStatus: u8 {
        const GLOBAL = 0x03; // 0b0000_0011
        const LIFT   = 0x0C; // 0b0000_1100
        const TILT   = 0x30; // 0b0011_1111
    }
}

which is wrong, 0b11` is not a valid state for any of the operations.
I couldn't find any method to set the individual bits of each of the ranges, which makes this unusable?

I think the definition should look like this:

bitflags::bitflags! {
    struct OperationalStatus: u8 {
        const GLOBAL_OPENING    = 0x01; // 0b0000_0001
        const GLOBAL_CLOSING    = 0x02; // 0b0000_0010

        const LIFT_OPENING      = 0x04; // 0b0000_0100
        const LIFT_CLOSING      = 0x08; // 0b0000_1000

        const TILT_OPENING      = 0x10; // 0b0001_0000
        const TILT_CLOSING      = 0x20; // 0b0010_0000
    }
}

which could then be used like this:

return OperationalStatus::GLOBAL_OPENING | OperationalStatus::LIFT_OPENING;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions