washpy.state

  1import datetime
  2from typing import Any, Dict, Optional
  3import isodate
  4from pydantic import BaseModel
  5from washpy.status import Status
  6
  7
  8class StateModel(BaseModel):
  9    """
 10    captures the output format of the `/State` endpoint.
 11
 12    For pExtended: the contents of the field are device specific.
 13    For the PWM 507 machine, look at the `pExtendedPWM507` class.
 14
 15    View `State` for more details on the class fields.
 16    """
 17
 18    Status: Status
 19    ProgramID: int
 20    ProgramPhase: int
 21    SyncState: int
 22    pRemainingTime: str
 23    pElapsedTime: str
 24    pSystemTime: str
 25    pStartTime: str
 26    pEndTime: str
 27    pLastNotificationTime: str
 28    ProcessUID: str
 29    pExtended: Dict[str, Any]
 30
 31
 32class State:
 33    """
 34    Wrapper around `StateModel`.
 35
 36    This class provides some control logic around
 37    accessing the properties of `StateModel`.
 38
 39    Some properties are not always valid,
 40    largely depending on the value of State.Status
 41    """
 42
 43    _model: StateModel
 44
 45    def __init__(self, **data) -> None:
 46        self._model = StateModel(**data)
 47
 48    def __repr__(self) -> str:
 49        return f"State({self._model.__repr__()})"
 50
 51    def __str__(self) -> str:
 52        return self._model.__str__()
 53
 54    @property
 55    def Status(self) -> Status:
 56        """
 57        This property should always be valid.
 58        """
 59        return self._model.Status
 60
 61    @property
 62    def ProgramID(self) -> int:
 63        """
 64        This property should always be valid.
 65        """
 66        return self._model.ProgramID
 67
 68    @property
 69    def ProgramPhase(self) -> Optional[int]:
 70        """
 71        - None, if the machine is not in the RUNNING state.
 72        - int: ProgramPhase, a device specific 16 bit integer denoting the program phase
 73        """
 74        if self._model.Status != Status.RUNNING:
 75            return None
 76        return self._model.ProgramPhase
 77
 78    @property
 79    def SyncState(self) -> int:
 80        return self._model.SyncState
 81
 82    @property
 83    def pRemainingTime(self) -> Optional[isodate.Duration | datetime.timedelta]:
 84        """
 85        - None, if the machine is not in the RUNNING state, or if the returned date from the machine is not valid.
 86        - Duration: pRemainingTime, the remaining time of the currently active program.
 87        """
 88        if self._model.Status != Status.RUNNING:
 89            return None
 90
 91        try:
 92            return isodate.parse_duration(self._model.pRemainingTime)
 93        except:
 94            return None
 95
 96    @property
 97    def pElapsedTime(self) -> Optional[isodate.Duration | datetime.timedelta]:
 98        """
 99        - None, if the machine is not in the
100          RUNNING, PAUSE, END_PROGRAMMED, FAILURE, or PROGRAMME_INTERRUPTED state,
101          or if the returned date from the machine is not valid.
102        - pElapsedTime, the elapsed time of the currently active program.
103        """
104        if self._model.Status not in {
105            Status.RUNNING,
106            Status.PAUSE,
107            Status.END_PROGRAMMED,
108            Status.FAILURE,
109            Status.PROGRAMME_INTERRUPTED,
110        }:
111            return None
112
113        try:
114            return isodate.parse_duration(self._model.pElapsedTime)
115        except:
116            return None
117
118    @property
119    def pSystemTime(self) -> datetime.datetime:
120        """
121        This property should always be valid.
122        """
123        return isodate.parse_datetime(self._model.pSystemTime)
124
125    @property
126    def pStartTime(self) -> Optional[datetime.datetime]:
127        """
128        - None, if the machine is not in one of these states:
129            - PROGRAMMED_WAITING_TO_START
130            - RUNNING
131            - PAUSE
132            - END_PROGRAMMED
133            - FAILURE
134            - PROGRAMME_INTERRUPTED
135            - RINSE_HOLD
136          or if the returned date from the machine is not valid.
137        - pStartTime, the start time of the currently active program.
138        """
139
140        if self._model.Status not in {
141            Status.PROGRAMMED_WAITING_TO_START,
142            Status.RUNNING,
143            Status.PAUSE,
144            Status.END_PROGRAMMED,
145            Status.FAILURE,
146            Status.PROGRAMME_INTERRUPTED,
147            Status.RINSE_HOLD,
148        }:
149            return None
150
151        try:
152            return isodate.parse_datetime(self._model.pStartTime)
153        except:
154            return None
155
156    @property
157    def pEndTime(self) -> Optional[datetime.datetime]:
158        """
159        - None, if the machine is not in one of these states:
160            - RUNNING
161            - PAUSE
162            - END_PROGRAMMED
163            - FAILURE
164            - PROGRAMME_INTERRUPTED
165          or if the returned date from the machine is not valid.
166        - pEndTime, the estimated end time of the currently active program.
167        """
168        if self._model.Status not in {
169            Status.RUNNING,
170            Status.PAUSE,
171            Status.END_PROGRAMMED,
172            Status.FAILURE,
173            Status.PROGRAMME_INTERRUPTED,
174        }:
175            return None
176
177        try:
178            return isodate.parse_datetime(self._model.pEndTime)
179        except:
180            return None
181
182    @property
183    def pLastNotificationTime(self) -> Optional[datetime.datetime]:
184        """
185        - None, if there is no time stamp.
186        - pLastNotificationTime, the timestamp of the last received notification.
187        """
188        stamp = self._model.pLastNotificationTime
189
190        if stamp == "":
191            return None
192
193        try:
194            return isodate.parse_datetime(stamp)
195        except:
196            return None
197
198    @property
199    def ProcessUID(self) -> str:
200        """
201        According to the Miele documentation,
202        this property should always be valid for devices newer than 01.01.2022.
203
204        The behaviour of older devices is not specified in more detail.
205        washpy assumes, that older devices will always return this property,
206        albeit with an empty string as the value.
207        """
208        return self._model.ProcessUID
209
210    @property
211    def pExtended(self) -> Dict[str, Any]:
212        """
213        The contents of this property are device specific.
214
215        Fow PWM 507 machines take a look at the class `pExtendedPWM507`
216        """
217        return self._model.pExtended
class StateModel(pydantic.main.BaseModel):
 9class StateModel(BaseModel):
