diff --git a/.github/ISSUE_TEMPLATE/new_device_request.disabled b/.github/ISSUE_TEMPLATE/new_device_request.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/new_device_request.disabled rename to .github/ISSUE_TEMPLATE/new_device_request.yml diff --git a/.github/scripts/library_doc/generate_file.py b/.github/scripts/library_doc/generate_file.py new file mode 100644 index 000000000..7984ba08a --- /dev/null +++ b/.github/scripts/library_doc/generate_file.py @@ -0,0 +1,55 @@ +"""Battery library document generator.""" + +from __future__ import annotations + +import json + +from pytablewriter import MarkdownTableWriter + + +def generate_device_list(): + """Generate static file containing the device library.""" + + # Load the existing JSON library file + with open("custom_components/battery_notes/data/library.json", + encoding="UTF-8") as f: + devices_json = json.loads(f.read()) + devices = devices_json.get("devices") + + toc_links: list[str] = [] + tables_output: str = "" + rows = [] + + num_devices = len(devices) + + writer = MarkdownTableWriter() + headers = [ + "Manufacturer", + "Model", + "Battery Type", + ] + + writer.header_list = headers + + for device in devices: + if device.get("battery_quantity", 1) > 1: + battery_type_qty = f"{device['battery_quantity']}x {device['battery_type']}" + else: + battery_type_qty = device["battery_type"] + row = [ + device['manufacturer'], + device['model'], + battery_type_qty, + ] + rows.append(row) + + writer.value_matrix = rows + tables_output += f"## {num_devices} Devices in library\n\n" + tables_output += "This file is auto generated, do not modify\n\n" + tables_output += writer.dumps() + + with open("library.md", "w", encoding="UTF-8") as md_file: + md_file.write("".join(toc_links) + tables_output) + md_file.close() + +generate_device_list() diff --git a/.github/scripts/library_doc/requirements.txt b/.github/scripts/library_doc/requirements.txt new file mode 100644 index 000000000..213df6c38 --- /dev/null +++ b/.github/scripts/library_doc/requirements.txt @@ -0,0 +1 @@ +pytablewriter==0.61.0 \ No newline at end of file diff --git a/.github/workflows/json_librarian.yml b/.github/workflows/json_librarian.yml new file mode 100644 index 000000000..b9119a3d8 --- /dev/null +++ b/.github/workflows/json_librarian.yml @@ -0,0 +1,53 @@ +name: JSON Library Sorter and Doc Gen + +on: + workflow_dispatch: + push: + paths: + - 'custom_components/battery_notes/data/library.json' + - '.github/workflows/json_librarian.yml' + - '.github/workflows/scripts/library_doc/**' + +jobs: + librarian: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up python 3.12 + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Clean up JSON library file + id: update-json + uses: jannekem/run-python-script-action@v1 + with: + script: | + import json + + # Load the existing JSON library file + with open("custom_components/battery_notes/data/library.json", "r", encoding="UTF-8") as f: + devices_json = json.loads(f.read()) + devices = devices_json.get("devices") + + # Sort the devices by manufacturer and model + devices.sort(key=lambda k: (k["manufacturer"].lower(), k["model"].lower())) + + with open("custom_components/battery_notes/data/library.json", "w", encoding="UTF-8") as f: + f.write(json.dumps(devices_json, indent=4)) + + - name: Install library doc generator dependencies + run: | + python -m pip install -r ${{ github.workspace }}/.github/scripts/library_doc/requirements.txt + + - name: Generate library doc + run: | + python3 ${{ github.workspace }}/.github/scripts/library_doc/generate_file.py + + - name: Commit any changes + uses: stefanzweifel/git-auto-commit-action@v5 diff --git a/.github/workflows/new_device.yml b/.github/workflows/new_device.yml index 22139160c..aaab6d882 100644 --- a/.github/workflows/new_device.yml +++ b/.github/workflows/new_device.yml @@ -61,9 +61,6 @@ jobs: if not duplicate_found: devices.append(new_device) - # Sort the devices by manufacturer and model - # devices.sort(key=lambda k: (k['manufacturer'], k['model'])) - # Save manufacturer and model for later use set_output("mm", "_".join(re.findall(r"\w+",f"{new_device['manufacturer']}{new_device['model']})".lower()))) set_output("manufacturer", "_".join(re.findall(r"\w+",f"{new_device['manufacturer']})"))) @@ -79,13 +76,24 @@ jobs: --header 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \ --header 'Content-Type: application/json' \ --data '{ - "title": "Device: ${{ steps.update-json.outputs.mm }}" + "title": "Device: ${{ steps.update-json.outputs.manufacturer }} - ${{ steps.update-json.outputs.model }}" }' + - name: Validate JSON + uses: docker://orrosenblatt/validate-json-action:latest + env: + INPUT_SCHEMA: ./schema.json + INPUT_JSONS: custom_components/battery_notes/data/library.json + - name: Create pull request uses: peter-evans/create-pull-request@v5 with: commit-message: "Update device: ${{ steps.update-json.outputs.model }} by ${{ steps.update-json.outputs.manufacturer }}" - title: "DEVICE: ${{ steps.update-json.outputs.manufacturer }} - ${{ steps.update-json.outputs.model }}" + title: "Device: ${{ steps.update-json.outputs.manufacturer }} - ${{ steps.update-json.outputs.model }}" body: "This pull request adds or updates the device information for ${{ steps.update-json.outputs.model }} by ${{ steps.update-json.outputs.manufacturer }}\nIt closes issue #${{ github.event.issue.number }}" branch: "device-${{ steps.update-json.outputs.mm }}" + + - name: Close Issue + run: gh issue close --comment "Thanks for the contribution. We're auto-closing this issue. If it's a new device, a pull request will be created that will be reviewed and merged." ${{github.event.issue.number}} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 8cf9f7cfa..40c7f6074 100644 --- a/README.md +++ b/README.md @@ -112,11 +112,9 @@ battery_notes: * How can I show my support? [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/yellow_img.png)](https://www.buymeacoffee.com/codechimp) - - ## Contributing to the Battery Library - -Fork the repository, add your device details to the JSON document `custom_components/battery_notes/data/library.json`, and then submit a pull request. Do not enable GitHub Actions (disabled by default) as this will mess with the pull request and are unnecessary for a library submission. +If you have issues with the form, or if you feel more comfortable editing JSON data, you can directly add definitions to [the library.json file](custom_components/battery_notes/data/library.json). +Fork the repository, add your device details to the JSON document `custom_components/battery_notes/data/library.json`, and then submit a pull request. +Do not enable GitHub Actions (disabled by default) on your fork as this will mess with the pull request and they are unnecessary for a library submission. * The manufacturer and model should be exactly what is displayed on the Device screen within Home Assistant. * The make & model names may be different between integrations such as Zigbee2MQTT and ZHA, if you see a similar device please duplicate the entry rather than changing it. @@ -159,7 +158,7 @@ If you want to contribute to this please read the [Contribution guidelines](CONT A lot of the inspiration for this integration came from the excellent [PowerCalc by bramstroker](https://github.com/bramstroker/homeassistant-powercalc), without adapting code from PowerCalc I'd never have worked out how to add additional sensors to a device. - +Huge thanks to @bmos for creating the issue form & automations for adding new devices. Thanks to everyone who has submitted devices to the library. diff --git a/custom_components/battery_notes/data/library.json b/custom_components/battery_notes/data/library.json index 0c2a7cf67..f06b59aa6 100644 --- a/custom_components/battery_notes/data/library.json +++ b/custom_components/battery_notes/data/library.json @@ -1782,4 +1782,4 @@ "battery_quantity": 3 } ] -} +} \ No newline at end of file