smartbox 2.1.2__tar.gz → 2.2.0__tar.gz

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 (80) hide show
  1. smartbox-2.2.0/.github/ISSUE_TEMPLATE/new-reseller.md +18 -0
  2. {smartbox-2.1.2 → smartbox-2.2.0}/.github/workflows/publish-to-pypi.yml +1 -1
  3. {smartbox-2.1.2 → smartbox-2.2.0}/.github/workflows/python-package.yml +3 -3
  4. {smartbox-2.1.2 → smartbox-2.2.0}/PKG-INFO +7 -7
  5. {smartbox-2.1.2 → smartbox-2.2.0}/README.md +6 -6
  6. {smartbox-2.1.2 → smartbox-2.2.0}/pyproject.toml +1 -1
  7. {smartbox-2.1.2 → smartbox-2.2.0}/src/smartbox/__init__.py +5 -5
  8. {smartbox-2.1.2 → smartbox-2.2.0}/src/smartbox/cmd.py +29 -5
  9. {smartbox-2.1.2 → smartbox-2.2.0}/src/smartbox/error.py +2 -2
  10. {smartbox-2.1.2 → smartbox-2.2.0}/src/smartbox/models.py +37 -4
  11. smartbox-2.1.2/src/smartbox/resailer.py → smartbox-2.2.0/src/smartbox/reseller.py +46 -34
  12. {smartbox-2.1.2 → smartbox-2.2.0}/src/smartbox/session.py +58 -26
  13. {smartbox-2.1.2 → smartbox-2.2.0}/src/smartbox/socket.py +8 -0
  14. {smartbox-2.1.2 → smartbox-2.2.0}/src/smartbox/update_manager.py +19 -0
  15. {smartbox-2.1.2 → smartbox-2.2.0}/tests/conftest.py +8 -8
  16. smartbox-2.2.0/tests/fixtures/devs/device1/connected.json +3 -0
  17. smartbox-2.2.0/tests/fixtures/devs/device1/mgr/nodes.json +31 -0
  18. smartbox-2.2.0/tests/fixtures/devs/device1/pmo/3/samples.json +16 -0
  19. smartbox-2.2.0/tests/fixtures/devs/device1/pmo/3/setup.json +5 -0
  20. smartbox-2.2.0/tests/fixtures/devs/device1/pmo/3/status.json +4 -0
  21. smartbox-2.2.0/tests/fixtures/devs/device2/connected.json +3 -0
  22. {smartbox-2.1.2 → smartbox-2.2.0}/tests/test_cmd.py +34 -8
  23. smartbox-2.2.0/tests/test_reseller.py +58 -0
  24. {smartbox-2.1.2 → smartbox-2.2.0}/tests/test_session.py +98 -21
  25. {smartbox-2.1.2 → smartbox-2.2.0}/tests/test_update_manager.py +18 -0
  26. {smartbox-2.1.2 → smartbox-2.2.0}/uv.lock +2 -1
  27. smartbox-2.1.2/.github/ISSUE_TEMPLATE/new-resailer.md +0 -18
  28. smartbox-2.1.2/requirements.txt +0 -2
  29. smartbox-2.1.2/tests/fixtures/devs/device1/mgr/nodes.json +0 -18
  30. smartbox-2.1.2/tests/test_resailer.py +0 -46
  31. {smartbox-2.1.2 → smartbox-2.2.0}/.github/FUNDING.yml +0 -0
  32. {smartbox-2.1.2 → smartbox-2.2.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  33. {smartbox-2.1.2 → smartbox-2.2.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  34. {smartbox-2.1.2 → smartbox-2.2.0}/.github/dependabot.yml +0 -0
  35. {smartbox-2.1.2 → smartbox-2.2.0}/.gitignore +0 -0
  36. {smartbox-2.1.2 → smartbox-2.2.0}/.pre-commit-config.yaml +0 -0
  37. {smartbox-2.1.2 → smartbox-2.2.0}/.vscode/settings.json +0 -0
  38. {smartbox-2.1.2 → smartbox-2.2.0}/CHANGELOG.md +0 -0
  39. {smartbox-2.1.2 → smartbox-2.2.0}/CODEOWNERS +0 -0
  40. {smartbox-2.1.2 → smartbox-2.2.0}/LICENSE +0 -0
  41. {smartbox-2.1.2 → smartbox-2.2.0}/api-notes.md +0 -0
  42. {smartbox-2.1.2 → smartbox-2.2.0}/codecov.yml +0 -0
  43. {smartbox-2.1.2 → smartbox-2.2.0}/src/smartbox/py.typed +0 -0
  44. {smartbox-2.1.2 → smartbox-2.2.0}/tests/__init__.py +0 -0
  45. {smartbox-2.1.2 → smartbox-2.2.0}/tests/common.py +0 -0
  46. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device1/acm/1/samples.json +0 -0
  47. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device1/acm/1/setup.json +0 -0
  48. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device1/acm/1/status.json +0 -0
  49. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device1/htr/0/samples.json +0 -0
  50. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device1/htr/0/setup.json +0 -0
  51. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device1/htr/0/status.json +0 -0
  52. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device1/htr_system/power_limit.json +0 -0
  53. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device1/mgr/away_status.json +0 -0
  54. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/0/samples.json +0 -0
  55. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/0/setup.json +0 -0
  56. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/0/status.json +0 -0
  57. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/1/samples.json +0 -0
  58. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/1/setup.json +0 -0
  59. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/1/status.json +0 -0
  60. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/2/samples.json +0 -0
  61. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/2/setup.json +0 -0
  62. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/2/status.json +0 -0
  63. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/3/samples.json +0 -0
  64. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/3/setup.json +0 -0
  65. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/3/status.json +0 -0
  66. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/4/samples.json +0 -0
  67. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/4/setup.json +0 -0
  68. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/4/status.json +0 -0
  69. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/5/samples.json +0 -0
  70. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/5/setup.json +0 -0
  71. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/5/status.json +0 -0
  72. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_system/power_limit.json +0 -0
  73. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/mgr/away_status.json +0 -0
  74. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs/device2/mgr/nodes.json +0 -0
  75. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/devs.json +0 -0
  76. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/grouped_devs.json +0 -0
  77. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/groups/test_home/guest_users.json +0 -0
  78. {smartbox-2.1.2 → smartbox-2.2.0}/tests/fixtures/test_path.json +0 -0
  79. {smartbox-2.1.2 → smartbox-2.2.0}/tests/test_models.py +0 -0
  80. {smartbox-2.1.2 → smartbox-2.2.0}/tox.ini +0 -0
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: New reseller
3
+ about: Add a new available reseller.
4
+ title: "[RESELLER] New available reseller"
5
+ labels: reseller
6
+ assignees: Delmael
7
+
8
+ ---
9
+
10
+ > [!NOTE]
11
+ > If you do not see your current reseller in the available list, you can ask to add it. We cannot ensure your device go through this platform
12
+
13
+ * [ ] I have check with the `smartbox resellers` command that my reseller is not already present
14
+ * **Website url (mandatory)** :
15
+ * Name of the resellers:
16
+ * API url :
17
+ * Basic auth headers :
18
+ * Serial id:
@@ -22,7 +22,7 @@ jobs:
22
22
  with:
23
23
  python-version: ${{ env.PYTHON_VERSION }}
24
24
  - name: Set up Python ${{ env.PYTHON_VERSION }}
25
- uses: actions/setup-python@v5.4.0
25
+ uses: actions/setup-python@v5.5.0
26
26
  with:
27
27
  python-version: ${{ env.PYTHON_VERSION }}
28
28
  - name: Build a binary wheel and a source tarball
@@ -25,7 +25,7 @@ jobs:
25
25
  with:
26
26
  python-version: ${{ matrix.python-version }}
27
27
  - name: Set up Python ${{ matrix.python-version }}
28
- uses: actions/setup-python@v5.4.0
28
+ uses: actions/setup-python@v5.5.0
29
29
  with:
30
30
  python-version: ${{ matrix.python-version }}
31
31
  - name: Install the project
@@ -47,7 +47,7 @@ jobs:
47
47
  with:
48
48
  python-version: ${{ matrix.python-version }}
49
49
  - name: Set up Python ${{ matrix.python-version }}
50
- uses: actions/setup-python@v5.4.0
50
+ uses: actions/setup-python@v5.5.0
51
51
  with:
52
52
  python-version: ${{ matrix.python-version }}
53
53
  - name: Install the project
@@ -70,7 +70,7 @@ jobs:
70
70
  python-version: ${{ matrix.python-version }}
71
71
 
72
72
  - name: Set up Python ${{ matrix.python-version }}
73
- uses: actions/setup-python@v5.4.0
73
+ uses: actions/setup-python@v5.5.0
74
74
  with:
75
75
  python-version: ${{ matrix.python-version }}
76
76
  - name: Install the project
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: smartbox
3
- Version: 2.1.2
3
+ Version: 2.2.0
4
4
  Summary: Python API to control heating 'smart boxes'
5
5
  Project-URL: Homepage, https://github.com/ajtudela/smartbox
6
6
  Project-URL: Issues, https://github.com/ajtudela/smartbox/issues
@@ -53,7 +53,7 @@ A few common options are required for all commands:
53
53
  Verbose logging can be enabled with the `-v`/`--verbose` flag.
54
54
 
55
55
  ### Optional options
56
- These options are useful if your resailer is not configured.
56
+ These options are useful if your reseller is not configured.
57
57
 
58
58
  * `-b`/`--base-auth-creds`: An HTTP Basic Auth credential used to do initial
59
59
  authentication with the server. Use the base64 encoded string directly. See
@@ -61,7 +61,7 @@ These options are useful if your resailer is not configured.
61
61
  * `-a`/`--api-name`: The API name for your heater vendor. This is visible in
62
62
  the 'API Host' entry in the 'Version' menu item in the mobile app/web app. If
63
63
  the host name is of the form `api-foo.xxxx` or `api.xxxx` use the values
64
- `api-foo` or `api` respectively. The resailer has to be declared in the package.
64
+ `api-foo` or `api` respectively. The reseller has to be declared in the package.
65
65
  * `-r`/`--x-referer`: The referer of your request.
66
66
  * `-i`/`--x-serial-id`: The serial-id of your request.
67
67
 
@@ -132,11 +132,11 @@ The `health-check` command can be used to know if the API is alived
132
132
 
133
133
  smartbox <auth options...> health-check
134
134
 
135
- ### List available resailers
136
- The `resailers` command can be used to know which resailershas an automatic configuration.
137
- If your resailer is not present you can raise an issue in github, or use the optional options.
135
+ ### List available resellers
136
+ The `resellers` command can be used to know which resellers has an automatic configuration.
137
+ If your reseller is not present you can raise an issue in github, or use the optional options.
138
138
 
139
- smartbox <auth options...> resailers
139
+ smartbox <auth options...> resellers
140
140
 
141
141
 
142
142
  See [api-notes.md](./api-notes.md) for notes on REST and socket.io endpoints.
@@ -31,7 +31,7 @@ A few common options are required for all commands:
31
31
  Verbose logging can be enabled with the `-v`/`--verbose` flag.
32
32
 
33
33
  ### Optional options
34
- These options are useful if your resailer is not configured.
34
+ These options are useful if your reseller is not configured.
35
35
 
36
36
  * `-b`/`--base-auth-creds`: An HTTP Basic Auth credential used to do initial
37
37
  authentication with the server. Use the base64 encoded string directly. See
@@ -39,7 +39,7 @@ These options are useful if your resailer is not configured.
39
39
  * `-a`/`--api-name`: The API name for your heater vendor. This is visible in
40
40
  the 'API Host' entry in the 'Version' menu item in the mobile app/web app. If
41
41
  the host name is of the form `api-foo.xxxx` or `api.xxxx` use the values
42
- `api-foo` or `api` respectively. The resailer has to be declared in the package.
42
+ `api-foo` or `api` respectively. The reseller has to be declared in the package.
43
43
  * `-r`/`--x-referer`: The referer of your request.
44
44
  * `-i`/`--x-serial-id`: The serial-id of your request.
45
45
 
@@ -110,11 +110,11 @@ The `health-check` command can be used to know if the API is alived
110
110
 
111
111
  smartbox <auth options...> health-check
112
112
 
113
- ### List available resailers
114
- The `resailers` command can be used to know which resailershas an automatic configuration.
115
- If your resailer is not present you can raise an issue in github, or use the optional options.
113
+ ### List available resellers
114
+ The `resellers` command can be used to know which resellers has an automatic configuration.
115
+ If your reseller is not present you can raise an issue in github, or use the optional options.
116
116
 
117
- smartbox <auth options...> resailers
117
+ smartbox <auth options...> resellers
118
118
 
119
119
 
120
120
  See [api-notes.md](./api-notes.md) for notes on REST and socket.io endpoints.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "smartbox"
3
- version = "2.1.2"
3
+ version = "2.2.0"
4
4
  requires-python = ">=3.13"
5
5
  authors = [
6
6
  { name="Alberto Tudela", email="ajtudela@gmail.com" },
@@ -5,7 +5,7 @@ import importlib.metadata
5
5
  from .error import (
6
6
  APIUnavailableError,
7
7
  InvalidAuthError,
8
- ResailerNotExistError,
8
+ ResellerNotExistError,
9
9
  SmartboxError,
10
10
  )
11
11
  from .models import (
@@ -21,7 +21,7 @@ from .models import (
21
21
  NodeStatus,
22
22
  SmartboxNodeType,
23
23
  )
24
- from .resailer import AvailableResailers, SmartboxResailer
24
+ from .reseller import AvailableResellers, SmartboxReseller
25
25
  from .session import AsyncSmartboxSession, Session
26
26
  from .socket import SocketSession
27
27
  from .update_manager import UpdateManager
@@ -33,7 +33,7 @@ __all__ = [
33
33
  "APIUnavailableError",
34
34
  "AcmNodeStatus",
35
35
  "AsyncSmartboxSession",
36
- "AvailableResailers",
36
+ "AvailableResellers",
37
37
  "DefaultNodeStatus",
38
38
  "GuestUser",
39
39
  "Guests",
@@ -44,11 +44,11 @@ __all__ = [
44
44
  "NodeFactoryOptions",
45
45
  "NodeSetup",
46
46
  "NodeStatus",
47
- "ResailerNotExistError",
47
+ "ResellerNotExistError",
48
48
  "Session",
49
49
  "SmartboxError",
50
50
  "SmartboxNodeType",
51
- "SmartboxResailer",
51
+ "SmartboxReseller",
52
52
  "SocketSession",
53
53
  "UpdateManager",
54
54
  ]
@@ -7,7 +7,7 @@ from typing import Any
7
7
  from aiohttp import ClientSession
8
8
  import asyncclick as click
9
9
 
10
- from smartbox.resailer import AvailableResailers
10
+ from smartbox.reseller import AvailableResellers
11
11
  from smartbox.session import AsyncSmartboxSession
12
12
  from smartbox.socket import SocketSession
13
13
 
@@ -277,6 +277,21 @@ async def device_away_status(ctx) -> None:
277
277
  _pretty_print(device_away_status)
278
278
 
279
279
 
280
+ @smartbox.command(help="Show device connected status")
281
+ @click.pass_context
282
+ async def device_connected_status(ctx) -> None:
283
+ """Show device connected status."""
284
+ session = ctx.obj["session"]
285
+ devices = await session.get_devices()
286
+
287
+ for device in devices:
288
+ print(f"{device['name']} (dev_id: {device['dev_id']})")
289
+ device_away_status = await session.get_device_connected(
290
+ device["dev_id"],
291
+ )
292
+ _pretty_print(device_away_status)
293
+
294
+
280
295
  @smartbox.command(
281
296
  help="Set device away_status (pass settings as extra args, e.g. away=true)",
282
297
  )
@@ -379,10 +394,19 @@ async def health_check(ctx) -> None:
379
394
  _pretty_print(health)
380
395
 
381
396
 
382
- @smartbox.command(help="Get the availables resailers.")
383
- def resailers() -> None:
384
- """Get the availables resailers."""
385
- for item in AvailableResailers.resailers.items():
397
+ @smartbox.command(help="Get version of the API.")
398
+ @click.pass_context
399
+ async def api_version(ctx) -> None:
400
+ """Get the version of the API."""
401
+ session = ctx.obj["session"]
402
+ version = await session.api_version()
403
+ _pretty_print(version)
404
+
405
+
406
+ @smartbox.command(help="Get the availables resellers.")
407
+ def resellers() -> None:
408
+ """Get the availables resellers."""
409
+ for item in AvailableResellers.resellers.items():
386
410
  print(item)
387
411
 
388
412
 
@@ -15,5 +15,5 @@ class APIUnavailableError(aiohttp.ClientConnectionError):
15
15
  """API is unavailable."""
16
16
 
17
17
 
18
- class ResailerNotExistError(Exception):
19
- """Resailer is not known."""
18
+ class ResellerNotExistError(Exception):
19
+ """Reseller is not known."""
@@ -47,7 +47,15 @@ class NodeExtraOptions(BaseModel):
47
47
  boost_time: int
48
48
 
49
49
 
50
- class NodeSetup(BaseModel):
50
+ class PmoSetup(BaseModel):
51
+ """Pmo node setup."""
52
+
53
+ circuit_type: int
54
+ power_limit: int
55
+ reverse: bool
56
+
57
+
58
+ class DefaultNodeSetup(BaseModel):
51
59
  """NodeSetup model."""
52
60
 
53
61
  sync_status: str
@@ -66,6 +74,16 @@ class NodeSetup(BaseModel):
66
74
  extra_options: NodeExtraOptions
67
75
 
68
76
 
77
+ class NodeSetup(RootModel[DefaultNodeSetup | PmoSetup]):
78
+ """NodeSetup model."""
79
+
80
+ root: DefaultNodeSetup | PmoSetup
81
+
82
+ def __getattr__(self, name: str) -> DefaultNodeSetup | PmoSetup:
83
+ """Get the root model directly."""
84
+ return getattr(self.root, name)
85
+
86
+
69
87
  class DefaultNodeStatus(BaseModel):
70
88
  """Default Node Status."""
71
89
 
@@ -196,17 +214,26 @@ class Homes(RootModel[list[Home]]):
196
214
 
197
215
 
198
216
  class Sample(BaseModel):
199
- """Sample model."""
217
+ """Pmo Sample model."""
200
218
 
201
219
  t: int
220
+ counter: float
202
221
  temp: str
203
- counter: int
222
+
223
+
224
+ class PmoSample(BaseModel):
225
+ """Default Sample."""
226
+
227
+ t: int
228
+ counter: float
229
+ max: int
230
+ min: int
204
231
 
205
232
 
206
233
  class Samples(BaseModel):
207
234
  """Samples model."""
208
235
 
209
- samples: list[Sample]
236
+ samples: list[PmoSample | Sample]
210
237
 
211
238
 
212
239
  class Token(BaseModel):
@@ -229,3 +256,9 @@ class Guests(BaseModel):
229
256
  """Guests model."""
230
257
 
231
258
  guest_users: list[GuestUser]
259
+
260
+
261
+ class DeviceConnected(BaseModel):
262
+ """Connected status of devices."""
263
+
264
+ connected: bool
@@ -1,18 +1,18 @@
1
- """Resailer of Smartbox."""
1
+ """Reseller of Smartbox."""
2
2
 
3
3
  import logging
4
4
  from typing import ClassVar
5
5
 
6
6
  from pydantic import BaseModel, ValidationError
7
7
 
8
- from smartbox.error import ResailerNotExistError
8
+ from smartbox.error import ResellerNotExistError
9
9
 
10
10
  SMARTBOX_GENERIC_BASIC_AUTH = "NTRiY2NiZmI0MWE5YTUxMTNmMDQ4OGQwOnZkaXZkaQ=="
11
11
  _LOGGER = logging.getLogger(__name__)
12
12
 
13
13
 
14
- class SmartboxResailer(BaseModel):
15
- """Model of Smartbox Resailer config."""
14
+ class SmartboxReseller(BaseModel):
15
+ """Model of Smartbox Reseller config."""
16
16
 
17
17
  name: str = "Smartbox"
18
18
  web_url: str = ""
@@ -21,43 +21,55 @@ class SmartboxResailer(BaseModel):
21
21
  serial_id: int = 0
22
22
 
23
23
 
24
- class AvailableResailers:
25
- """Resailers that have been verified."""
24
+ class AvailableResellers:
25
+ """Resellers that have been verified."""
26
26
 
27
- resailers: ClassVar[dict[str, SmartboxResailer]] = {
28
- "api": SmartboxResailer(
27
+ resellers: ClassVar[dict[str, SmartboxReseller]] = {
28
+ "api": SmartboxReseller(
29
29
  name="Helki",
30
30
  web_url="https://app.helki.com/",
31
31
  api_url="api",
32
32
  serial_id=1,
33
33
  ),
34
- "api-climastar": SmartboxResailer(
34
+ "api-ehc": SmartboxReseller(
35
+ name="Electric Heating Company",
36
+ web_url="https://control.electric-heatingcompany.co.uk/",
37
+ api_url="api-ehc",
38
+ serial_id=3,
39
+ ),
40
+ "api-climastar": SmartboxReseller(
35
41
  name="Climastar",
36
42
  web_url="https://avantwifi.climastar.es/",
37
43
  api_url="api-climastar",
38
44
  serial_id=5,
39
45
  ),
40
- "api-elnur": SmartboxResailer(
46
+ "api-elnur": SmartboxReseller(
41
47
  name="Elnur",
42
48
  web_url="https://remotecontrol.elnur.es/",
43
49
  api_url="api-elnur",
44
50
  serial_id=7,
45
51
  ),
46
- "api-hjm": SmartboxResailer(
52
+ "api-hjm": SmartboxReseller(
47
53
  name="HJM",
48
54
  web_url="https://api.calorhjm.com/",
49
55
  api_url="api-hjm",
50
56
  serial_id=10,
51
57
  ),
52
- "api-haverland": SmartboxResailer(
58
+ "api-evconfort": SmartboxReseller(
59
+ name="Electrorad",
60
+ web_url="https://app.controls-electrorad.co.uk/",
61
+ api_url="api-evconfort",
62
+ serial_id=12,
63
+ ),
64
+ "api-haverland": SmartboxReseller(
53
65
  name="Haverland",
54
66
  web_url="https://i2control.haverland.com/",
55
67
  api_url="api-haverland",
56
68
  basic_auth="NTU2ZDc0MWI3OGUzYmU5YjU2NjA3NTQ4OnZkaXZkaQ==",
57
69
  serial_id=14,
58
70
  ),
59
- "api-lhz": SmartboxResailer(
60
- name="Technotherm",
71
+ "api-lhz": SmartboxReseller(
72
+ name="Technotherm / Lucht-LHZ",
61
73
  web_url="https://ttiapp.technotherm.com/",
62
74
  api_url="api-lhz",
63
75
  serial_id=16,
@@ -72,7 +84,7 @@ class AvailableResailers:
72
84
  serial_id: int | None = None,
73
85
  name: str = "Smartbox",
74
86
  ) -> None:
75
- """Check if resailer is already available or try to create one."""
87
+ """Check if reseller is already available or try to create one."""
76
88
  self._api_url = api_url
77
89
  self._basic_auth = basic_auth
78
90
  self._web_url = web_url
@@ -80,27 +92,27 @@ class AvailableResailers:
80
92
  self._name = name
81
93
 
82
94
  @property
83
- def resailer(self) -> SmartboxResailer:
84
- """Get the resailer."""
85
- resailer = self.resailers.get(self._api_url, None)
86
- if resailer is None:
95
+ def reseller(self) -> SmartboxReseller:
96
+ """Get the reseller."""
97
+ reseller = self.resellers.get(self._api_url, None)
98
+ if reseller is None:
87
99
  if (
88
100
  self._basic_auth is None
89
101
  or self._web_url is None
90
102
  or self._serial_id is None
91
103
  ):
92
- msg = "This Resailer is not yet available or some arguments are missing."
93
- raise ResailerNotExistError(msg)
104
+ msg = "This reseller is not yet available or some arguments are missing."
105
+ raise ResellerNotExistError(msg)
94
106
  try:
95
107
  _LOGGER.debug(
96
- "Creating a new resailer api_url (%s), name=%s, web_url %s, basic_auth=%s, serial_id=%s",
108
+ "Creating a new reseller api_url (%s), name=%s, web_url %s, basic_auth=%s, serial_id=%s",
97
109
  self._api_url,
98
110
  self._name,
99
111
  self._web_url,
100
112
  self._basic_auth,
101
113
  self._serial_id,
102
114
  )
103
- resailer = SmartboxResailer(
115
+ reseller = SmartboxReseller(
104
116
  api_url=self._api_url,
105
117
  basic_auth=self._basic_auth,
106
118
  web_url=self._web_url,
@@ -108,26 +120,26 @@ class AvailableResailers:
108
120
  name=self._name,
109
121
  )
110
122
  except ValidationError as e:
111
- raise ResailerNotExistError from e
123
+ raise ResellerNotExistError from e
112
124
  _LOGGER.debug(
113
- "Resailer api_url (%s), name=%s, web_url %s",
114
- resailer.api_url,
115
- resailer.name,
116
- resailer.web_url,
125
+ "Reseller api_url (%s), name=%s, web_url %s",
126
+ reseller.api_url,
127
+ reseller.name,
128
+ reseller.web_url,
117
129
  )
118
- return resailer
130
+ return reseller
119
131
 
120
132
  @property
121
133
  def api_url(self) -> str:
122
134
  """Get the api sub domain url."""
123
- return self.resailer.api_url
135
+ return self.reseller.api_url
124
136
 
125
137
  @property
126
138
  def name(self) -> str:
127
- """Get the name of resailer."""
128
- return self.resailer.name
139
+ """Get the name of reseller."""
140
+ return self.reseller.name
129
141
 
130
142
  @property
131
143
  def web_url(self) -> str:
132
- """Get the public websit of the resailer."""
133
- return self.resailer.web_url
144
+ """Get the public websit of the reseller."""
145
+ return self.reseller.web_url