10    """
11    captures the output format of the `/State` endpoint.
12
13    For pExtended: the contents of the field are device specific.
14    For the PWM 507 machine, look at the `pExtendedPWM507` class.
15
16    View `State` for more details on the class fields.
17    """
18
19    Status: Status
20    ProgramID: int
21    ProgramPhase: int
22    SyncState: int
23    pRemainingTime: str
24    pElapsedTime: str
25    pSystemTime: str
26    pStartTime: str
27    pEndTime: str
28    pLastNotificationTime: str
29    ProcessUID: str
30    pExtended: Dict[str, Any]

captures the output format of the /State endpoint.

For pExtended: the contents of the field are device specific. For the PWM 507 machine, look at the pExtendedPWM507 class.

View State for more details on the class fields.

ProgramID: int
ProgramPhase: int
SyncState: int
pRemainingTime: str
pElapsedTime: str
pSystemTime: str
pStartTime: str
pEndTime: str
pLastNotificationTime: str
ProcessUID: str
pExtended: Dict[str, Any]
model_config: ClassVar[pydantic.config.ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, pydantic.fields.FieldInfo]] = {'Status': FieldInfo(annotation=Status, required=True), 'ProgramID': FieldInfo(annotation=int, required=True), 'ProgramPhase': FieldInfo(annotation=int, required=True), 'SyncState': FieldInfo(annotation=int, required=True), 'pRemainingTime': FieldInfo(annotation=str, required=True), 'pElapsedTime': FieldInfo(annotation=str, required=True), 'pSystemTime': FieldInfo(annotation=str, required=True), 'pStartTime': FieldInfo(annotation=str, required=True), 'pEndTime': FieldInfo(annotation=str, required=True), 'pLastNotificationTime': FieldInfo(annotation=str, required=True), 'ProcessUID': FieldInfo(annotation=str, required=True), 'pExtended': FieldInfo(annotation=Dict[str, Any], required=True)}

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

model_computed_fields: ClassVar[Dict[str, pydantic.fields.ComputedFieldInfo]] = {}

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

