besen 0.3.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.
besen-0.3.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yoav Mor
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
besen-0.3.0/NOTICE.md ADDED
@@ -0,0 +1,8 @@
1
+ # Notices
2
+
3
+ Portions of the Besen Bluetooth protocol implementation are derived from
4
+ the MIT-licensed `slespersen/evseMQTT` project by slespersen and contributors:
5
+
6
+ https://github.com/slespersen/evseMQTT
7
+
8
+ See `LICENSE` for this project's MIT license terms.
besen-0.3.0/PKG-INFO ADDED
@@ -0,0 +1,261 @@
1
+ Metadata-Version: 2.4
2
+ Name: besen
3
+ Version: 0.3.0
4
+ Summary: Async Python client for Besen EV chargers over BLE
5
+ Author-email: Yoav Mor <moryoav@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/moryoav/ha_besen
8
+ Project-URL: Repository, https://github.com/moryoav/ha_besen
9
+ Project-URL: Issues, https://github.com/moryoav/ha_besen/issues
10
+ Project-URL: Changelog, https://github.com/moryoav/ha_besen/blob/main/CHANGELOG.md
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Framework :: AsyncIO
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Home Automation
18
+ Requires-Python: >=3.12
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ License-File: NOTICE.md
22
+ Requires-Dist: bleak-retry-connector>=3.10.0
23
+ Provides-Extra: dev
24
+ Requires-Dist: build>=1.2.0; extra == "dev"
25
+ Requires-Dist: homeassistant>=2025.1.0; extra == "dev"
26
+ Requires-Dist: mypy>=1.16.0; extra == "dev"
27
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
28
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
29
+ Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
30
+ Requires-Dist: ruff>=0.8.0; extra == "dev"
31
+ Requires-Dist: twine>=6.0.0; extra == "dev"
32
+ Dynamic: license-file
33
+
34
+ # Besen Home Assistant Integration and Python Library
35
+ [![HACS][hacs-badge]][hacs-url] [![release][release-badge]][release-url] ![downloads][downloads-badge] [![hassfest][hassfest-badge]][hassfest-url] [![validate][validate-badge]][validate-url] [![license][license-badge]][license-url]
36
+
37
+ Native Home Assistant integration for Besen EV chargers over Bluetooth Low Energy. This has been verified with the BS20 model.
38
+
39
+ This integration talks directly to the charger through Home Assistant's Bluetooth stack. It does not need MQTT, Docker, a sidecar process, or a Home Assistant add-on. It is designed to work through existing ESPHome Bluetooth proxies as long as those proxies support active GATT connections.
40
+
41
+ ## Python Library
42
+
43
+ The reusable BLE client and protocol parser are published as the `besen` Python package. Home Assistant installs that package as this integration's communication dependency.
44
+
45
+ ```bash
46
+ pip install besen
47
+ ```
48
+
49
+ ## Disclaimer
50
+
51
+ This is an unofficial community project. It is not affiliated with, associated with, authorized by, endorsed by, or in any way officially connected with BESEN, Besen Group, or any related company. Product names, trademarks, and registered trademarks belong to their respective owners and are used only to identify compatible devices.
52
+
53
+ Use this integration at your own risk. EV charging equipment controls real electrical hardware; incorrect configuration, device firmware behavior, Bluetooth issues, automation mistakes, or software defects may cause charging interruption, equipment damage, vehicle damage, electrical hazards, or other loss. The maintainer and contributors are not responsible or liable for damage, injury, data loss, costs, or other consequences arising from use of this integration.
54
+
55
+ ## Requirements
56
+
57
+ - Home Assistant with the Bluetooth integration enabled.
58
+ - A Besen charger advertising as `ACP#...`; the BS20 model has been verified.
59
+ - The charger BLE address and 6-digit PIN.
60
+ - For ESPHome Bluetooth proxies:
61
+ - `bluetooth_proxy:` with active connections enabled.
62
+ - A connectable proxy close enough to the charger.
63
+ - Enough free active connection slots.
64
+
65
+ ESPHome Bluetooth proxies default to active connections enabled in current ESPHome releases. Each continuously connected charger uses one active GATT connection slot on the selected proxy.
66
+
67
+ ## Migrating From evseMQTT
68
+
69
+ If you previously used evseMQTT with the same charger, fully stop or terminate the old evseMQTT bridge before installing this integration. This includes any Docker container, Home Assistant add-on, Raspberry Pi service, systemd unit, or other process that may still connect to the charger.
70
+
71
+ The charger can only keep one active BLE client connection. In some cases, after evseMQTT has been stopped, you may also need to turn the EV charger off and back on so it forgets the old component pairing before Home Assistant can discover or connect to it through this integration.
72
+
73
+ ## Installation
74
+
75
+ ### HACS custom repository
76
+
77
+ [![Open the Besen HACS repository](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=moryoav&repository=ha_besen&category=integration)
78
+
79
+ 1. Open HACS.
80
+ 2. Add this repository as a custom integration repository.
81
+ 3. Install **Besen**.
82
+ 4. Restart Home Assistant.
83
+ 5. Go to **Settings > Devices & services**.
84
+ 6. Add **Besen** or accept the discovered `ACP#...` device.
85
+
86
+ HACS uses GitHub releases when they are available. Install the latest release tag unless you explicitly want to test the default branch.
87
+
88
+ ### Manual installation
89
+
90
+ 1. Copy `custom_components/besen` into your Home Assistant `custom_components` directory.
91
+ 2. Restart Home Assistant.
92
+ 3. Add **Besen** from **Settings > Devices & services**.
93
+
94
+ ## Configuration
95
+
96
+ [![Add the Besen integration](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start/?domain=besen)
97
+
98
+ - **BLE address**: The charger Bluetooth address. Discovery fills this automatically when Home Assistant sees an `ACP#...` advertisement.
99
+ - **PIN**: The charger's 6-digit Bluetooth PIN. Many units default to `123456`.
100
+ - **Sync charger clock**: Keeps the charger's internal clock aligned during heartbeat responses.
101
+
102
+ The PIN can be updated later through the integration reconfigure flow.
103
+
104
+ ## Entities
105
+
106
+ The exact entity set depends on charger model, board revision, reported phase count, and supported firmware responses.
107
+
108
+ Enabled by default:
109
+
110
+ - Charge switch.
111
+ - Charge amps number.
112
+ - Current Energy sensor.
113
+ - Total/session energy sensors.
114
+ - L1 Voltage and L1 Amperage.
115
+ - Charger status, plug state, output state, current state, and error state.
116
+ - Charger temperature.
117
+ - Device name text entity.
118
+ - Temperature unit and language selectors.
119
+
120
+ Diagnostic or less commonly used entities may be disabled by default:
121
+
122
+ - RSSI.
123
+ - L2/L3 Voltage and Amperage on three-phase chargers.
124
+ - System time.
125
+ - LCD brightness.
126
+ - Integration/protocol version details.
127
+
128
+ ## Controls And Actions
129
+
130
+ The integration does not register custom Home Assistant service actions. Use the standard entity actions instead:
131
+
132
+ - `switch.turn_on` / `switch.turn_off` on the charging switch.
133
+ - `number.set_value` on charge amps.
134
+ - `select.select_option` on language or temperature unit.
135
+ - `text.set_value` on the charger name.
136
+
137
+ Command failures are raised back to Home Assistant and the device is marked unavailable if the BLE write path fails.
138
+
139
+ ## Updating Data
140
+
141
+ The charger sends status over BLE notifications after login. Home Assistant keeps one active BLE connection open, listens for notifications, and responds to charger heartbeats. If notifications stop for about 45 seconds, the integration reconnects without repeatedly filling the logs.
142
+
143
+ This is a local-push integration. There is no cloud dependency.
144
+
145
+ ## Common Automations
146
+
147
+ Start charging when solar surplus is available:
148
+
149
+ ```yaml
150
+ alias: Start EV charging on solar surplus
151
+ triggers:
152
+ - trigger: numeric_state
153
+ entity_id: sensor.solar_surplus_power
154
+ above: 2500
155
+ for: "00:05:00"
156
+ conditions:
157
+ - condition: state
158
+ entity_id: sensor.besen_plug_state
159
+ state: Connected Locked
160
+ actions:
161
+ - action: number.set_value
162
+ target:
163
+ entity_id: number.besen_charge_amps
164
+ data:
165
+ value: 8
166
+ - action: switch.turn_on
167
+ target:
168
+ entity_id: switch.besen_charging
169
+ ```
170
+
171
+ Stop charging before peak tariff:
172
+
173
+ ```yaml
174
+ alias: Stop EV charging before peak tariff
175
+ triggers:
176
+ - trigger: time
177
+ at: "17:00:00"
178
+ actions:
179
+ - action: switch.turn_off
180
+ target:
181
+ entity_id: switch.besen_charging
182
+ ```
183
+
184
+ ## Supported Devices
185
+
186
+ Known target:
187
+
188
+ - [Besen BS20 EV Charging Station](https://www.besen-group.com/products/ev-charging-station/bs20/).
189
+
190
+ Likely compatible:
191
+
192
+ - Besen wallboxes using the same `ACP#` BLE protocol and one of the known UUID pairs.
193
+
194
+ Unsupported or not implemented:
195
+
196
+ - Wi-Fi provisioning.
197
+ - Password reset.
198
+ - Device reset.
199
+ - Charging history download.
200
+ - Firmware updates through Home Assistant.
201
+ - Safety-certified load balancing.
202
+
203
+ ## Troubleshooting
204
+
205
+ ### The charger is not discovered
206
+
207
+ - Confirm it appears in **Settings > Bluetooth > Advertisement monitor** as `ACP#...`.
208
+ - Move an ESPHome Bluetooth proxy closer to the charger.
209
+ - Make sure the proxy is added to Home Assistant through the ESPHome integration.
210
+ - Run an active scan or temporarily place a local Bluetooth adapter near the charger.
211
+
212
+ ### Setup says no connectable Bluetooth path is available
213
+
214
+ The charger may be visible only through a passive/non-connectable adapter. Use an ESPHome Bluetooth proxy with active connections enabled, or a local Bluetooth adapter supported by Home Assistant.
215
+
216
+ Stop any existing evseMQTT bridge, Docker container, add-on, Raspberry Pi service, or other app that is already connected to the charger before setting up this integration. The charger can expose live data through the old MQTT bridge while Home Assistant has no free connectable BLE path for the native integration.
217
+
218
+ ### The charger becomes unavailable
219
+
220
+ - Check **Settings > Bluetooth > Connection monitor**.
221
+ - Verify the proxy has free active connection slots.
222
+ - Stop any old evseMQTT/MQTT bridge or companion process that may still hold the charger's BLE connection.
223
+ - Prefer Ethernet ESP32 Bluetooth proxies when possible.
224
+ - Avoid placing the proxy next to strong Wi-Fi or USB 3.0 interference sources.
225
+
226
+ ### The PIN is rejected
227
+
228
+ Use the integration reauthentication prompt or reconfigure flow to enter the correct 6-digit PIN. The integration redacts PINs from diagnostics.
229
+
230
+ ### Diagnostics
231
+
232
+ From the device page, download diagnostics before opening an issue. Diagnostics include the board revision, charger metadata, latest parsed state, availability, and last error. The PIN is redacted.
233
+
234
+ ## Removal
235
+
236
+ 1. Go to **Settings > Devices & services**.
237
+ 2. Open **Besen**.
238
+ 3. Select the integration menu and choose **Delete**.
239
+ 4. Restart Home Assistant if you also manually copied the integration files and want to remove them from `custom_components`.
240
+
241
+ ## Safety Notes
242
+
243
+ This integration exposes charger controls but is not a safety controller. Do not rely on it as the only protection for electrical limits, overheating, grid constraints, or vehicle safety. Keep charger hardware, breaker sizing, wiring, and local electrical code protections correct independently of Home Assistant. Use manual supervision and conservative automation defaults when controlling charging equipment.
244
+
245
+ ## Attribution
246
+
247
+ The Bluetooth protocol implementation is based on the MIT-licensed work in [slespersen/evseMQTT](https://github.com/slespersen/evseMQTT), with the MQTT/runtime portions replaced by native Home Assistant integration code.
248
+
249
+ Additional attribution details are maintained in [NOTICE.md](NOTICE.md).
250
+
251
+ [hacs-badge]: https://img.shields.io/badge/HACS-Custom-41BDF5.svg?style=flat-square
252
+ [hacs-url]: https://github.com/hacs/integration
253
+ [release-badge]: https://img.shields.io/github/v/release/moryoav/ha_besen?style=flat-square
254
+ [release-url]: https://github.com/moryoav/ha_besen/releases
255
+ [downloads-badge]: https://img.shields.io/github/downloads/moryoav/ha_besen/total?style=flat-square
256
+ [hassfest-badge]: https://img.shields.io/github/actions/workflow/status/moryoav/ha_besen/hassfest.yaml?branch=main&style=flat-square&label=hassfest
257
+ [hassfest-url]: https://github.com/moryoav/ha_besen/actions/workflows/hassfest.yaml
258
+ [validate-badge]: https://img.shields.io/github/actions/workflow/status/moryoav/ha_besen/validate.yaml?branch=main&style=flat-square&label=validate
259
+ [validate-url]: https://github.com/moryoav/ha_besen/actions/workflows/validate.yaml
260
+ [license-badge]: https://img.shields.io/github/license/moryoav/ha_besen?style=flat-square
261
+ [license-url]: https://github.com/moryoav/ha_besen/blob/main/LICENSE
besen-0.3.0/README.md ADDED
@@ -0,0 +1,228 @@
1
+ # Besen Home Assistant Integration and Python Library
2
+ [![HACS][hacs-badge]][hacs-url] [![release][release-badge]][release-url] ![downloads][downloads-badge] [![hassfest][hassfest-badge]][hassfest-url] [![validate][validate-badge]][validate-url] [![license][license-badge]][license-url]
3
+
4
+ Native Home Assistant integration for Besen EV chargers over Bluetooth Low Energy. This has been verified with the BS20 model.
5
+
6
+ This integration talks directly to the charger through Home Assistant's Bluetooth stack. It does not need MQTT, Docker, a sidecar process, or a Home Assistant add-on. It is designed to work through existing ESPHome Bluetooth proxies as long as those proxies support active GATT connections.
7
+
8
+ ## Python Library
9
+
10
+ The reusable BLE client and protocol parser are published as the `besen` Python package. Home Assistant installs that package as this integration's communication dependency.
11
+
12
+ ```bash
13
+ pip install besen
14
+ ```
15
+
16
+ ## Disclaimer
17
+
18
+ This is an unofficial community project. It is not affiliated with, associated with, authorized by, endorsed by, or in any way officially connected with BESEN, Besen Group, or any related company. Product names, trademarks, and registered trademarks belong to their respective owners and are used only to identify compatible devices.
19
+
20
+ Use this integration at your own risk. EV charging equipment controls real electrical hardware; incorrect configuration, device firmware behavior, Bluetooth issues, automation mistakes, or software defects may cause charging interruption, equipment damage, vehicle damage, electrical hazards, or other loss. The maintainer and contributors are not responsible or liable for damage, injury, data loss, costs, or other consequences arising from use of this integration.
21
+
22
+ ## Requirements
23
+
24
+ - Home Assistant with the Bluetooth integration enabled.
25
+ - A Besen charger advertising as `ACP#...`; the BS20 model has been verified.
26
+ - The charger BLE address and 6-digit PIN.
27
+ - For ESPHome Bluetooth proxies:
28
+ - `bluetooth_proxy:` with active connections enabled.
29
+ - A connectable proxy close enough to the charger.
30
+ - Enough free active connection slots.
31
+
32
+ ESPHome Bluetooth proxies default to active connections enabled in current ESPHome releases. Each continuously connected charger uses one active GATT connection slot on the selected proxy.
33
+
34
+ ## Migrating From evseMQTT
35
+
36
+ If you previously used evseMQTT with the same charger, fully stop or terminate the old evseMQTT bridge before installing this integration. This includes any Docker container, Home Assistant add-on, Raspberry Pi service, systemd unit, or other process that may still connect to the charger.
37
+
38
+ The charger can only keep one active BLE client connection. In some cases, after evseMQTT has been stopped, you may also need to turn the EV charger off and back on so it forgets the old component pairing before Home Assistant can discover or connect to it through this integration.
39
+
40
+ ## Installation
41
+
42
+ ### HACS custom repository
43
+
44
+ [![Open the Besen HACS repository](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=moryoav&repository=ha_besen&category=integration)
45
+
46
+ 1. Open HACS.
47
+ 2. Add this repository as a custom integration repository.
48
+ 3. Install **Besen**.
49
+ 4. Restart Home Assistant.
50
+ 5. Go to **Settings > Devices & services**.
51
+ 6. Add **Besen** or accept the discovered `ACP#...` device.
52
+
53
+ HACS uses GitHub releases when they are available. Install the latest release tag unless you explicitly want to test the default branch.
54
+
55
+ ### Manual installation
56
+
57
+ 1. Copy `custom_components/besen` into your Home Assistant `custom_components` directory.
58
+ 2. Restart Home Assistant.
59
+ 3. Add **Besen** from **Settings > Devices & services**.
60
+
61
+ ## Configuration
62
+
63
+ [![Add the Besen integration](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start/?domain=besen)
64
+
65
+ - **BLE address**: The charger Bluetooth address. Discovery fills this automatically when Home Assistant sees an `ACP#...` advertisement.
66
+ - **PIN**: The charger's 6-digit Bluetooth PIN. Many units default to `123456`.
67
+ - **Sync charger clock**: Keeps the charger's internal clock aligned during heartbeat responses.
68
+
69
+ The PIN can be updated later through the integration reconfigure flow.
70
+
71
+ ## Entities
72
+
73
+ The exact entity set depends on charger model, board revision, reported phase count, and supported firmware responses.
74
+
75
+ Enabled by default:
76
+
77
+ - Charge switch.
78
+ - Charge amps number.
79
+ - Current Energy sensor.
80
+ - Total/session energy sensors.
81
+ - L1 Voltage and L1 Amperage.
82
+ - Charger status, plug state, output state, current state, and error state.
83
+ - Charger temperature.
84
+ - Device name text entity.
85
+ - Temperature unit and language selectors.
86
+
87
+ Diagnostic or less commonly used entities may be disabled by default:
88
+
89
+ - RSSI.
90
+ - L2/L3 Voltage and Amperage on three-phase chargers.
91
+ - System time.
92
+ - LCD brightness.
93
+ - Integration/protocol version details.
94
+
95
+ ## Controls And Actions
96
+
97
+ The integration does not register custom Home Assistant service actions. Use the standard entity actions instead:
98
+
99
+ - `switch.turn_on` / `switch.turn_off` on the charging switch.
100
+ - `number.set_value` on charge amps.
101
+ - `select.select_option` on language or temperature unit.
102
+ - `text.set_value` on the charger name.
103
+
104
+ Command failures are raised back to Home Assistant and the device is marked unavailable if the BLE write path fails.
105
+
106
+ ## Updating Data
107
+
108
+ The charger sends status over BLE notifications after login. Home Assistant keeps one active BLE connection open, listens for notifications, and responds to charger heartbeats. If notifications stop for about 45 seconds, the integration reconnects without repeatedly filling the logs.
109
+
110
+ This is a local-push integration. There is no cloud dependency.
111
+
112
+ ## Common Automations
113
+
114
+ Start charging when solar surplus is available:
115
+
116
+ ```yaml
117
+ alias: Start EV charging on solar surplus
118
+ triggers:
119
+ - trigger: numeric_state
120
+ entity_id: sensor.solar_surplus_power
121
+ above: 2500
122
+ for: "00:05:00"
123
+ conditions:
124
+ - condition: state
125
+ entity_id: sensor.besen_plug_state
126
+ state: Connected Locked
127
+ actions:
128
+ - action: number.set_value
129
+ target:
130
+ entity_id: number.besen_charge_amps
131
+ data:
132
+ value: 8
133
+ - action: switch.turn_on
134
+ target:
135
+ entity_id: switch.besen_charging
136
+ ```
137
+
138
+ Stop charging before peak tariff:
139
+
140
+ ```yaml
141
+ alias: Stop EV charging before peak tariff
142
+ triggers:
143
+ - trigger: time
144
+ at: "17:00:00"
145
+ actions:
146
+ - action: switch.turn_off
147
+ target:
148
+ entity_id: switch.besen_charging
149
+ ```
150
+
151
+ ## Supported Devices
152
+
153
+ Known target:
154
+
155
+ - [Besen BS20 EV Charging Station](https://www.besen-group.com/products/ev-charging-station/bs20/).
156
+
157
+ Likely compatible:
158
+
159
+ - Besen wallboxes using the same `ACP#` BLE protocol and one of the known UUID pairs.
160
+
161
+ Unsupported or not implemented:
162
+
163
+ - Wi-Fi provisioning.
164
+ - Password reset.
165
+ - Device reset.
166
+ - Charging history download.
167
+ - Firmware updates through Home Assistant.
168
+ - Safety-certified load balancing.
169
+
170
+ ## Troubleshooting
171
+
172
+ ### The charger is not discovered
173
+
174
+ - Confirm it appears in **Settings > Bluetooth > Advertisement monitor** as `ACP#...`.
175
+ - Move an ESPHome Bluetooth proxy closer to the charger.
176
+ - Make sure the proxy is added to Home Assistant through the ESPHome integration.
177
+ - Run an active scan or temporarily place a local Bluetooth adapter near the charger.
178
+
179
+ ### Setup says no connectable Bluetooth path is available
180
+
181
+ The charger may be visible only through a passive/non-connectable adapter. Use an ESPHome Bluetooth proxy with active connections enabled, or a local Bluetooth adapter supported by Home Assistant.
182
+
183
+ Stop any existing evseMQTT bridge, Docker container, add-on, Raspberry Pi service, or other app that is already connected to the charger before setting up this integration. The charger can expose live data through the old MQTT bridge while Home Assistant has no free connectable BLE path for the native integration.
184
+
185
+ ### The charger becomes unavailable
186
+
187
+ - Check **Settings > Bluetooth > Connection monitor**.
188
+ - Verify the proxy has free active connection slots.
189
+ - Stop any old evseMQTT/MQTT bridge or companion process that may still hold the charger's BLE connection.
190
+ - Prefer Ethernet ESP32 Bluetooth proxies when possible.
191
+ - Avoid placing the proxy next to strong Wi-Fi or USB 3.0 interference sources.
192
+
193
+ ### The PIN is rejected
194
+
195
+ Use the integration reauthentication prompt or reconfigure flow to enter the correct 6-digit PIN. The integration redacts PINs from diagnostics.
196
+
197
+ ### Diagnostics
198
+
199
+ From the device page, download diagnostics before opening an issue. Diagnostics include the board revision, charger metadata, latest parsed state, availability, and last error. The PIN is redacted.
200
+
201
+ ## Removal
202
+
203
+ 1. Go to **Settings > Devices & services**.
204
+ 2. Open **Besen**.
205
+ 3. Select the integration menu and choose **Delete**.
206
+ 4. Restart Home Assistant if you also manually copied the integration files and want to remove them from `custom_components`.
207
+
208
+ ## Safety Notes
209
+
210
+ This integration exposes charger controls but is not a safety controller. Do not rely on it as the only protection for electrical limits, overheating, grid constraints, or vehicle safety. Keep charger hardware, breaker sizing, wiring, and local electrical code protections correct independently of Home Assistant. Use manual supervision and conservative automation defaults when controlling charging equipment.
211
+
212
+ ## Attribution
213
+
214
+ The Bluetooth protocol implementation is based on the MIT-licensed work in [slespersen/evseMQTT](https://github.com/slespersen/evseMQTT), with the MQTT/runtime portions replaced by native Home Assistant integration code.
215
+
216
+ Additional attribution details are maintained in [NOTICE.md](NOTICE.md).
217
+
218
+ [hacs-badge]: https://img.shields.io/badge/HACS-Custom-41BDF5.svg?style=flat-square
219
+ [hacs-url]: https://github.com/hacs/integration
220
+ [release-badge]: https://img.shields.io/github/v/release/moryoav/ha_besen?style=flat-square
221
+ [release-url]: https://github.com/moryoav/ha_besen/releases
222
+ [downloads-badge]: https://img.shields.io/github/downloads/moryoav/ha_besen/total?style=flat-square
223
+ [hassfest-badge]: https://img.shields.io/github/actions/workflow/status/moryoav/ha_besen/hassfest.yaml?branch=main&style=flat-square&label=hassfest
224
+ [hassfest-url]: https://github.com/moryoav/ha_besen/actions/workflows/hassfest.yaml
225
+ [validate-badge]: https://img.shields.io/github/actions/workflow/status/moryoav/ha_besen/validate.yaml?branch=main&style=flat-square&label=validate
226
+ [validate-url]: https://github.com/moryoav/ha_besen/actions/workflows/validate.yaml
227
+ [license-badge]: https://img.shields.io/github/license/moryoav/ha_besen?style=flat-square
228
+ [license-url]: https://github.com/moryoav/ha_besen/blob/main/LICENSE
@@ -0,0 +1,87 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "besen"
7
+ version = "0.3.0"
8
+ description = "Async Python client for Besen EV chargers over BLE"
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ license = "MIT"
12
+ license-files = ["LICENSE", "NOTICE.md"]
13
+ authors = [{ name = "Yoav Mor", email = "moryoav@gmail.com" }]
14
+ dependencies = [
15
+ "bleak-retry-connector>=3.10.0",
16
+ ]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Framework :: AsyncIO",
20
+ "Intended Audience :: Developers",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Topic :: Home Automation",
25
+ ]
26
+
27
+ [project.urls]
28
+ Homepage = "https://github.com/moryoav/ha_besen"
29
+ Repository = "https://github.com/moryoav/ha_besen"
30
+ Issues = "https://github.com/moryoav/ha_besen/issues"
31
+ Changelog = "https://github.com/moryoav/ha_besen/blob/main/CHANGELOG.md"
32
+
33
+ [project.optional-dependencies]
34
+ dev = [
35
+ "build>=1.2.0",
36
+ "homeassistant>=2025.1.0",
37
+ "mypy>=1.16.0",
38
+ "pytest>=8.0.0",
39
+ "pytest-asyncio>=0.23.0",
40
+ "pytest-cov>=5.0.0",
41
+ "ruff>=0.8.0",
42
+ "twine>=6.0.0",
43
+ ]
44
+
45
+ [tool.setuptools.packages.find]
46
+ where = ["src"]
47
+
48
+ [tool.pytest.ini_options]
49
+ asyncio_mode = "auto"
50
+ testpaths = ["tests"]
51
+ pythonpath = ["src", "."]
52
+
53
+ [tool.coverage.run]
54
+ branch = true
55
+ source = ["custom_components/besen", "src/besen"]
56
+ omit = [
57
+ "custom_components/besen/translations/*",
58
+ ]
59
+
60
+ [tool.coverage.report]
61
+ fail_under = 95
62
+ show_missing = true
63
+ skip_covered = true
64
+
65
+ [tool.ruff]
66
+ target-version = "py312"
67
+ line-length = 88
68
+
69
+ [tool.ruff.lint]
70
+ select = ["A", "ASYNC", "B", "C4", "DTZ", "E", "F", "FA", "I", "ICN", "N", "PERF", "PIE", "PTH", "RET", "RUF", "SIM", "T20", "UP", "W"]
71
+ ignore = ["ASYNC109", "N818"]
72
+
73
+ [tool.ruff.lint.isort]
74
+ known-first-party = ["besen", "custom_components.besen"]
75
+
76
+ [tool.mypy]
77
+ python_version = "3.13"
78
+ strict = true
79
+ warn_unreachable = true
80
+ explicit_package_bases = true
81
+ mypy_path = "src"
82
+ files = ["src/besen", "custom_components/besen", "tests"]
83
+ exclude = ["build", "dist", "besen.egg-info", "besen_bs20.egg-info", "ha_besen_bs20.egg-info"]
84
+
85
+ [[tool.mypy.overrides]]
86
+ module = ["bleak.*", "bleak_retry_connector.*"]
87
+ ignore_missing_imports = true
besen-0.3.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,41 @@
1
+ """Async Python client for Besen EV chargers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from .client import BesenClient
6
+ from .exceptions import (
7
+ BesenError,
8
+ CannotConnect,
9
+ CommandFailed,
10
+ InvalidAuth,
11
+ NoConnectablePath,
12
+ ProtocolError,
13
+ )
14
+ from .models import (
15
+ BesenData,
16
+ BoardRevision,
17
+ CharacteristicPair,
18
+ ChargerConfig,
19
+ ChargerInfo,
20
+ ChargeStatus,
21
+ CommandResult,
22
+ )
23
+
24
+ __version__ = "0.3.0"
25
+
26
+ __all__ = [
27
+ "BesenClient",
28
+ "BesenData",
29
+ "BesenError",
30
+ "BoardRevision",
31
+ "CannotConnect",
32
+ "CharacteristicPair",
33
+ "ChargeStatus",
34
+ "ChargerConfig",
35
+ "ChargerInfo",
36
+ "CommandFailed",
37
+ "CommandResult",
38
+ "InvalidAuth",
39
+ "NoConnectablePath",
40
+ "ProtocolError",
41
+ ]