bluetti-bt-connect-lib 1.5.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.
- bluetti_bt_connect_lib-1.5.0/LICENSE +22 -0
- bluetti_bt_connect_lib-1.5.0/PKG-INFO +280 -0
- bluetti_bt_connect_lib-1.5.0/README.md +252 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/__init__.py +21 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/base_devices/__init__.py +3 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/base_devices/base_device_v1.py +50 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/base_devices/base_device_v2.py +46 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/base_devices/bluetti_device.py +255 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/bluetooth/__init__.py +3 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/bluetooth/device_reader.py +306 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/bluetooth/device_recognizer.py +90 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/bluetooth/device_writer.py +78 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/const.py +2 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/__init__.py +67 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac180.py +43 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac180p.py +20 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac180t.py +21 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac200l.py +34 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac200m.py +27 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac200pl.py +27 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac2a.py +18 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac2p.py +38 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac300.py +48 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac500.py +35 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac50b.py +14 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac60.py +18 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac60p.py +18 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac70.py +41 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ac70p.py +21 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ap300.py +15 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/eb3a.py +29 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/el100v2.py +15 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/el30v2.py +27 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ep2000.py +156 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ep500.py +35 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ep500p.py +35 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ep600.py +73 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ep760.py +27 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/ep800.py +5 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/handsfree1.py +22 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/pr100v2.py +15 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/devices/pr30v2.py +15 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/enums/__init__.py +8 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/enums/charging_mode.py +8 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/enums/display_mode.py +9 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/enums/eco_mode.py +9 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/enums/frequency_mode.py +8 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/enums/led_mode.py +9 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/enums/output_mode.py +10 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/enums/split_phase_mode.py +7 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/enums/ups_mode.py +9 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/enums/working_mode.py +9 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/exceptions.py +21 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/BoolField.py +16 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/BoolFieldNonZero.py +23 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/DecimalArrayField.py +14 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/DecimalField.py +32 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/DeviceField.py +22 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/EnumField.py +22 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/FieldName.py +131 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/FieldUnit.py +90 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/SInt32Field.py +45 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/SIntField.py +45 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/SelectField.py +19 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/SerialNumberField.py +15 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/StringField.py +9 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/SwapStringField.py +17 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/SwitchField.py +11 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/UIntField.py +31 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/VersionField.py +16 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/WriteableStringField.py +42 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/WriteableUIntField.py +28 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/fields/__init__.py +20 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/registers/DeviceRegister.py +50 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/registers/ReadableRegisters.py +34 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/registers/WriteableRegister.py +19 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/registers/WriteableRegisters.py +38 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/registers/__init__.py +4 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/scripts/__init__.py +0 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/scripts/bluetti_detect.py +38 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/scripts/bluetti_parse.py +70 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/scripts/bluetti_read.py +58 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/scripts/bluetti_readall.py +73 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/scripts/bluetti_scan.py +68 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/scripts/bluetti_write.py +96 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/scripts/types.py +17 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/utils/__init__.py +0 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/utils/bleak_client_mock.py +114 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/utils/device_builder.py +24 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/utils/device_info.py +18 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib/utils/privacy.py +4 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib.egg-info/PKG-INFO +280 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib.egg-info/SOURCES.txt +97 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib.egg-info/dependency_links.txt +1 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib.egg-info/entry_points.txt +7 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib.egg-info/requires.txt +7 -0
- bluetti_bt_connect_lib-1.5.0/bluetti_bt_connect_lib.egg-info/top_level.txt +1 -0
- bluetti_bt_connect_lib-1.5.0/setup.cfg +4 -0
- bluetti_bt_connect_lib-1.5.0/setup.py +80 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Patrick762
|
|
4
|
+
Copyright (c) 2026 Elliott Monaghan (modifications for Bluetti BT Connect)
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bluetti-bt-connect-lib
|
|
3
|
+
Version: 1.5.0
|
|
4
|
+
Summary: Bluetti BT Connect - Bluetooth library for Bluetti power stations (fork of bluetti-bt-lib by Patrick762)
|
|
5
|
+
Home-page: https://github.com/Elliottmonaghan/bluetti-bt-connect-lib
|
|
6
|
+
Author: Elliott Monaghan
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: async_timeout
|
|
14
|
+
Requires-Dist: bleak
|
|
15
|
+
Requires-Dist: bleak_retry_connector
|
|
16
|
+
Requires-Dist: crcmod
|
|
17
|
+
Requires-Dist: typing_extensions; python_version < "3.12"
|
|
18
|
+
Dynamic: author
|
|
19
|
+
Dynamic: classifier
|
|
20
|
+
Dynamic: description
|
|
21
|
+
Dynamic: description-content-type
|
|
22
|
+
Dynamic: home-page
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
Dynamic: requires-dist
|
|
25
|
+
Dynamic: requires-python
|
|
26
|
+
Dynamic: summary
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# bluetti-bt-connect-lib
|
|
30
|
+
|
|
31
|
+
> **This is a fork** of [bluetti-bt-lib](https://github.com/Patrick762/bluetti-bt-lib) by [Patrick762](https://github.com/Patrick762), extended with additional device support, register corrections, and new writable fields for the Bluetti EP2000. All credit for the original protocol reverse-engineering, architecture, and core library design goes to Patrick762 and the project's other contributors. This fork exists to track device-specific fixes and additions on a faster iteration cycle; where possible, improvements are intended to be contributed back upstream.
|
|
32
|
+
>
|
|
33
|
+
> Original repository: https://github.com/Patrick762/bluetti-bt-lib
|
|
34
|
+
>
|
|
35
|
+
> Additional credit to [atiweb/hassio-bluetti-bt](https://github.com/atiweb/hassio-bluetti-bt), a separate fork of the original project, cross-referenced for two specific fixes: correcting `consumption_power_all`, `pv_input_power_all`, and `grid_power_all` from incorrectly-assumed 32-bit fields to plain 16-bit fields (validated against real captured data), and the pattern for proper Modbus response validation (CRC checking and exception-response detection) now used in `device_reader.py`.
|
|
36
|
+
|
|
37
|
+
Inofficial Library for basic communication to bluetti powerstations.
|
|
38
|
+
Core functions based on https://github.com/warhammerkid/bluetti_mqtt
|
|
39
|
+
|
|
40
|
+
## Disclaimer
|
|
41
|
+
This library is provided without any warranty or support by Bluetti. I do not take responsibility for any problems it may cause in all cases. Use it at your own risk.
|
|
42
|
+
|
|
43
|
+
## ⚠️ EP2000: grid/mode controls carry real risk - read before using
|
|
44
|
+
|
|
45
|
+
**AC Output, Charge From Grid, Grid Export, Working Mode, and all four grid import/export power and current limits remain writable in this build.** Before you rely on any of them, please understand what we found while investigating this device.
|
|
46
|
+
|
|
47
|
+
**The core problem:** writes into this device's grid-related register block can get a clean, protocol-valid acknowledgment from the device - and then the change does not actually take effect. This was confirmed at the raw byte level, ruling out a simple wrong-address or scaling issue. In practice this means: **you may set a limit in Home Assistant, see it accepted with no error, and the device may still be running on its old setting.** Nothing in the app or the integration will reliably tell you a write didn't stick - the failure is silent. Do not assume a control has taken effect on the device just because Home Assistant shows no error; if you change one of these settings, verify the result independently (in the Bluetti app, or against real grid behavior) before relying on it.
|
|
48
|
+
|
|
49
|
+
**Why we believe this happens:** a research pass across comparable BLE-connected solar/battery projects (EcoFlow, Renogy, Growatt, Deye/Sunsynk, Anker SOLIX, Marstek, several open-source BMS forks) found that grid-facing settings - export/import limits, working mode, grid protection - are consistently gated behind some form of vendor authentication across the entire industry, not just on Bluetti hardware: a cloud-account round-trip, a licensed BLE encryption handshake keyed to the device's serial number, or a support-issued password. The EP2000 fits this pattern - there's a genuine "Pro Mode" authentication layer here, and while we confirmed the universal technician password Bluetti documents publicly ("88888888"), simply knowing that password did not make writes persist, which points at a session or encryption-level gate underneath it that hasn't been reverse-engineered.
|
|
50
|
+
|
|
51
|
+
**Why we haven't removed these controls outright:** unlike the grid-compliance layer itself, some of these fields (notably the AC Output and Grid Export switches, and Max Grid Export Current) were live-tested and confirmed to actually take effect on this specific unit at various points during development. Reliability may vary by field, by firmware version, and possibly by unit - which is exactly why blanket trust in any of them is the wrong approach. Treat every write as unverified until you've checked its real-world effect yourself.
|
|
52
|
+
|
|
53
|
+
**Grid export and grid-protection parameters are regulated for interconnection safety in most jurisdictions** (anti-islanding, voltage/frequency ride-through). Changing them, even successfully, may have real compliance implications depending on where you live and how your system is set up. This is worth knowing regardless of whether a given write actually persists.
|
|
54
|
+
|
|
55
|
+
**If you're an advanced user or researcher**: the full research writeup and the exact register-level evidence behind the above are referenced in this version's release notes. The realistic next step for confirming or defeating the authentication gate isn't more register-guessing - it's capturing the official app's authenticated write sequence directly (Android Bluetooth HCI snoop log, or hooking the app's write call with Frida).
|
|
56
|
+
|
|
57
|
+
## Projects using this library
|
|
58
|
+
|
|
59
|
+
- [Bluetti BT Connect - Home Assistant Integration](https://github.com/Elliottmonaghan/bluetti-bt-connect) (this fork's companion integration)
|
|
60
|
+
- [Original Home Assistant Integration](https://github.com/Patrick762/hassio-bluetti-bt)
|
|
61
|
+
- [UPS Server (NUT compatible)](https://github.com/Patrick762/nut-server-bluetti)
|
|
62
|
+
|
|
63
|
+
## Supported Powerstations and data
|
|
64
|
+
|
|
65
|
+
Validated
|
|
66
|
+
|
|
67
|
+
|Device Name|total_battery_percent|dc_input_power|ac_input_power|dc_output_power|ac_output_power|
|
|
68
|
+
|-----------|---------------------|--------------|--------------|---------------|---------------|
|
|
69
|
+
|AC70 |✅ |✅ |✅ |✅ |✅ |
|
|
70
|
+
|AC180 |✅ |✅ |✅ |✅ |✅ |
|
|
71
|
+
|EB3A |✅ |✅ |✅ |✅ |✅ |
|
|
72
|
+
|EP600 |✅ |PV |Grid |❌ |AC Phases |
|
|
73
|
+
|EP2000 |✅ |PV |Grid |❌ |AC Phases, writable grid/mode fields (⚠️ see warning above)|
|
|
74
|
+
|Handsfree 1|✅ |✅ |✅ |✅ |✅ |
|
|
75
|
+
|
|
76
|
+
Added and mostly validated by contributors (some are moved here from the HA Integration https://github.com/Patrick762/hassio-bluetti-bt):
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|Device Name|Contributor |total_battery_percent|dc_input_power|ac_input_power|dc_output_power|ac_output_power|
|
|
80
|
+
|-----------|-----------------------------------------------------------------------------------|---------------------|--------------|--------------|---------------|---------------|
|
|
81
|
+
|AC2A |[@ruanmed](https://github.com/ruanmed) |✅ |✅ |✅ |✅ |✅ |
|
|
82
|
+
|AC50B |[@goetzc](https://github.com/goetzc) |✅ |❌ |✅ |✅ |✅ |
|
|
83
|
+
|AC60 |[@mzpwr](https://github.com/mzpwr) |✅ |✅ |✅ |✅ |✅ |
|
|
84
|
+
|AC60P |[@mzpwr](https://github.com/mzpwr) |✅ |✅ |✅ |✅ |✅ |
|
|
85
|
+
|AC70P |[@matthewpucc](https://github.com/matthewpucc) |✅ |✅ |✅ |✅ |✅ |
|
|
86
|
+
|AC180P |@Patrick762 |✅ |✅ |✅ |✅ |✅ |
|
|
87
|
+
|AC200L |bluetti-mqtt |✅ |✅ |✅ |✅ |✅ |
|
|
88
|
+
|AC200M |bluetti-mqtt |✅ |✅ |✅ |✅ |✅ |
|
|
89
|
+
|AC200PL |[@0x4E4448](https://github.com/0x4E4448) |✅ |✅ |✅ |✅ |✅ |
|
|
90
|
+
|AC300 |bluetti-mqtt |✅ |✅ |✅ |✅ |✅ |
|
|
91
|
+
|AC500 |bluetti-mqtt |✅ |✅ |✅ |✅ |✅ |
|
|
92
|
+
|AP300 |[@seaburger](https://github.com/seaburger), [@sidieje](https://github.com/sidieje) |✅ |✅ |✅ |✅ |✅ |
|
|
93
|
+
|EL30V2 |[@dgudim](https://github.com/dgudim) |✅ |✅ |✅ |✅ |✅ |
|
|
94
|
+
|EL100V2 |[@seaburger](https://github.com/seaburger) |✅ |✅ |✅ |✅ |✅ |
|
|
95
|
+
|EP500 |bluetti-mqtt |✅ |✅ |✅ |✅ |✅ |
|
|
96
|
+
|EP500P |bluetti-mqtt |✅ |✅ |✅ |✅ |✅ |
|
|
97
|
+
|EP760 |[@Apfuntimes](https://github.com/Apfuntimes) |✅ |PV |Grid |❌ |AC Phases |
|
|
98
|
+
|EP800 |[@jhagenk](https://github.com/jhagenk) |✅ |❌ |❌ |❌ |❌ |
|
|
99
|
+
|PR30V2 |@gentoo90 |✅ |✅ |✅ |✅ |✅ |
|
|
100
|
+
|PR100V2 |shares PR30V2 register layout (pending validation) |✅ |✅ |✅ |✅ |✅ |
|
|
101
|
+
|
|
102
|
+
## Controls
|
|
103
|
+
|
|
104
|
+
Validated:
|
|
105
|
+
|
|
106
|
+
|Device Name|ctrl_ac|ctrl_dc|
|
|
107
|
+
|-----------|-------|-------|
|
|
108
|
+
|EB3A |✅ |✅ |
|
|
109
|
+
|
|
110
|
+
Added and mostly validated by contributors:
|
|
111
|
+
|Device Name|Contributor |ctrl_ac|ctrl_dc|ctrl_ups_mode|soc_range_start|soc_range_end|
|
|
112
|
+
|-----------|---------------------------------------------------------|-------|-------|-------------|---------------|-------------|
|
|
113
|
+
|AC200L |bluetti-mqtt, [@seaburger](https://github.com/seaburger) |✅ |✅ |✅ |❌ |❌ |
|
|
114
|
+
|EL30V2 |[@x3ccd4828](https://github.com/x3ccd4828) |✅ |✅ |❌ |❌ |❌ |
|
|
115
|
+
|
|
116
|
+
## Battery pack data
|
|
117
|
+
|
|
118
|
+
|Device Name|voltage|battery_soc|cell_voltages|
|
|
119
|
+
|-----------|-------|-----------|-------------|
|
|
120
|
+
|AC300 |✅ |✅ |✅ |
|
|
121
|
+
|
|
122
|
+
## Installation
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
pip install bluetti-bt-connect-lib
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Commands for testing
|
|
129
|
+
|
|
130
|
+
Commands included in this library should only be used for testing.
|
|
131
|
+
|
|
132
|
+
### Scan for supported devices
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
usage: bluetti-scan [-h] [-r REGEX] [-s SCAN_TIME]
|
|
136
|
+
|
|
137
|
+
Detect bluetti devices by bluetooth name
|
|
138
|
+
|
|
139
|
+
options:
|
|
140
|
+
-h, --help show this help message and exit
|
|
141
|
+
-r REGEX, --regex REGEX
|
|
142
|
+
Custom regex to match device name
|
|
143
|
+
-s SCAN_TIME, --scan-time SCAN_TIME
|
|
144
|
+
How long to scan for devices (seconds)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Example output: `['EB3A', '00:00:00:00:00:00']`
|
|
148
|
+
|
|
149
|
+
### Detect device type by mac address
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
usage: bluetti-detect [-h] mac
|
|
153
|
+
|
|
154
|
+
Detect bluetti devices
|
|
155
|
+
|
|
156
|
+
positional arguments:
|
|
157
|
+
mac Mac-address of the powerstation
|
|
158
|
+
|
|
159
|
+
options:
|
|
160
|
+
-h, --help show this help message and exit
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Example:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
bluetti-detect 00:00:00:00:00:00
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Example output: `Device type is 'EB3A' with iot version 1 and serial 0000000000000. Full name: EB3A0000000000000`
|
|
170
|
+
|
|
171
|
+
### Read device data for supported devices
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
usage: bluetti-read [-h] [-m MAC] [-t TYPE] [-e ENCRYPTION]
|
|
175
|
+
|
|
176
|
+
Detect bluetti devices
|
|
177
|
+
|
|
178
|
+
options:
|
|
179
|
+
-h, --help show this help message and exit
|
|
180
|
+
-m MAC, --mac MAC Mac-address of the powerstation
|
|
181
|
+
-t TYPE, --type TYPE Type of the powerstation (AC70 f.ex.)
|
|
182
|
+
-e ENCRYPTION, --encryption ENCRYPTION
|
|
183
|
+
Add this if encryption is needed
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Example:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
bluetti-read -m 00:00:00:00:00:00 -t EB3A
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Example output:
|
|
193
|
+
```bash
|
|
194
|
+
FieldName.DEVICE_TYPE: EB3A
|
|
195
|
+
FieldName.DEVICE_SN: 0000000000000
|
|
196
|
+
FieldName.BATTERY_SOC: 92%
|
|
197
|
+
FieldName.DC_INPUT_POWER: 0W
|
|
198
|
+
FieldName.AC_INPUT_POWER: 0W
|
|
199
|
+
FieldName.AC_OUTPUT_POWER: 0W
|
|
200
|
+
FieldName.DC_OUTPUT_POWER: 0W
|
|
201
|
+
FieldName.CTRL_AC: False
|
|
202
|
+
FieldName.CTRL_DC: True
|
|
203
|
+
FieldName.CTRL_LED_MODE: LedMode.OFF
|
|
204
|
+
FieldName.CTRL_POWER_OFF: False
|
|
205
|
+
FieldName.CTRL_ECO: False
|
|
206
|
+
FieldName.CTRL_ECO_TIME_MODE: EcoMode.HOURS1
|
|
207
|
+
FieldName.CTRL_CHARGING_MODE: ChargingMode.STANDARD
|
|
208
|
+
FieldName.CTRL_POWER_LIFTING: False
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Write to supported device
|
|
212
|
+
|
|
213
|
+
INFO: Devices with encryption are currently not supported!
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
usage: bluetti-write [-h] [-m MAC] [-t TYPE] [--on ON] [--off OFF] [-v VALUE] [-e ENCRYPTION] field
|
|
217
|
+
|
|
218
|
+
Write to bluetti device
|
|
219
|
+
|
|
220
|
+
positional arguments:
|
|
221
|
+
field Field name (ctrl_dc f.ex.)
|
|
222
|
+
|
|
223
|
+
options:
|
|
224
|
+
-h, --help show this help message and exit
|
|
225
|
+
-m MAC, --mac MAC Mac-address of the powerstation
|
|
226
|
+
-t TYPE, --type TYPE Type of the powerstation (AC70 f.ex.)
|
|
227
|
+
--on ON Value to write
|
|
228
|
+
--off OFF Value to write
|
|
229
|
+
-v VALUE, --value VALUE
|
|
230
|
+
Value to write (integer, see enum for value)
|
|
231
|
+
-e ENCRYPTION, --encryption ENCRYPTION
|
|
232
|
+
Add this if encryption is needed
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Example:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
bluetti-write -m 00:00:00:00:00:00 -t EB3A --on on ctrl_ac
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Adding fields
|
|
242
|
+
|
|
243
|
+
To add new fields, you can use the `bluetti-detect` command to first find out which version of iot protocol is used and if it uses encryption.
|
|
244
|
+
|
|
245
|
+
After you got this information, you can use the `bluetti-readall` command to read every registry and save the data to a json file. You should also note all values you see in the app to later compare the data.
|
|
246
|
+
|
|
247
|
+
Here's how to use the `bluetti-readall` command:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
usage: bluetti-readall [-h] [-m MAC] [-v VERSION] [-e ENCRYPTION]
|
|
251
|
+
|
|
252
|
+
Detect bluetti devices
|
|
253
|
+
|
|
254
|
+
options:
|
|
255
|
+
-h, --help show this help message and exit
|
|
256
|
+
-m MAC, --mac MAC Mac-address of the powerstation
|
|
257
|
+
-v VERSION, --version VERSION
|
|
258
|
+
IoT protocol version
|
|
259
|
+
-e ENCRYPTION, --encryption ENCRYPTION
|
|
260
|
+
Add this if encryption is needed
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
With the separate tool at [bluetti-bt-raw-reader](https://github.com/Patrick762/bluetti-bt-raw-reader) you can view those values in a more understandable way.
|
|
264
|
+
|
|
265
|
+
You can also share the output with me using [this form](https://forms.gle/ewp7DYigtaN3ZLc68)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
To test added fields with the created json file, use `bluetti-parse`:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
usage: bluetti-parse [-h] file
|
|
272
|
+
|
|
273
|
+
Parse readall output files
|
|
274
|
+
|
|
275
|
+
positional arguments:
|
|
276
|
+
file JSON file of the powerstation readall output
|
|
277
|
+
|
|
278
|
+
options:
|
|
279
|
+
-h, --help show this help message and exit
|
|
280
|
+
```
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# bluetti-bt-connect-lib
|
|
2
|
+
|
|
3
|
+
> **This is a fork** of [bluetti-bt-lib](https://github.com/Patrick762/bluetti-bt-lib) by [Patrick762](https://github.com/Patrick762), extended with additional device support, register corrections, and new writable fields for the Bluetti EP2000. All credit for the original protocol reverse-engineering, architecture, and core library design goes to Patrick762 and the project's other contributors. This fork exists to track device-specific fixes and additions on a faster iteration cycle; where possible, improvements are intended to be contributed back upstream.
|
|
4
|
+
>
|
|
5
|
+
> Original repository: https://github.com/Patrick762/bluetti-bt-lib
|
|
6
|
+
>
|
|
7
|
+
> Additional credit to [atiweb/hassio-bluetti-bt](https://github.com/atiweb/hassio-bluetti-bt), a separate fork of the original project, cross-referenced for two specific fixes: correcting `consumption_power_all`, `pv_input_power_all`, and `grid_power_all` from incorrectly-assumed 32-bit fields to plain 16-bit fields (validated against real captured data), and the pattern for proper Modbus response validation (CRC checking and exception-response detection) now used in `device_reader.py`.
|
|
8
|
+
|
|
9
|
+
Inofficial Library for basic communication to bluetti powerstations.
|
|
10
|
+
Core functions based on https://github.com/warhammerkid/bluetti_mqtt
|
|
11
|
+
|
|
12
|
+
## Disclaimer
|
|
13
|
+
This library is provided without any warranty or support by Bluetti. I do not take responsibility for any problems it may cause in all cases. Use it at your own risk.
|
|
14
|
+
|
|
15
|
+
## ⚠️ EP2000: grid/mode controls carry real risk - read before using
|
|
16
|
+
|
|
17
|
+
**AC Output, Charge From Grid, Grid Export, Working Mode, and all four grid import/export power and current limits remain writable in this build.** Before you rely on any of them, please understand what we found while investigating this device.
|
|
18
|
+
|
|
19
|
+
**The core problem:** writes into this device's grid-related register block can get a clean, protocol-valid acknowledgment from the device - and then the change does not actually take effect. This was confirmed at the raw byte level, ruling out a simple wrong-address or scaling issue. In practice this means: **you may set a limit in Home Assistant, see it accepted with no error, and the device may still be running on its old setting.** Nothing in the app or the integration will reliably tell you a write didn't stick - the failure is silent. Do not assume a control has taken effect on the device just because Home Assistant shows no error; if you change one of these settings, verify the result independently (in the Bluetti app, or against real grid behavior) before relying on it.
|
|
20
|
+
|
|
21
|
+
**Why we believe this happens:** a research pass across comparable BLE-connected solar/battery projects (EcoFlow, Renogy, Growatt, Deye/Sunsynk, Anker SOLIX, Marstek, several open-source BMS forks) found that grid-facing settings - export/import limits, working mode, grid protection - are consistently gated behind some form of vendor authentication across the entire industry, not just on Bluetti hardware: a cloud-account round-trip, a licensed BLE encryption handshake keyed to the device's serial number, or a support-issued password. The EP2000 fits this pattern - there's a genuine "Pro Mode" authentication layer here, and while we confirmed the universal technician password Bluetti documents publicly ("88888888"), simply knowing that password did not make writes persist, which points at a session or encryption-level gate underneath it that hasn't been reverse-engineered.
|
|
22
|
+
|
|
23
|
+
**Why we haven't removed these controls outright:** unlike the grid-compliance layer itself, some of these fields (notably the AC Output and Grid Export switches, and Max Grid Export Current) were live-tested and confirmed to actually take effect on this specific unit at various points during development. Reliability may vary by field, by firmware version, and possibly by unit - which is exactly why blanket trust in any of them is the wrong approach. Treat every write as unverified until you've checked its real-world effect yourself.
|
|
24
|
+
|
|
25
|
+
**Grid export and grid-protection parameters are regulated for interconnection safety in most jurisdictions** (anti-islanding, voltage/frequency ride-through). Changing them, even successfully, may have real compliance implications depending on where you live and how your system is set up. This is worth knowing regardless of whether a given write actually persists.
|
|
26
|
+
|
|
27
|
+
**If you're an advanced user or researcher**: the full research writeup and the exact register-level evidence behind the above are referenced in this version's release notes. The realistic next step for confirming or defeating the authentication gate isn't more register-guessing - it's capturing the official app's authenticated write sequence directly (Android Bluetooth HCI snoop log, or hooking the app's write call with Frida).
|
|
28
|
+
|
|
29
|
+
## Projects using this library
|
|
30
|
+
|
|
31
|
+
- [Bluetti BT Connect - Home Assistant Integration](https://github.com/Elliottmonaghan/bluetti-bt-connect) (this fork's companion integration)
|
|
32
|
+
- [Original Home Assistant Integration](https://github.com/Patrick762/hassio-bluetti-bt)
|
|
33
|
+
- [UPS Server (NUT compatible)](https://github.com/Patrick762/nut-server-bluetti)
|
|
34
|
+
|
|
35
|
+
## Supported Powerstations and data
|
|
36
|
+
|
|
37
|
+
Validated
|
|
38
|
+
|
|
39
|
+
|Device Name|total_battery_percent|dc_input_power|ac_input_power|dc_output_power|ac_output_power|
|
|
40
|
+
|-----------|---------------------|--------------|--------------|---------------|---------------|
|
|
41
|
+
|AC70 |✅ |✅ |✅ |✅ |✅ |
|
|
42
|
+
|AC180 |✅ |✅ |✅ |✅ |✅ |
|
|
43
|
+
|EB3A |✅ |✅ |✅ |✅ |✅ |
|
|
44
|
+
|EP600 |✅ |PV |Grid |❌ |AC Phases |
|
|
45
|
+
|EP2000 |✅ |PV |Grid |❌ |AC Phases, writable grid/mode fields (⚠️ see warning above)|
|
|
46
|
+
|Handsfree 1|✅ |✅ |✅ |✅ |✅ |
|
|
47
|
+
|
|
48
|
+
Added and mostly validated by contributors (some are moved here from the HA Integration https://github.com/Patrick762/hassio-bluetti-bt):
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|Device Name|Contributor |total_battery_percent|dc_input_power|ac_input_power|dc_output_power|ac_output_power|
|
|
52
|
+
|-----------|-----------------------------------------------------------------------------------|---------------------|--------------|--------------|---------------|---------------|
|
|
53
|
+
|AC2A |[@ruanmed](https://github.com/ruanmed) |✅ |✅ |✅ |✅ |✅ |
|
|
54
|
+
|AC50B |[@goetzc](https://github.com/goetzc) |✅ |❌ |✅ |✅ |✅ |
|
|
55
|
+
|AC60 |[@mzpwr](https://github.com/mzpwr) |✅ |✅ |✅ |✅ |✅ |
|
|
56
|
+
|AC60P |[@mzpwr](https://github.com/mzpwr) |✅ |✅ |✅ |✅ |✅ |
|
|
57
|
+
|AC70P |[@matthewpucc](https://github.com/matthewpucc) |✅ |✅ |✅ |✅ |✅ |
|
|
58
|
+
|AC180P |@Patrick762 |✅ |✅ |✅ |✅ |✅ |
|
|
59
|
+
|AC200L |bluetti-mqtt |✅ |✅ |✅ |✅ |✅ |
|
|
60
|
+
|AC200M |bluetti-mqtt |✅ |✅ |✅ |✅ |✅ |
|
|
61
|
+
|AC200PL |[@0x4E4448](https://github.com/0x4E4448) |✅ |✅ |✅ |✅ |✅ |
|
|
62
|
+
|AC300 |bluetti-mqtt |✅ |✅ |✅ |✅ |✅ |
|
|
63
|
+
|AC500 |bluetti-mqtt |✅ |✅ |✅ |✅ |✅ |
|
|
64
|
+
|AP300 |[@seaburger](https://github.com/seaburger), [@sidieje](https://github.com/sidieje) |✅ |✅ |✅ |✅ |✅ |
|
|
65
|
+
|EL30V2 |[@dgudim](https://github.com/dgudim) |✅ |✅ |✅ |✅ |✅ |
|
|
66
|
+
|EL100V2 |[@seaburger](https://github.com/seaburger) |✅ |✅ |✅ |✅ |✅ |
|
|
67
|
+
|EP500 |bluetti-mqtt |✅ |✅ |✅ |✅ |✅ |
|
|
68
|
+
|EP500P |bluetti-mqtt |✅ |✅ |✅ |✅ |✅ |
|
|
69
|
+
|EP760 |[@Apfuntimes](https://github.com/Apfuntimes) |✅ |PV |Grid |❌ |AC Phases |
|
|
70
|
+
|EP800 |[@jhagenk](https://github.com/jhagenk) |✅ |❌ |❌ |❌ |❌ |
|
|
71
|
+
|PR30V2 |@gentoo90 |✅ |✅ |✅ |✅ |✅ |
|
|
72
|
+
|PR100V2 |shares PR30V2 register layout (pending validation) |✅ |✅ |✅ |✅ |✅ |
|
|
73
|
+
|
|
74
|
+
## Controls
|
|
75
|
+
|
|
76
|
+
Validated:
|
|
77
|
+
|
|
78
|
+
|Device Name|ctrl_ac|ctrl_dc|
|
|
79
|
+
|-----------|-------|-------|
|
|
80
|
+
|EB3A |✅ |✅ |
|
|
81
|
+
|
|
82
|
+
Added and mostly validated by contributors:
|
|
83
|
+
|Device Name|Contributor |ctrl_ac|ctrl_dc|ctrl_ups_mode|soc_range_start|soc_range_end|
|
|
84
|
+
|-----------|---------------------------------------------------------|-------|-------|-------------|---------------|-------------|
|
|
85
|
+
|AC200L |bluetti-mqtt, [@seaburger](https://github.com/seaburger) |✅ |✅ |✅ |❌ |❌ |
|
|
86
|
+
|EL30V2 |[@x3ccd4828](https://github.com/x3ccd4828) |✅ |✅ |❌ |❌ |❌ |
|
|
87
|
+
|
|
88
|
+
## Battery pack data
|
|
89
|
+
|
|
90
|
+
|Device Name|voltage|battery_soc|cell_voltages|
|
|
91
|
+
|-----------|-------|-----------|-------------|
|
|
92
|
+
|AC300 |✅ |✅ |✅ |
|
|
93
|
+
|
|
94
|
+
## Installation
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pip install bluetti-bt-connect-lib
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Commands for testing
|
|
101
|
+
|
|
102
|
+
Commands included in this library should only be used for testing.
|
|
103
|
+
|
|
104
|
+
### Scan for supported devices
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
usage: bluetti-scan [-h] [-r REGEX] [-s SCAN_TIME]
|
|
108
|
+
|
|
109
|
+
Detect bluetti devices by bluetooth name
|
|
110
|
+
|
|
111
|
+
options:
|
|
112
|
+
-h, --help show this help message and exit
|
|
113
|
+
-r REGEX, --regex REGEX
|
|
114
|
+
Custom regex to match device name
|
|
115
|
+
-s SCAN_TIME, --scan-time SCAN_TIME
|
|
116
|
+
How long to scan for devices (seconds)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Example output: `['EB3A', '00:00:00:00:00:00']`
|
|
120
|
+
|
|
121
|
+
### Detect device type by mac address
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
usage: bluetti-detect [-h] mac
|
|
125
|
+
|
|
126
|
+
Detect bluetti devices
|
|
127
|
+
|
|
128
|
+
positional arguments:
|
|
129
|
+
mac Mac-address of the powerstation
|
|
130
|
+
|
|
131
|
+
options:
|
|
132
|
+
-h, --help show this help message and exit
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Example:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
bluetti-detect 00:00:00:00:00:00
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Example output: `Device type is 'EB3A' with iot version 1 and serial 0000000000000. Full name: EB3A0000000000000`
|
|
142
|
+
|
|
143
|
+
### Read device data for supported devices
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
usage: bluetti-read [-h] [-m MAC] [-t TYPE] [-e ENCRYPTION]
|
|
147
|
+
|
|
148
|
+
Detect bluetti devices
|
|
149
|
+
|
|
150
|
+
options:
|
|
151
|
+
-h, --help show this help message and exit
|
|
152
|
+
-m MAC, --mac MAC Mac-address of the powerstation
|
|
153
|
+
-t TYPE, --type TYPE Type of the powerstation (AC70 f.ex.)
|
|
154
|
+
-e ENCRYPTION, --encryption ENCRYPTION
|
|
155
|
+
Add this if encryption is needed
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Example:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
bluetti-read -m 00:00:00:00:00:00 -t EB3A
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Example output:
|
|
165
|
+
```bash
|
|
166
|
+
FieldName.DEVICE_TYPE: EB3A
|
|
167
|
+
FieldName.DEVICE_SN: 0000000000000
|
|
168
|
+
FieldName.BATTERY_SOC: 92%
|
|
169
|
+
FieldName.DC_INPUT_POWER: 0W
|
|
170
|
+
FieldName.AC_INPUT_POWER: 0W
|
|
171
|
+
FieldName.AC_OUTPUT_POWER: 0W
|
|
172
|
+
FieldName.DC_OUTPUT_POWER: 0W
|
|
173
|
+
FieldName.CTRL_AC: False
|
|
174
|
+
FieldName.CTRL_DC: True
|
|
175
|
+
FieldName.CTRL_LED_MODE: LedMode.OFF
|
|
176
|
+
FieldName.CTRL_POWER_OFF: False
|
|
177
|
+
FieldName.CTRL_ECO: False
|
|
178
|
+
FieldName.CTRL_ECO_TIME_MODE: EcoMode.HOURS1
|
|
179
|
+
FieldName.CTRL_CHARGING_MODE: ChargingMode.STANDARD
|
|
180
|
+
FieldName.CTRL_POWER_LIFTING: False
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Write to supported device
|
|
184
|
+
|
|
185
|
+
INFO: Devices with encryption are currently not supported!
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
usage: bluetti-write [-h] [-m MAC] [-t TYPE] [--on ON] [--off OFF] [-v VALUE] [-e ENCRYPTION] field
|
|
189
|
+
|
|
190
|
+
Write to bluetti device
|
|
191
|
+
|
|
192
|
+
positional arguments:
|
|
193
|
+
field Field name (ctrl_dc f.ex.)
|
|
194
|
+
|
|
195
|
+
options:
|
|
196
|
+
-h, --help show this help message and exit
|
|
197
|
+
-m MAC, --mac MAC Mac-address of the powerstation
|
|
198
|
+
-t TYPE, --type TYPE Type of the powerstation (AC70 f.ex.)
|
|
199
|
+
--on ON Value to write
|
|
200
|
+
--off OFF Value to write
|
|
201
|
+
-v VALUE, --value VALUE
|
|
202
|
+
Value to write (integer, see enum for value)
|
|
203
|
+
-e ENCRYPTION, --encryption ENCRYPTION
|
|
204
|
+
Add this if encryption is needed
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Example:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
bluetti-write -m 00:00:00:00:00:00 -t EB3A --on on ctrl_ac
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Adding fields
|
|
214
|
+
|
|
215
|
+
To add new fields, you can use the `bluetti-detect` command to first find out which version of iot protocol is used and if it uses encryption.
|
|
216
|
+
|
|
217
|
+
After you got this information, you can use the `bluetti-readall` command to read every registry and save the data to a json file. You should also note all values you see in the app to later compare the data.
|
|
218
|
+
|
|
219
|
+
Here's how to use the `bluetti-readall` command:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
usage: bluetti-readall [-h] [-m MAC] [-v VERSION] [-e ENCRYPTION]
|
|
223
|
+
|
|
224
|
+
Detect bluetti devices
|
|
225
|
+
|
|
226
|
+
options:
|
|
227
|
+
-h, --help show this help message and exit
|
|
228
|
+
-m MAC, --mac MAC Mac-address of the powerstation
|
|
229
|
+
-v VERSION, --version VERSION
|
|
230
|
+
IoT protocol version
|
|
231
|
+
-e ENCRYPTION, --encryption ENCRYPTION
|
|
232
|
+
Add this if encryption is needed
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
With the separate tool at [bluetti-bt-raw-reader](https://github.com/Patrick762/bluetti-bt-raw-reader) you can view those values in a more understandable way.
|
|
236
|
+
|
|
237
|
+
You can also share the output with me using [this form](https://forms.gle/ewp7DYigtaN3ZLc68)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
To test added fields with the created json file, use `bluetti-parse`:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
usage: bluetti-parse [-h] file
|
|
244
|
+
|
|
245
|
+
Parse readall output files
|
|
246
|
+
|
|
247
|
+
positional arguments:
|
|
248
|
+
file JSON file of the powerstation readall output
|
|
249
|
+
|
|
250
|
+
options:
|
|
251
|
+
-h, --help show this help message and exit
|
|
252
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Bluetti BT Lib exports."""
|
|
2
|
+
|
|
3
|
+
__version__ = "1.5.0"
|
|
4
|
+
"""Single source of truth for the package version.
|
|
5
|
+
|
|
6
|
+
setup.py reads this when LIB_VERSION is not set, so an install straight from
|
|
7
|
+
git reports a real version rather than falling back to 0.0.0. The release
|
|
8
|
+
workflow checks the git tag against it and refuses to publish on a mismatch.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from .base_devices import BluettiDevice
|
|
12
|
+
from .bluetooth import (
|
|
13
|
+
DeviceReader,
|
|
14
|
+
DeviceReaderConfig,
|
|
15
|
+
DeviceWriter,
|
|
16
|
+
DeviceRecognizerResult,
|
|
17
|
+
recognize_device,
|
|
18
|
+
)
|
|
19
|
+
from .enums import *
|
|
20
|
+
from .fields import DeviceField, FieldName, FieldUnit, get_unit
|
|
21
|
+
from .utils.device_builder import build_device
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from . import BluettiDevice
|
|
4
|
+
from ..fields import DeviceField
|
|
5
|
+
from ..fields import FieldName, StringField, UIntField, SerialNumberField
|
|
6
|
+
from ..registers import ReadableRegisters, WriteableRegister
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BaseDeviceV1(BluettiDevice):
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
additional_fields: List[DeviceField] = [],
|
|
13
|
+
pack_fields: List[DeviceField] = [],
|
|
14
|
+
max_packs: int = 0,
|
|
15
|
+
**kwargs,
|
|
16
|
+
):
|
|
17
|
+
super().__init__(
|
|
18
|
+
[
|
|
19
|
+
StringField(FieldName.DEVICE_TYPE, 10, 6),
|
|
20
|
+
SerialNumberField(FieldName.DEVICE_SN, 17),
|
|
21
|
+
UIntField(FieldName.BATTERY_SOC, 43, min=0, max=100),
|
|
22
|
+
UIntField(FieldName.DC_INPUT_POWER, 36),
|
|
23
|
+
UIntField(FieldName.AC_INPUT_POWER, 37),
|
|
24
|
+
UIntField(FieldName.AC_OUTPUT_POWER, 38),
|
|
25
|
+
UIntField(FieldName.DC_OUTPUT_POWER, 39),
|
|
26
|
+
]
|
|
27
|
+
+ additional_fields,
|
|
28
|
+
pack_fields,
|
|
29
|
+
max_packs,
|
|
30
|
+
**kwargs,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
def get_full_registers_range(self) -> List[ReadableRegisters]:
|
|
34
|
+
return [ReadableRegisters(i, 10) for i in range(1, 8000, 10)]
|
|
35
|
+
|
|
36
|
+
def get_device_type_registers(self) -> List[ReadableRegisters]:
|
|
37
|
+
return [
|
|
38
|
+
ReadableRegisters(10, 6),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
def get_device_sn_registers(self) -> List[ReadableRegisters]:
|
|
42
|
+
return [
|
|
43
|
+
ReadableRegisters(17, 4),
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
def get_iot_version(self) -> int:
|
|
47
|
+
return 1
|
|
48
|
+
|
|
49
|
+
def get_pack_selector(self, pack: int) -> WriteableRegister:
|
|
50
|
+
return WriteableRegister(3006, pack)
|