Inherited Members
pydantic.main.BaseModel
BaseModel
model_extra
model_fields_set
model_construct
model_copy
model_dump
model_dump_json
model_json_schema
model_parametrized_name
model_post_init
model_rebuild
model_validate
model_validate_json
model_validate_strings
dict
json
parse_obj
parse_raw
parse_file
from_orm
construct
copy
schema
schema_json
validate
update_forward_refs
class State:
 33class State:
 34    """
 35    Wrapper around `StateModel`.
 36
 37    This class provides some control logic around
 38    accessing the properties of `StateModel`.
 39
 40    Some properties are not always valid,
 41    largely depending on the value of State.Status
 42    """
 43
 44    _model: StateModel
 45
 46    def __init__(self, **data) -> None:
 47        self._model = StateModel(**data)
 48
 49    def __repr__(self) -> str:
 50        return f"State({self._model.__repr__()})"
 51
 52    def __str__(self) -> str:
 53        return self._model.__str__()
 54
 55    @property
 56    def Status(self) -> Status:
 57        """
 58        This property should always be valid.
 59        """
 60        return self._model.Status
 61
 62    @property
 63    def ProgramID(self) -> int:
 64        """
 65        This property should always be valid.
 66        """
 67        return self._model.ProgramID
 68
 69    @property
 70    def ProgramPhase(self) -> Optional[int]:
 71        """
 72        - None, if the machine is not in the RUNNING state.
 73        - int: ProgramPhase, a device specific 16 bit integer denoting the program phase
 74        """
 75        if self._model.Status != Status.RUNNING:
 76            return None
 77        return self._model.ProgramPhase
 78
 79    @property
 80    def SyncState(self) -> int:
 81        return self._model.SyncState
 82
 83    @property
 84    def pRemainingTime(self) -> Optional[isodate.Duration | datetime.timedelta]:
 85        """
 86        - None, if the machine is not in the RUNNING state, or if the returned date from the machine is not valid.
 87        - Duration: pRemainingTime, the remaining time of the currently active program.
 88        """
 89        if self._model.Status != Status.RUNNING:
 90            return None
 91
 92        try:
 93            return isodate.parse_duration(self._model.pRemainingTime)
 94        except:
 95            return None
 96
 97    @property
 98    def pElapsedTime(self) -> Optional[isodate.Duration | datetime.timedelta]:
 99        """
100        - None, if the machine is not in the
101          RUNNING, PAUSE, END_PROGRAMMED, FAILURE, or PROGRAMME_INTERRUPTED state,
102          or if the returned date from the machine is not valid.
103        - pElapsedTime, the elapsed time of the currently active program.
104        """
105        if self._model.Status not in {
106            Status.RUNNING,
107            Status.PAUSE,
108            Status.END_PROGRAMMED,
109            Status.FAILURE,
110            Status.PROGRAMME_INTERRUPTED,
111        }:
112            return None
113
114        try:
115            return isodate.parse_duration(self._model.pElapsedTime)
116        except:
117            return None
118
119    @property
120    def pSystemTime(self) -> datetime.datetime:
121        """
122        This property should always be valid.
123        """
124        return isodate.parse_datetime(self._model.pSystemTime)
125
126    @property
127    def pStartTime(self) -> Optional[datetime.datetime]:
128        """
129        - None, if the machine is not in one of these states:
130            - PROGRAMMED_WAITING_TO_START
131            - RUNNING
132            - PAUSE
133            - END_PROGRAMMED
134            - FAILURE
135            - PROGRAMME_INTERRUPTED
136            - RINSE_HOLD
137          or if the returned date from the machine is not valid.
138        - pStartTime, the start time of the currently active program.
139        """
140
141        if self._model.Status not in {
142            Status.PROGRAMMED_WAITING_TO_START,
143            Status.RUNNING,
144            Status.PAUSE,
145            Status.END_PROGRAMMED,
146            Status.FAILURE,
147            Status.PROGRAMME_INTERRUPTED,
148            Status.RINSE_HOLD,
149        }:
150            return None
151
152        try:
153            return isodate.parse_datetime(self._model.pStartTime)
154        except:
155            return None
156
157    @property
158    def pEndTime(self) -> Optional[datetime.datetime]:
159        """
160        - None, if the machine is not in one of these states:
161            - RUNNING
162            - PAUSE
163            - END_PROGRAMMED
164            - FAILURE
165            - PROGRAMME_INTERRUPTED
166          or if the returned date from the machine is not valid.
167        - pEndTime, the estimated end time of the currently active program.
168        """
169        if self._model.Status not in {
170            Status.RUNNING,
171            Status.PAUSE,
172            Status.END_PROGRAMMED,
173            Status.FAILURE,
174            Status.PROGRAMME_INTERRUPTED,
175        }:
176            return None
177
178        try:
179            return isodate.parse_datetime(self._model.pEndTime)
180        except:
181            return None
182
183    @property
184    def pLastNotificationTime(self) -> Optional[datetime.datetime]:
185        """
186        - None, if there is no time stamp.
187        - pLastNotificationTime, the timestamp of the last received notification.
188        """
189        stamp = self._model.pLastNotificationTime
190
191        if stamp == "":
192            return None
193
194        try:
195            return isodate.parse_datetime(stamp)
196        except:
197            return None
198
199    @property
200    def ProcessUID(self) -> str:
201        """
202        According to the Miele documentation,
203        this property should always be valid for devices newer than 01.01.2022.
204
205        The behaviour of older devices is not specified in more detail.
206        washpy assumes, that older devices will always return this property,
207        albeit with an empty string as the value.
208        """
209        return self._model.ProcessUID
210
211    @property
212    def pExtended(self) -> Dict[str, Any]:
213        """
214        The contents of this property are device specific.
215
216        Fow PWM 507 machines take a look at the class `pExtendedPWM507`
217        """
218        return self._model.pExtended

