pyvesync 3.0.0b0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. pyvesync/__init__.py +11 -0
  2. pyvesync/base_devices/__init__.py +35 -0
  3. pyvesync/base_devices/bulb_base.py +348 -0
  4. pyvesync/base_devices/fan_base.py +398 -0
  5. pyvesync/base_devices/fryer_base.py +69 -0
  6. pyvesync/base_devices/humidifier_base.py +460 -0
  7. pyvesync/base_devices/outlet_base.py +315 -0
  8. pyvesync/base_devices/purifier_base.py +518 -0
  9. pyvesync/base_devices/switch_base.py +270 -0
  10. pyvesync/base_devices/thermostat_base.py +277 -0
  11. pyvesync/base_devices/vesyncbasedevice.py +580 -0
  12. pyvesync/const.py +749 -0
  13. pyvesync/device_container.py +360 -0
  14. pyvesync/device_map.py +1090 -0
  15. pyvesync/devices/__init__.py +1 -0
  16. pyvesync/devices/vesyncbulb.py +1254 -0
  17. pyvesync/devices/vesyncfan.py +238 -0
  18. pyvesync/devices/vesynchumidifier.py +785 -0
  19. pyvesync/devices/vesynckitchen.py +664 -0
  20. pyvesync/devices/vesyncoutlet.py +962 -0
  21. pyvesync/devices/vesyncpurifier.py +951 -0
  22. pyvesync/devices/vesyncswitch.py +449 -0
  23. pyvesync/devices/vesyncthermostat.py +175 -0
  24. pyvesync/models/__init__.py +11 -0
  25. pyvesync/models/base_models.py +117 -0
  26. pyvesync/models/bulb_models.py +173 -0
  27. pyvesync/models/bypass_models.py +264 -0
  28. pyvesync/models/fan_models.py +46 -0
  29. pyvesync/models/fryer_models.py +28 -0
  30. pyvesync/models/home_models.py +158 -0
  31. pyvesync/models/humidifier_models.py +187 -0
  32. pyvesync/models/outlet_models.py +194 -0
  33. pyvesync/models/purifier_models.py +204 -0
  34. pyvesync/models/switch_models.py +89 -0
  35. pyvesync/models/thermostat_models.py +122 -0
  36. pyvesync/models/vesync_models.py +252 -0
  37. pyvesync/utils/__init__.py +1 -0
  38. pyvesync/utils/colors.py +248 -0
  39. pyvesync/utils/device_mixins.py +366 -0
  40. pyvesync/utils/enum_utils.py +25 -0
  41. pyvesync/utils/errors.py +859 -0
  42. pyvesync/utils/helpers.py +696 -0
  43. pyvesync/utils/logs.py +500 -0
  44. pyvesync/vesync.py +445 -0
  45. pyvesync-3.0.0b0.dist-info/METADATA +527 -0
  46. pyvesync-3.0.0b0.dist-info/RECORD +49 -0
  47. pyvesync-3.0.0b0.dist-info/WHEEL +5 -0
  48. pyvesync-3.0.0b0.dist-info/licenses/LICENSE +21 -0
  49. pyvesync-3.0.0b0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,117 @@
