From 129b3b15b34a65cb1646577d673520d6c4e6621a Mon Sep 17 00:00:00 2001 From: b2un0 Date: Tue, 3 Dec 2024 14:15:04 +0100 Subject: [PATCH] fix ble password arg not used add container image add container run example add missing MIT LICENSE file add example to determine the ble address --- .github/workflows/container.yml | 51 +++++++ .gitignore | 1 + Dockerfile | 19 +++ LICENSE | 19 +++ readme.md => README.md | 260 ++++++++++++++++++-------------- evseMQTT/requirements.txt | 2 - main.py | 6 +- requirements.txt | 2 + 8 files changed, 244 insertions(+), 116 deletions(-) create mode 100644 .github/workflows/container.yml create mode 100644 Dockerfile create mode 100644 LICENSE rename readme.md => README.md (81%) delete mode 100644 evseMQTT/requirements.txt create mode 100644 requirements.txt diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml new file mode 100644 index 0000000..73c2d31 --- /dev/null +++ b/.github/workflows/container.yml @@ -0,0 +1,51 @@ +name: 'container' + +on: + push: + workflow_dispatch: + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + with: + # images: ${{ vars.DOCKER_USERNAME }}/${{ vars.DOCKER_IMAGE }},ghcr.io/${{ github.repository }} + images: ghcr.io/${{ github.repository }} + tags: | + type=raw,value=latest,enable={{is_default_branch}} + + # - name: Login to DockerHub + # uses: docker/login-action@v2 + # with: + # username: ${{ vars.DOCKER_USERNAME }} + # password: ${{ secrets.DOCKER_TOKEN }} + + - name: Login to ghcr.io + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Build and push + uses: docker/build-push-action@v4 + with: + context: . + # platforms: linux/amd64,linux/arm64 + platforms: linux/amd64 + push: true + provenance: false + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index efa8aae..5a76dc7 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ venv/ ENV/ env.bak/ venv.bak/ +.env # Installed packages *.egg-info/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..34423eb --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3-alpine + +RUN apk add bluez + +ENV BLE_ADDRESS="" \ + BLE_PASSWORD="" \ + MQTT_BROKER="" \ + MQTT_PORT="1883" \ + MQTT_USERNAME="" \ + MQTT_PASSWORD="" \ + LOGGING_LEVEL="INFO" + +ADD . /app + +WORKDIR /app + +RUN pip install -r requirements.txt + +CMD ["sh", "-c", "python main.py --address ${BLE_ADDRESS} --password ${BLE_PASSWORD} --mqtt --mqtt_broker ${MQTT_BROKER} --mqtt_port ${MQTT_PORT} --mqtt_user ${MQTT_USERNAME} --mqtt_password ${MQTT_PASSWORD} --logging_level ${LOGGING_LEVEL}"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0bf6001 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. \ No newline at end of file diff --git a/readme.md b/README.md similarity index 81% rename from readme.md rename to README.md index e5ae279..e211684 100644 --- a/readme.md +++ b/README.md @@ -1,112 +1,150 @@ -# evseMQTT -`evseMQTT` is a Python library designed for communicating with EVSE-based Electric Vehicle Charging Wallboxes using Bluetooth Low Energy (BLE), and exposing its data and controls to Home Assistant using MQTT Discovery. Due to potential security concerns of WiFi connectivity, this library facilitates a local, no cloud connection to your EVSE device. It has been tested on the Besen BS20 model using a Raspberry Pi Zero 2 W. - -The code base is by no means perfect or especially beautiful -- pragmatic hacks are applied where needed. -![Home Assistant Device view](https://raw.githubusercontent.com/slespersen/evseMQTT/refs/heads/main/evseMQTT_home_assistant.png) -## Features - -`evseMQTT` provides the following functionalities: - -- **Start/Stop Charging:** Control the charging process. -- **Set Maximum Amps:** Define the maximum amperage for a charging session. -- **Change Language:** Modify the language setting (note: this affects the smartphone app rather than the wallbox itself). -- **Device Name:** Set or change the name of the device. -- **Temperature Unit:** Set the preferred unit of temperature. -- **Phase detection**: Available phases are automatically identified. -- **Max amp detection**: Maximum amperage output is automatically detected. -- **Automatic Reconnect**: In case the Bluetooth connection is stale, and no message has been received for more than 35 seconds, the script will automatically reinitialize. - -Additionally, `evseMQTT` allows you to read: -- **Current Consumption of Energy:** Monitor the energy consumption in kilowatt-hours (kWh). -- **Errors**: Monitor potential errors. -- **Phase characteristics**: Monitor voltage and amperage across the phases present on the charger. -- **Messages**: Monitor messages defined by the state of both the plug, the output and the status. -- **Total Consumption**: Monitor the total energy consumption (since last reset) in kilowatt-hours (kWh). -- **Temperature**: Monitor the current temperature. -- **Date & Time**: Get the devices current date and time. - -## Home Assistant Integration - -`evseMQTT` exposes basic control functionalities to Home Assistant via MQTT Discovery, enabling seamless integration and control within your home automation setup. - -## Upcoming features - -The following functions are in the making: - -- **Automatic Temperature Unit Update**: Automatically updating of the enabled and disabled temperature unit sensor in Home Assistant to not pollute the different statistics. -- **Additional Status Messages**: Additional messages for both charge_start and charge_stop. - -## Installation - -Since `evseMQTT` is not yet available on pip, it needs to be installed manually. Follow these steps: - -1. Clone the repository: - ```bash - git clone https://github.com/slespersen/evseMQTT.git - ``` - -2. Create a symbolic link to your Python library directory: - ```bash - ln -s /path/to/evseMQTT /path/to/your/python/lib - ``` - -## Usage - -`main.py` is provided for running the library. Below are the arguments it accepts: - -### Arguments - -- `--address`: (Required) The BLE device address. -- `--password`: (Optional) The BLE device password. Default is "123456". -- `--mqtt`: (Optional) Enable MQTT. -- `--mqtt_broker`: (Optional) The MQTT broker address. -- `--mqtt_port`: (Optional) The MQTT broker port. -- `--mqtt_user`: (Optional) The MQTT username. -- `--mqtt_password`: (Optional) The MQTT password. -- `--logging_level`: (Optional) The logging level. Default is "INFO". - -### Example Command - -Here's an example of how to run `main.py` with the necessary arguments: - -```bash -python main.py --address "your_device_address" --mqtt --mqtt_broker "your_mqtt_broker_address" --mqtt_port 1883 --mqtt_user "your_mqtt_username" --mqtt_password "your_mqtt_password" --logging_level "DEBUG" - -``` - -## Caveats -This library is in no means complete, when compared to the original app - some features missing: -- Charging History -- LCD Brightness -- Password Reset -- Device Reset -- WiFi setup - -Seemingly unexpected behavior, but working as intended: -- When changing the device name, the device will disconnect and the script will wait for 35 seconds, since the last received message, before reconnecting. - -## Acknowledgements - -A big thank you to the following contributors: - -- [bakkers](https://github.com/bakkers) for documenting findings: https://gist.github.com/bakkerrs/cb75e3c3a337f8f38a3f84f4b49beaa5 - -- [johnwoo-nl](https://github.com/johnwoo-nl) for building emproto: https://github.com/johnwoo-nl/emproto/tree/main?tab=readme-ov-file - -- [Phil242](https://github.com/Phil242), [FlorentVTT](https://github.com/FlorentVTT), and [DutchDevelop](https://github.com/DutchDevelop) for their original efforts in decoding the EVSE protocol - -## Tested Devices - -- **Besen BS20:** This library has been tested and verified to work with the Besen BS20 Electric Vehicle Charging Wallbox. - -## License - -This project is licensed under the MIT License. - -## Contributing - -Contributions are welcome! Please feel free to submit a pull request or open an issue. - -## Support - +# evseMQTT +`evseMQTT` is a Python library designed for communicating with EVSE-based Electric Vehicle Charging Wallboxes using Bluetooth Low Energy (BLE), and exposing its data and controls to Home Assistant using MQTT Discovery. Due to potential security concerns of WiFi connectivity, this library facilitates a local, no cloud connection to your EVSE device. It has been tested on the Besen BS20 model using a Raspberry Pi Zero 2 W. + +The code base is by no means perfect or especially beautiful -- pragmatic hacks are applied where needed. +![Home Assistant Device view](https://raw.githubusercontent.com/slespersen/evseMQTT/refs/heads/main/evseMQTT_home_assistant.png) +## Features + +`evseMQTT` provides the following functionalities: + +- **Start/Stop Charging:** Control the charging process. +- **Set Maximum Amps:** Define the maximum amperage for a charging session. +- **Change Language:** Modify the language setting (note: this affects the smartphone app rather than the wallbox itself). +- **Device Name:** Set or change the name of the device. +- **Temperature Unit:** Set the preferred unit of temperature. +- **Phase detection**: Available phases are automatically identified. +- **Max amp detection**: Maximum amperage output is automatically detected. +- **Automatic Reconnect**: In case the Bluetooth connection is stale, and no message has been received for more than 35 seconds, the script will automatically reinitialize. + +Additionally, `evseMQTT` allows you to read: +- **Current Consumption of Energy:** Monitor the energy consumption in kilowatt-hours (kWh). +- **Errors**: Monitor potential errors. +- **Phase characteristics**: Monitor voltage and amperage across the phases present on the charger. +- **Messages**: Monitor messages defined by the state of both the plug, the output and the status. +- **Total Consumption**: Monitor the total energy consumption (since last reset) in kilowatt-hours (kWh). +- **Temperature**: Monitor the current temperature. +- **Date & Time**: Get the devices current date and time. + +## Home Assistant Integration + +`evseMQTT` exposes basic control functionalities to Home Assistant via MQTT Discovery, enabling seamless integration and control within your home automation setup. + +## Upcoming features + +The following functions are in the making: + +- **Automatic Temperature Unit Update**: Automatically updating of the enabled and disabled temperature unit sensor in Home Assistant to not pollute the different statistics. +- **Additional Status Messages**: Additional messages for both charge_start and charge_stop. + +## Installation + +Since `evseMQTT` is not yet available on pip, it needs to be installed manually. Follow these steps: + +1. Clone the repository: + ```bash + git clone https://github.com/slespersen/evseMQTT.git + ``` + +2. Create a symbolic link to your Python library directory: + ```bash + ln -s /path/to/evseMQTT /path/to/your/python/lib + ``` + +## Usage + +`main.py` is provided for running the library. Below are the arguments it accepts: + +### Arguments + +- `--address`: (Required) The BLE device address. +- `--password`: (Optional) The BLE device password. Default is "123456". +- `--mqtt`: (Optional) Enable MQTT. +- `--mqtt_broker`: (Optional) The MQTT broker address. +- `--mqtt_port`: (Optional) The MQTT broker port. +- `--mqtt_user`: (Optional) The MQTT username. +- `--mqtt_password`: (Optional) The MQTT password. +- `--logging_level`: (Optional) The logging level. Default is "INFO". + +### Example Command + +Here's an example of how to run `main.py` with the necessary arguments: + +```bash +python main.py --address "your_device_mac_address" \ + --password "your_6_digit_pin" \ + --mqtt \ + --mqtt_broker "your_mqtt_broker_address" \ + --mqtt_port 1883 \ + --mqtt_user "your_mqtt_username" \ + --mqtt_password "your_mqtt_password" \ + --logging_level "DEBUG" +``` + +### run as container + +```bash + +docker run -d --name evseMQTT \ + --restart always \ + -v /var/run/dbus:/run/dbus \ + -e BLE_ADDRESS="your_device_mac_address" \ + -e BLE_PASSWORD="your_6_digit_pin" \ + -e MQTT_BROKER="your_mqtt_broker_address" \ + -e MQTT_PORT=1883 \ + -e MQTT_USER="your_mqtt_username" \ + -e MQTT_PASSWORD="your_mqtt_password" \ + -e LOGGING_LEVEL="INFO" \ + ghcr.io/slespersen/evsemqtt:latest +``` + +### determine BLE address for your EVSE + +look for a mac address started with `ACP#` like this: + +```bash +bluetoothctl scan le +``` + +results in something like this: +```plain +Discovery started +[CHG] Controller B8:27:EB:B4:51:EB Discovering: yes +[NEW] Device 12:34:56:78:99:00 ACP#NamedEVSE +``` + +## Caveats +This library is in no means complete, when compared to the original app - some features missing: +- Charging History +- LCD Brightness +- Password Reset +- Device Reset +- WiFi setup + +Seemingly unexpected behavior, but working as intended: +- When changing the device name, the device will disconnect and the script will wait for 35 seconds, since the last received message, before reconnecting. + +## Acknowledgements + +A big thank you to the following contributors: + +- [bakkers](https://github.com/bakkers) for documenting findings: https://gist.github.com/bakkerrs/cb75e3c3a337f8f38a3f84f4b49beaa5 + +- [johnwoo-nl](https://github.com/johnwoo-nl) for building emproto: https://github.com/johnwoo-nl/emproto/tree/main?tab=readme-ov-file + +- [Phil242](https://github.com/Phil242), [FlorentVTT](https://github.com/FlorentVTT), and [DutchDevelop](https://github.com/DutchDevelop) for their original efforts in decoding the EVSE protocol + +## Tested Devices + +- **Besen BS20:** This library has been tested and verified to work with the Besen BS20 Electric Vehicle Charging Wallbox. + +## License + +This project is licensed under the MIT License. + +## Contributing + +Contributions are welcome! Please feel free to submit a pull request or open an issue. + +## Support + For any questions or issues, please open an issue. \ No newline at end of file diff --git a/evseMQTT/requirements.txt b/evseMQTT/requirements.txt deleted file mode 100644 index 74fa409..0000000 --- a/evseMQTT/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -bleak==0.20.2 -paho-mqtt==1.6.1 \ No newline at end of file diff --git a/main.py b/main.py index 3f81a00..6fad2e7 100644 --- a/main.py +++ b/main.py @@ -4,7 +4,7 @@ from evseMQTT import BLEManager, Constants, Device, EventHandlers, Commands, Logger, MQTTClient, MQTTCallback, MQTTPayloads, Utils class Manager: - def __init__(self, address, ble_password="123456", mqtt_enabled=False, mqtt_settings=None, logging_level=logging.INFO): + def __init__(self, address, ble_password, mqtt_enabled=False, mqtt_settings=None, logging_level=logging.INFO): self.setup_logging(logging_level) self.logger = logging.getLogger("evseMQTT") debug = logging_level == logging.DEBUG # Determine if debug logging is enabled @@ -114,7 +114,7 @@ async def restart_run(self, address = None): if __name__ == "__main__": parser = argparse.ArgumentParser(description="BLE Manager") parser.add_argument("--address", type=str, required=True, help="BLE device address") - parser.add_argument("--password", type=str, help="BLE device password") + parser.add_argument("--password", type=str, required=True, help="BLE device password") parser.add_argument("--mqtt", action='store_true', help="Enable MQTT") parser.add_argument("--mqtt_broker", type=str, help="MQTT broker address") parser.add_argument("--mqtt_port", type=int, help="MQTT broker port") @@ -133,5 +133,5 @@ async def restart_run(self, address = None): logging_level = getattr(logging, args.logging_level.upper(), logging.INFO) - manager = Manager(args.address, mqtt_enabled=args.mqtt, mqtt_settings=mqtt_settings, logging_level=logging_level) + manager = Manager(args.address, ble_password=args.password, mqtt_enabled=args.mqtt, mqtt_settings=mqtt_settings, logging_level=logging_level) asyncio.run(manager.run(args.address)) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d32ff1e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +bleak==0.20.2 +paho-mqtt==1.6.1