Wrapper around StateModel.

This class provides some control logic around accessing the properties of StateModel.

Some properties are not always valid, largely depending on the value of State.Status

State(**data)
46    def __init__(self, **data) -> None:
47        self._model = StateModel(**data)
Status: washpy.status.Status
55    @property
56    def Status(self) -> Status:
57        """
58        This property should always be valid.
59        """
60        return self._model.Status

This property should always be valid.

ProgramID: int
62    @property
63    def ProgramID(self) -> int:
64        """
65        This property should always be valid.
66        """
67        return self._model.ProgramID

This property should always be valid.

ProgramPhase: Optional[int]
69    @property
70    def ProgramPhase(self) -> Optional[int]:
71        """
72        - None, if the machine is not in the RUNNING state.
73        - int: ProgramPhase, a device specific 16 bit integer denoting the program phase
74        """
75        if self._model.Status != Status.RUNNING:
76            return None
77        return self._model.ProgramPhase
  • None, if the machine is not in the RUNNING state.
  • int: ProgramPhase, a device specific 16 bit integer denoting the program phase
SyncState: int
79    @property
80    def SyncState(self) -> int:
81        return self._model.SyncState
pRemainingTime: Union[isodate.duration.Duration, datetime.timedelta, NoneType]
83    @property
84    def pRemainingTime(self) -> Optional[isodate.Duration | datetime.timedelta]:
85        """
86        - None, if the machine is not in the RUNNING state, or if the returned date from the machine is not valid.
87        - Duration: pRemainingTime, the remaining time of the currently active program.
88        """
89        if self._model.Status != Status.RUNNING:
90            return None
91
92        try:
93            return isodate.parse_duration(self._model.pRemainingTime)
94        except:
95            return None
  • None, if the machine is not in the RUNNING state, or if the returned date from the machine is not valid.
  • Duration: pRemainingTime, the remaining time of the currently active program.
pElapsedTime: Union[isodate.duration.Duration, datetime.timedelta, NoneType]
 97    @property
 98    def pElapsedTime(self) -> Optional[isodate.Duration | datetime.timedelta]:
 99        """
100        - None, if the machine is not in the
101          RUNNING, PAUSE, END_PROGRAMMED, FAILURE, or PROGRAMME_INTERRUPTED state,
102          or if the returned date from the machine is not valid.
103        - pElapsedTime, the elapsed time of the currently active program.
104        """
105        if self._model.Status not in {
106            Status.RUNNING,
107            Status.PAUSE,
108            Status.END_PROGRAMMED,
109            Status.FAILURE,
110            Status.PROGRAMME_INTERRUPTED,
111        }:
112            return None
113
114        try:
115            return isodate.parse_duration(self._model.pElapsedTime)
116        except:
117            return None
  • None, if the machine is not in the RUNNING, PAUSE, END_PROGRAMMED, FAILURE, or PROGRAMME_INTERRUPTED state, or if the returned date from the machine is not valid.
  • pElapsedTime, the elapsed time of the currently active program.