1
+ """Base data models for API requests and response.
2
+
3
+ These models are used to define the structure of the requests and
4
+ responses from the API. They use Mashumaro for serialization and
5
+ deserialization. The `DataClassConfigMixin` class sets default options
6
+ for `orjson` and `Mashumaro`.
7
+
8
+ Note:
9
+ Dataclasses should follow the naming convention of
10
+ Request/Response + API Name. Internal models can have any descriptive
11
+ name.
12
+
13
+
14
+ All models should inherit `ResponseBaseModel` or `RequestBaseModel`. Use
15
+ [pyvesync.const][pyvesync.const] to set default values and import here.
16
+
17
+ Attributes are inherited from the [const][pyvesync.const] module for
18
+ default values.
19
+ """
20
+ from __future__ import annotations
21
+ from time import time
22
+ from typing import ClassVar
23
+ from dataclasses import dataclass
24
+ import orjson
25
+ from mashumaro.mixins.orjson import DataClassORJSONMixin
26
+ from mashumaro.config import BaseConfig
27
+ from pyvesync.const import (
28
+ USER_TYPE,
29
+ APP_VERSION,
30
+ PHONE_BRAND,
31
+ PHONE_OS,
32
+ MOBILE_ID,
33
+ DEFAULT_REGION,
34
+ DEFAULT_LANGUAGE,
35
+ DEFAULT_TZ,
36
+ BYPASS_HEADER_UA,
37
+ TERMINAL_ID,
38
+ )
39
+
40
+
41
+ RequestHeaders = {
42
+ "User-Agent": BYPASS_HEADER_UA,
43
+ "Content-Type": "application/json; charset=UTF-8",
44
+ }
45
+
46
+
47
+ class BaseModelConfig(BaseConfig):
48
+ """Base config for dataclasses."""
49
+ orjson_options = orjson.OPT_NON_STR_KEYS
50
+
51
+
52
+ @dataclass
53
+ class RequestBaseModel(DataClassORJSONMixin):
54
+ """Base request model for API requests.
55
+
56
+ Forbids extra keys in the request JSON.
57
+ """
58
+
59
+ class Config(BaseModelConfig):
60
+ """orjson config for dataclasses."""
61
+ forbid_extra_keys = True
62
+ orjson_options = orjson.OPT_NON_STR_KEYS
63
+
64
+
65
+ @dataclass
66
+ class ResponseBaseModel(DataClassORJSONMixin):
67
+ """Base response model for API responses.
68
+
69
+ Allows extra keys in the response model and
70
+ non-string keys in the JSON.
71
+ """
72
+
73
+ class Config(BaseConfig):
74
+ """Config for dataclasses."""
75
+ orjson_options = orjson.OPT_NON_STR_KEYS
76
+ forbid_extra_keys = False
77
+
78
+
79
+ @dataclass
80
+ class DefaultValues:
81
+ """Default request fields.
82
+
83
+ Attributes for the default values of the request fields
84
+ and static methods for preparing calculated fields.
85
+ """
86
+ _call_number: ClassVar[int] = 0
87
+ userType: str = USER_TYPE
88
+ appVersion: str = APP_VERSION
89
+ phoneBrand: str = PHONE_BRAND
90
+ phoneOS: str = PHONE_OS
91
+ mobileId: str = MOBILE_ID
92
+ deviceRegion: str = DEFAULT_REGION
93
+ countryCode: str = DEFAULT_REGION
94
+ userCountryCode: str = DEFAULT_REGION
95
+ acceptLanguage: str = DEFAULT_LANGUAGE
96
+ timeZone: str = DEFAULT_TZ
97
+ terminalId: str = TERMINAL_ID
98
+ debugMode: bool = False
99
+
100
+ @staticmethod
101
+ def traceId() -> str:
102
+ """Trace ID CSRF token."""
103
+ return str(int(time()))
104
+
105
+ @staticmethod
106
+ def newTraceId() -> str:
107
+ """Generate a new trace ID."""
108
+ DefaultValues._call_number += 1
109
+ return f'APP{TERMINAL_ID[-5:-1]}{int(time())}-{DefaultValues._call_number:0>5}'
110
+
111
+
112
+ @dataclass
113
+ class ResponseCodeModel(ResponseBaseModel):
114
+ """Model for the 'result' field in response."""
115
+ traceId: str
116
+ code: int
117
+ msg: str | None
@@ -0,0 +1,173 @@
1
+ """Models for VeSync Bulb API responses and requests.
2
+
3
+ These models are used to serialize and deserialize the JSON responses from the
4
+ VeSync API. The models are used in the VeSync API class methods to provide
5
+ type hints and data validation.
6
+ """
7
+ from __future__ import annotations
8
+ from dataclasses import dataclass, field
9
+ from typing import Self, TypedDict
10
+ from mashumaro import field_options
11
+ from mashumaro.config import BaseConfig
12
+ from mashumaro.mixins.orjson import DataClassORJSONMixin
13
+ from pyvesync.models.bypass_models import RequestBypassV1
14
+ from pyvesync.models.base_models import ResponseCodeModel, ResponseBaseModel
15
+
16
+
17
+ @dataclass
18
+ class JSONCMD(DataClassORJSONMixin):
19
+ """Tunable Bulb JSON CMD dict."""
20
+ light: None | JSONCMDLight = None
21
+ getLightStatus: None | str = None
22
+
23
+ class Config(BaseConfig):
24
+ """Configure the JSONCMD model."""
25
+ omit_none = True
26
+
27
+
28
+ @dataclass
29
+ class JSONCMDLight(DataClassORJSONMixin):
30
+ """Light JSON CMD dict."""
31
+ action: str
32
+ brightness: int | None = None
33
+ colorTempe: int | None = None
34
+
35
+ class Config(BaseConfig):
36
+ """Configure the JSONCMDLight model."""
37
+ omit_none = True
38
+
39
+
40
+ @dataclass
41
+ class RequestESL100Detail(RequestBypassV1):
42
+ """Request model for Etekcity bulb details."""
43
+
44
+
45
+ @dataclass
46
+ class RequestESL100Status(RequestBypassV1):
47
+ """Request model for Etekcity bulb details."""
48
+ status: str
49
+
50
+
51
+ @dataclass
52
+ class RequestESL100Brightness(RequestBypassV1):
53
+ """Request model for Etekcity bulb details."""
54
+ status: str
55
+ brightNess: int
56
+
57
+
58
+ @dataclass
59
+ class RequestESL100CWBase(RequestBypassV1):
60
+ """Request model for ESL100CW bulb."""
61
+ jsonCmd: JSONCMD
62
+
63
+
64
+ @dataclass
65
+ class ResponseESL100Detail(ResponseCodeModel):
66
+ """Response model for Etekcity bulb details."""
67
+ traceId: str
68
+ code: int
69
+ msg: str | None
70
+ result: ResponseESL100DetailResult
71
+
72
+
73
+ @dataclass
74
+ class ResponseESL100DetailResult(ResponseBaseModel):
75
+ """ESL100 Dimmable Bulb Device Detail Response."""
76
+ deviceName: str | None
77
+ name: str | None
78
+ brightness: int | None = field(metadata=field_options(alias="brightNess"))
79
+ activeTime: int | None
80
+ deviceStatus: str = "off"
81
+ connectionStatus: str = "offline"
82
+
83
+ @classmethod
84
+ def __post_deserialize__( # type: ignore[override]
85
+ cls, obj: Self) -> Self:
86
+ """Set values depending on color or white mode."""
87
+ if obj.brightness is None:
88
+ obj.brightness = 0
89
+ if obj.activeTime is None:
90
+ obj.activeTime = 0
91
+ return obj
92
+
93
+
94
+ @dataclass
95
+ class ResponseESL100CWDetail(ResponseCodeModel):
96
+ """Response model for Etekcity bulb details."""
97
+ result: ResponseESL100CWDetailResult
98
+
99
+
100
+ @dataclass
101
+ class ResponseESL100CWLight(ResponseBaseModel):
102
+ """ESL100CW Tunable Bulb Device Detail Response."""
103
+ brightness: int | None
104
+ action: str = "on"
105
+ colorTempe: int = 0
106
+
107
+
108
+ @dataclass
109
+ class ResponseESL100CWDetailResult(ResponseBaseModel):
110
+ """Result model for ESL100CW Tunable bulb details."""
111
+ light: ResponseESL100CWLight
112
+
113
+
114
+ @dataclass
115
+ class ResponseESL100MCStatus(ResponseCodeModel):
116
+ """Response model for Etekcity bulb status."""
117
+ result: ResponseESL100MCOuterResult
118
+
119
+
120
+ @dataclass
121
+ class ResponseESL100MCOuterResult:
122
+ """ESL100MC Multi-Color Bulb Status Response."""
123
+ traceId: str
124
+ code: int
125
+ result: ResponseESL100MCResult
126
+
127
+
128
+ @dataclass
129
+ class ResponseESL100MCResult:
130
+ """ESL100MC Multi-Color Bulb Status Response."""
131
+ colorMode: str
132
+ action: str
133
+ brightness: int = 0
134
+ red: int = 0
135
+ green: int = 0
136
+ blue: int = 0
137
+
138
+
139
+ @dataclass
140
+ class ResponseValcenoStatus(ResponseCodeModel):
141
+ """Response model for Valceno bulb status."""
142
+ result: ResponseValcenoOuterResult
143
+
144
+
145
+ @dataclass
146
+ class ResponseValcenoOuterResult(ResponseBaseModel):
147
+ """Valceno Bulb Status Response."""
148
+ result: ResponseValcenoStatusResult
149
+ traceId: str = ""
150
+ code: int = 0
151
+
152
+
153
+ @dataclass
154
+ class ResponseValcenoStatusResult(ResponseBaseModel):
155
+ """Valceno Bulb Status Result."""
156
+ colorMode: str = ""
157
+ colorTemp: int = 0
158
+ brightness: int = 0
159
+ hue: int = 0
160
+ saturation: int = 0
161
+ value: int = 0
162
+ enabled: str = "off"
163
+
164
+
165
+ class ValcenoStatusPayload(TypedDict):
166
+ """Typed Dict for setting Valceno bulb status."""
167
+ colorMode: str
168
+ colorTemp: int | str
169
+ brightness: int | str
170
+ hue: int | str
171
+ saturation: int | str
172
+ value: int | str
173
+ force: int
@@ -0,0 +1,264 @@
1
+ """Request Models for Bypass V2 Endpoints.
2
+
3
+ API calls to bypassV2 endpoints have similar request structures. These models are used
4
+ to serialize and deserialize the JSON requests for the bypassV2 endpoints.
5
+ """
6
+ from __future__ import annotations
7
+ from dataclasses import dataclass, field
8
+ from mashumaro.mixins.orjson import DataClassORJSONMixin
9
+ from mashumaro.config import BaseConfig
10
+ from mashumaro import pass_through
11
+ import orjson
12
+
13
+ from pyvesync.models.base_models import (
14
+ RequestBaseModel,
15
+ ResponseBaseModel,
16
+ ResponseCodeModel,
17
+ BaseModelConfig,
18
+ )
19
+
20
+
21
+ @dataclass
22
+ class RequestBypassV2(RequestBaseModel):
23
+ """Bypass V2 Status Request Dict.
24
+
25
+ This is the bypassV2 request model for API calls
26
+ that use the `configModel` and `deviceId` fields.
27
+ """
28
+ acceptLanguage: str
29
+ accountID: str
30
+ appVersion: str
31
+ cid: str
32
+ configModule: str
33
+ debugMode: bool
34
+ method: str
35
+ phoneBrand: str
36
+ phoneOS: str
37
+ traceId: str
38
+ timeZone: str
39
+ token: str
40
+ userCountryCode: str
41
+ deviceId: str
42
+ configModel: str
43
+ payload: BypassV2RequestPayload
44
+
45
+
46
+ @dataclass
47
+ class BypassV2RequestPayload(RequestBaseModel):
48
+ """Generic Bypass V2 Payload Request model."""
49
+ data: dict
50
+ method: str
51
+ source: str = "APP"
52
+
53
+
54
+ @dataclass
55
+ class RequestBypassV1(RequestBaseModel):
56
+ """Bypass V1 Status Request Dict.
57
+
58
+ This is the bypassV1 request model for API calls
59
+ that use the `configModel` and `deviceId` fields.
60
+ """
61
+ acceptLanguage: str
62
+ accountID: str
63
+ appVersion: str
64
+ cid: str
65
+ configModule: str
66
+ debugMode: bool
67
+ method: str
68
+ phoneBrand: str
69
+ phoneOS: str
70
+ traceId: str
71
+ timeZone: str
72
+ token: str
73
+ userCountryCode: str
74
+ uuid: str
75
+ deviceId: str
76
+ configModel: str
77
+
78
+ class Config(BaseConfig): # type: ignore[override]
79
+ """Configure omit None value keys."""
80
+ omit_none = True
81
+ orjson_options = orjson.OPT_NON_STR_KEYS
82
+ forbid_extra_keys = True
83
+
84
+
85
+ @dataclass
86
+ class ResponseBypassV1(ResponseCodeModel):
87
+ """Bypass V1 Response Dict."""
88
+ result: BypassV1Result | None = field(
89
+ default=None,
90
+ metadata={
91
+ "serialize": pass_through,
92
+ "deserialize": pass_through,
93
+ },
94
+ )
95
+
96
+
97
+ @dataclass
98
+ class BypassV1Result(DataClassORJSONMixin):
99
+ """Bypass V1 Response Dict."""
100
+
101
+
102
+ @dataclass
103
+ class ResponseBypassV2(ResponseCodeModel):
104
+ """Bypass V2 Response Dict.
105
+
106
+ This is the bypassV2 response model for API calls
107
+ that use the `configModel` and `deviceId` fields.
108
+ """
109
+ result: BypassV2OuterResult | None = None
110
+
111
+
112
+ @dataclass
113
+ class BypassV2InnerResult(DataClassORJSONMixin):
114
+ """Inner Bypass V2 Result Data Model."""
115
+
116
+ class Config(BaseModelConfig):
117
+ """Configure the Outer Result model."""
118
+ allow_deserialization_not_by_alias = True
119
+
120
+
121
+ @dataclass
122
+ class BypassV2OuterResult(DataClassORJSONMixin):
123
+ """Bypass V2 Outer Result Data Model."""
124
+
125
+ code: int
126
+ result: BypassV2InnerResult | None = field(
127
+ default=None,
128
+ metadata={
129
+ "serialize": pass_through,
130
+ "deserialize": pass_through,
131
+ },
132
+ )
133
+
134
+ class Config(BaseModelConfig):
135
+ """Configure the Outer Result model."""
136
+ allow_deserialization_not_by_alias = True
137
+
138
+
139
+ @dataclass
140
+ class BypassV2ResultError(DataClassORJSONMixin):
141
+ """Bypass V2 Result Error Data Model."""
142
+ msg: str
143
+
144
+
145
+ @dataclass
146
+ class ResultV2GetTimer(BypassV2InnerResult):
147
+ """Inner result for Bypass V2 GetTimer method."""
148
+ timers: list[TimerItemV2] | None = None
149
+
150
+
151
+ @dataclass
152
+ class ResultV2SetTimer(BypassV2InnerResult):
153
+ """Result for Bypass V2 SetTimer method."""
154
+ id: int
155
+
156
+
157
+ # Bypass V1 Timer Models
158
+
159
+ @dataclass
160
+ class TimeItemV1(ResponseBaseModel):
161
+ """Data model for Bypass V1 Timers."""
162
+ timerID: str
163
+ counterTime: str
164
+ action: str
165
+ status: str
166
+ resetTime: str
167
+ uuid: str
168
+
169
+
170
+ @dataclass
171
+ class TimerItemV1(ResponseBaseModel):
172
+ """Data model for Bypass V1 Timers."""
173
+ timerID: str
174
+ counterTimer: str
175
+ action: str
176
+ status: str
177
+ resetTime: str
178
+
179
+
180
+ @dataclass
181
+ class TimerItemV2(ResponseBaseModel):
182
+ """Data model for Bypass V2 Timers."""
183
+ id: int
184
+ remain: int
185
+ action: str
186
+ total: int
187
+
188
+
189
+ @dataclass
190
+ class ResultV1SetTimer(BypassV1Result):
191
+ """Result model for setting Bypass V1 API timer."""
192
+ timerID: str
193
+ conflictTimerIds: list[str] | None = None
194
+
195
+
196
+ @dataclass
197
+ class RequestV1ClearTimer(RequestBypassV1):
198
+ """Request model for clearing Bypass V1 API outlet timer."""
199
+ timerId: str
200
+ status: str | None = None
201
+
202
+
203
+ @dataclass
204
+ class ResultV1GetTimerList(BypassV1Result):
205
+ """Get timers result for v1 API."""
206
+ timers: list[TimeItemV1] | list[TimerItemV1] | TimerItemV1 | None = None
207
+
208
+
209
+ @dataclass
210
+ class RequestV1SetTime(RequestBypassV1):
211
+ """Request model for setting timer with counterTime."""
212
+ counterTime: str
213
+ action: str
214
+ status: str | None = None
215
+ switchNo: int | None = None
216
+
217
+
218
+ @dataclass
219
+ class RequestV1GetTimer(RequestBypassV1):
220
+ """Request model for getting timers from v1 API."""
221
+ switchNo: str | None = None
222
+
223
+
224
+ @dataclass
225
+ class RequestV1SetTimer(RequestBypassV1):
226
+ """Request model for timer with counterTimer key.
227
+
228
+ Attributes:
229
+ counterTimer (str): The timer value in seconds.
230
+ action (str): The action to perform (e.g., "on", "off").
231
+ switchNo (int | None): The switch number for the timer.
232
+ """
233
+ counterTimer: str
234
+ action: str
235
+ switchNo: int | None = None
236
+
237
+
238
+ class TimerModels:
239
+ """Class holding all common timer models.
240
+
241
+ Attributes:
242
+ ResultV2GetTimer (ResultV2GetTimer): Result model for Bypass V2 GetTimer method.
243
+ ResultV2SetTimer (ResultV2SetTimer): Result model for Bypass V2 SetTimer method.
244
+ ResultV1SetTimer (ResultV1SetTimer): Result model V1 API for setting timer.
245
+ ResultV1GetTimer (ResultV1GetTimerList): Get timers result for v1 API.
246
+ TimeItemV1 (TimeItemV1): Data model for Bypass V1 Timers.
247
+ TimerItemV1 (TimerItemV1): Data model for Bypass V1 Timers.
248
+ TimerItemV2 (TimerItemV2): Data model for Bypass V2 Timers.
249
+ RequestV1ClearTimer (RequestV1ClearTimer): Model for deleting timer.
250
+ RequestV1SetTimer (RequestV1SetTimer): Model for timer with counterTimer key.
251
+ RequestV1GetTimer (RequestV1GetTimer): Model for getting timers from v1 API.
252
+ RequestV1SetTime (RequestV1SetTime): Model for setting timer with counterTime key.
253
+ """
254
+ ResultV2GetTimer = ResultV2GetTimer
255
+ ResultV2SetTimer = ResultV2SetTimer
256
+ ResultV1SetTimer = ResultV1SetTimer
257
+ ResultV1GetTimer = ResultV1GetTimerList
258
+ TimeItemV1 = TimeItemV1
259
+ TimerItemV1 = TimerItemV1
260
+ TimerItemV2 = TimerItemV2
261
+ RequestV1ClearTimer = RequestV1ClearTimer
262
+ RequestV1SetTimer = RequestV1SetTimer
263
+ RequestV1GetTimer = RequestV1GetTimer
264
+ RequestV1SetTime = RequestV1SetTime
@@ -0,0 +1,46 @@
1
+ """Data models for VeSync Fans.
2
+
3
+ These models inherit from `ResponseBaseModel` and `RequestBaseModel` from the
4
+ `base_models` module.
5
+ """
6
+ from __future__ import annotations
7
+ from dataclasses import dataclass
8
+ from mashumaro.mixins.orjson import DataClassORJSONMixin
9
+
10
+ from pyvesync.const import IntFlag
11
+ from pyvesync.models.bypass_models import (
12
+ BypassV2InnerResult,
13
+ )
14
+
15
+
16
+ @dataclass
17
+ class TowerFanResult(BypassV2InnerResult):
18
+ """Vital 100S/200S and Everest Fan Result Model."""
19
+ powerSwitch: int
20
+ filterLifePercent: int
21
+ workMode: str
22
+ manualSpeedLevel: int
23
+ fanSpeedLevel: int
24
+ screenState: int
25
+ screenSwitch: int
26
+ oscillationSwitch: int
27
+ oscillationState: int
28
+ muteSwitch: int
29
+ muteState: int
30
+ timerRemain: int
31
+ temperature: int
32
+ humidity: int
33
+ thermalComfort: int
34
+ errorCode: int
35
+ scheduleCount: int
36
+ displayingType: int = IntFlag.NOT_SUPPORTED
37
+ sleepPreference: FanSleepPreferences | None = None
38
+
39
+
40
+ @dataclass
41
+ class FanSleepPreferences(DataClassORJSONMixin):
42
+ """Fan Sleep Preferences."""
43
+ sleepPreferenceType: int
44
+ oscillationSwitch: int
45
+ fallAsleepRemain: int
46
+ autoChangeFanLevelSwitch: int
@@ -0,0 +1,28 @@
1
+ """Data models for VeSync air fryers."""
2
+ from __future__ import annotations
3
+ from dataclasses import dataclass
4
+ from pyvesync.models.base_models import ResponseBaseModel
5
+
6
+
7
+ @dataclass
8
+ class ResultFryerDetails(ResponseBaseModel):
9
+ """Result model for air fryer details."""
10
+ returnStatus: FryerCookingReturnStatus | FryerBaseReturnStatus | None = None
11
+
12
+
13
+ @dataclass
14
+ class FryerCookingReturnStatus(ResponseBaseModel):
15
+ """Result returnStatus model for air fryer status."""
16
+ currentTemp: int
17
+ cookSetTemp: int
18
+ mode: str
19
+ cookSetTime: int
20
+ cookLastTime: int
21
+ cookStatus: str
22
+ tempUnit: str
23
+
24
+
25
+ @dataclass
26
+ class FryerBaseReturnStatus(ResponseBaseModel):
27
+ """Result returnStatus model for air fryer status."""
28
+ cookStatus: str