pSystemTime: datetime.datetime
119    @property
120    def pSystemTime(self) -> datetime.datetime:
121        """
122        This property should always be valid.
123        """
124        return isodate.parse_datetime(self._model.pSystemTime)

This property should always be valid.

pStartTime: Optional[datetime.datetime]
126    @property
127    def pStartTime(self) -> Optional[datetime.datetime]:
128        """
129        - None, if the machine is not in one of these states:
130            - PROGRAMMED_WAITING_TO_START
131            - RUNNING
132            - PAUSE
133            - END_PROGRAMMED
134            - FAILURE
135            - PROGRAMME_INTERRUPTED
136            - RINSE_HOLD
137          or if the returned date from the machine is not valid.
138        - pStartTime, the start time of the currently active program.
139        """
140
141        if self._model.Status not in {
142            Status.PROGRAMMED_WAITING_TO_START,
143            Status.RUNNING,
144            Status.PAUSE,
145            Status.END_PROGRAMMED,
146            Status.FAILURE,
147            Status.PROGRAMME_INTERRUPTED,
148            Status.RINSE_HOLD,
149        }:
150            return None
151
152        try:
153            return isodate.parse_datetime(self._model.pStartTime)
154        except:
155            return None
  • None, if the machine is not in one of these states:
    • PROGRAMMED_WAITING_TO_START
    • RUNNING
    • PAUSE
    • END_PROGRAMMED
    • FAILURE
    • PROGRAMME_INTERRUPTED
    • RINSE_HOLD or if the returned date from the machine is not valid.
  • pStartTime, the start time of the currently active program.
pEndTime: Optional[datetime.datetime]
157    @property
158    def pEndTime(self) -> Optional[datetime.datetime]:
159        """
160        - None, if the machine is not in one of these states:
161            - RUNNING
162            - PAUSE
163            - END_PROGRAMMED
164            - FAILURE
165            - PROGRAMME_INTERRUPTED
166          or if the returned date from the machine is not valid.
167        - pEndTime, the estimated end time of the currently active program.
168        """
169        if self._model.Status not in {
170            Status.RUNNING,
171            Status.PAUSE,
172            Status.END_PROGRAMMED,
173            Status.FAILURE,
174            Status.PROGRAMME_INTERRUPTED,
175        }:
176            return None
177
178        try:
179            return isodate.parse_datetime(self._model.pEndTime)
180        except:
181            return None
  • None, if the machine is not in one of these states:
    • RUNNING
    • PAUSE
    • END_PROGRAMMED
    • FAILURE
    • PROGRAMME_INTERRUPTED or if the returned date from the machine is not valid.
  • pEndTime, the estimated end time of the currently active program.
pLastNotificationTime: Optional[datetime.datetime]
183    @property
184    def pLastNotificationTime(self) -> Optional[datetime.datetime]:
185        """
186        - None, if there is no time stamp.
187        - pLastNotificationTime, the timestamp of the last received notification.
188        """
189        stamp = self._model.pLastNotificationTime
190
191        if stamp == "":
192            return None
193
194        try:
195            return isodate.parse_datetime(stamp)
196        except:
197            return None
  • None, if there is no time stamp.
  • pLastNotificationTime, the timestamp of the last received notification.
ProcessUID: str
199    @property
200    def ProcessUID(self) -> str:
201        """
202        According to the Miele documentation,
203        this property should always be valid for devices newer than 01.01.2022.
204
205        The behaviour of older devices is not specified in more detail.
206        washpy assumes, that older devices will always return this property,
207        albeit with an empty string as the value.
208        """
209        return self._model.ProcessUID

According to the Miele documentation, this property should always be valid for devices newer than 01.01.2022.

The behaviour of older devices is not specified in more detail. washpy assumes, that older devices will always return this property, albeit with an empty string as the value.

pExtended: Dict[str, Any]
211    @property
212    def pExtended(self) -> Dict[str, Any]:
213        """
214        The contents of this property are device specific.
215
216        Fow PWM 507 machines take a look at the class `pExtendedPWM507`
217        """
218        return self._model.pExtended

The contents of this property are device specific.

Fow PWM 507 machines take a look at the class pExtendedPWM507