commit 977b79408f08a2e781602cc6725cdff825295774 Author: Matt White Date: Mon Nov 2 10:09:26 2020 +0000 . initial commit diff --git a/.github/workflows/teslamate.yml b/.github/workflows/teslamate.yml new file mode 100644 index 0000000..97b0507 --- /dev/null +++ b/.github/workflows/teslamate.yml @@ -0,0 +1,93 @@ +name: teslamate + +on: + push: + branches: + - '**' + paths: + - 'teslamate/**' + - '!**.md' + - '.github/workflows/teslamate.yml' + +jobs: + build: + env: + TESLAMATE_TAG: 1.20.1 + + runs-on: ubuntu-latest + + strategy: + matrix: + arch: [amd64, armhf, armv7, aarch64] + fail-fast: true + + steps: + - uses: actions/checkout@v2 + with: + submodules: 'true' + - name: Docker version + run: docker version + - name: Setup qemu + id: qemu + uses: docker/setup-qemu-action@v1 + with: + platforms: all + - name: Install buildx + id: buildx + uses: docker/setup-buildx-action@v1 + with: + version: latest + - name: Available platforms + run: echo ${{ steps.buildx.outputs.platforms }} + - name: Set PLATFORM variable + run: | + case "${{ matrix.arch }}" in + "amd64" ) + echo "PLATFORM=linux/amd64" >> $GITHUB_ENV ;; + "i386" ) + echo "PLATFORM=linux/386" >> $GITHUB_ENV ;; + "aarch64" ) + echo "PLATFORM=linux/arm64" >> $GITHUB_ENV ;; + "armhf" ) + echo "PLATFORM=linux/arm/v7" >> $GITHUB_ENV ;; + "armv7" ) + echo "PLATFORM=linux/arm/v7" >> $GITHUB_ENV ;; + esac + - name: Set environment variables from config.json + run: | + echo "ADDON_VERSION=$(jq -r .version < $GITHUB_WORKFLOW/config.json)" >> $GITHUB_ENV + echo "ADDON_NAME=$(jq -r .name < $GITHUB_WORKFLOW/config.json)" >> $GITHUB_ENV + echo "ADDON_DESCRIPTION=$(jq -r .description < $GITHUB_WORKFLOW/config.json)" >> $GITHUB_ENV + - name: Login to docker hub + run: sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} + - name: Buildx build (if not main) + run: | + DOCKER_CLI_EXPERIMENTAL=enabled sudo docker buildx build \ + --pull \ + --platform=$PLATFORM \ + --build-arg TESLAMATE_TAG=$TESLAMATE_TAG \ + --label io.hass.type="addon" \ + --label io.hass.name="$ADDON_NAME" \ + --label io.hass.description="$ADDON_DESCRIPTION" \ + --label io.hass.version="$ADDON_VERSION" \ + --label io.hass.arch="${{ matrix.arch }}" \ + --label io.hass.url="https://github.com/matt-FFFFFF/hassio-addon-repository/blob/main/teslamate/README.md" \ + -t ${{ secrets.DOCKER_USERNAME }}/teslamate-${{ matrix.arch }}:$ADDON_VERSION \ + ./$GITHUB_WORKFLOW + if: github.ref != 'refs/heads/main' + - name: Buildx build --push (if main) + run: | + DOCKER_CLI_EXPERIMENTAL=enabled sudo docker buildx build \ + --pull \ + --push \ + --platform=$PLATFORM \ + --build-arg TESLAMATE_TAG=$TESLAMATE_TAG \ + --label io.hass.type="addon" \ + --label io.hass.name="$ADDON_NAME" \ + --label io.hass.description="$ADDON_DESCRIPTION" \ + --label io.hass.version="$ADDON_VERSION" \ + --label io.hass.arch="${{ matrix.arch }}" \ + --label io.hass.url="https://github.com/matt-FFFFFF/hassio-addon-repository/blob/main/teslamate/README.md" \ + -t ${{ secrets.DOCKER_USERNAME }}/teslamate-${{ matrix.arch }}:$ADDON_VERSION \ + ./$GITHUB_WORKFLOW + if: github.ref == 'refs/heads/main' diff --git a/CHANGELOG-FULL.md b/CHANGELOG-FULL.md new file mode 100644 index 0000000..c87fe5e --- /dev/null +++ b/CHANGELOG-FULL.md @@ -0,0 +1,48 @@ +# Changelog + +## 0.4.0 + +* Teslamate 1.20.1 +* Run as root + + +## 0.3.0 + +* Teslamate 1.20.0 + +## 0.2.0 + +* 🎉🎉🎉 Automatically deploy Grafana dashbaords 🎉🎉🎉 (if configured) +* Teslamate 1.19.3 +* Drop support for i386 + +## 0.1.1 + +* Teslamate [1.19.1](https://github.com/adriankumpf/teslamate/releases/tag/v1.19.1) + +## 0.1.0 + +* Teslamate [1.19.0](https://github.com/adriankumpf/teslamate/releases/tag/v1.19.0) +* Implement docker buildx +* Proper Raspberry Pi/ARM support (armv7 and arm64/aarch64) +* Use original Teslamate image as base + +[Full Changelog](https://github.com/matt-FFFFFF/hassio-addon-repository/blob/master/teslamate/CHANGELOG.md) + +## 0.0.7 + +* Disable Web UI link +* Disable ingress support + +## 0.0.6 + +* Teslamate 1.18.2 + +## 0.0.5 + +* Teslamate 1.18.0 + +## 0.0.4 + +* Initial published version +* Teslamate version 1.17.0 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..3339f01 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog + +## 0.4.0 + +* Teslamate 1.20.1 +* Run as root + +[Full Changelog](https://github.com/matt-FFFFFF/hassio-addon-repository/blob/master/teslamate/CHANGELOG.md) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a1cf6bd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,43 @@ +ARG TESLAMATE_TAG + +FROM teslamate/grafana:${TESLAMATE_TAG} as grafana + +#--- + +FROM teslamate/teslamate:${TESLAMATE_TAG} + +ARG BASHIO_VERSION=0.9.0 +ARG S6_OVERLAY_VERSION=1.22.1.0 + +USER root + +# Install bashio - from https://github.com/home-assistant/docker-base/blob/master/alpine/amd64/Dockerfile +RUN apk add --no-cache \ + bash \ + jq \ + tzdata \ + ca-certificates \ + curl \ + bind-tools \ + \ + && curl -L -s "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-amd64.tar.gz" \ + | tar zxvf - -C / \ + && mkdir -p /etc/fix-attrs.d \ + && mkdir -p /etc/services.d \ + \ + && mkdir -p /tmp/bashio \ + && curl -L -s https://github.com/hassio-addons/bashio/archive/v${BASHIO_VERSION}.tar.gz | tar -xzf - --strip 1 -C /tmp/bashio \ + && mv /tmp/bashio/lib /usr/lib/bashio \ + && ln -s /usr/lib/bashio/bashio /usr/bin/bashio \ + && rm -rf /tmp/bashio + +COPY --chown=root scripts/*.sh / +RUN chmod a+x /*.sh + +COPY --from=grafana --chown=root /dashboards /dashboards +COPY --from=grafana --chown=root /dashboards_internal /dashboards + +# USER nobody + +ENTRYPOINT ["/ha-bootstrap.sh"] +CMD ["bin/teslamate", "start"] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b29767a --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +# TeslaMate Addon for Home Assistant + +This addon builds on the excellent work of [Adrian Kumpf](https://github.com/adriankumpf/teslamate). See his repo for information regarding the TeslaMate application. + +## DB Connection + +If using the Postgres addon from this repo, the database host is ```29b65938-postgres``` + +## No Ingress Support + +TeslaMate does not currently support a base path, so it expects all requests to be generated from the URL root ```/```. +See https://github.com/adriankumpf/teslamate/issues/494. + +This means we cannot implement Ingress and must expose TeslaMate to the network. +I recommend you only do this to configure TeslaMate and you then remove the external port mapping. + +## Grafana Configuration + +> I recommend you use the existing Grafana addon from the community addons + +**NEW - Automatic dashboard uploading!** + +### Data Source + +Configure a PostgreSQL data source as follows: + +![Grafana Postgres data source](https://raw.githubusercontent.com/matt-FFFFFF/hassio-addon-repository/master/teslamate/media/grafana-postgres.png) + +### Uploading Dashboards + +Configure the **Grafana** addon and set the admin username and password: + +```yml +env_vars: + - name: GF_SECURITY_ADMIN_USER + value: admin + - name: GF_SECURITY_ADMIN_PASSWORD + value: mysecretpassword +``` + +Now configure the **Teslamate** addon: + +```yaml +grafana_import_dashboards: true +grafana_folder_name: "TeslaMate" +grafana_host: "a0d7b954-grafana" # this is correct if you use the community addon +grafana_port: 3000 # this is correct if you use the community addon +grafana_user: "admin" +grafana_pass: "pass" +``` diff --git a/config.json b/config.json new file mode 100644 index 0000000..10b0d51 --- /dev/null +++ b/config.json @@ -0,0 +1,64 @@ +{ + "name": "TeslaMate", + "version": "0.4.0", + "slug": "teslamate", + "description": "A self-hosted data logger for your Tesla.", + "arch": ["armhf", "armv7", "aarch64", "amd64"], + "startup": "application", + "boot": "auto", + "ingress": false, + "ports": { + "4000/tcp": null + }, + "ports_description": { + "4000/tcp": "Insecure web interface - disable when not in use" + }, + "options": { + "database_user": "user", + "database_pass": "pass", + "database_name": "dbname", + "database_host": "29b65938-postgres", + "database_ssl": false, + "database_port": 5432, + "disable_mqtt": false, + "grafana_import_dashboards": false, + "grafana_folder_name": "TeslaMate", + "grafana_host": "a0d7b954-grafana", + "grafana_port": 3000, + "grafana_user": "admin", + "grafana_pass": "pass", + "mqtt_host": "core-mosquitto", + "mqtt_user": "user", + "mqtt_pass": "pass", + "mqtt_tls": true, + "mqtt_tls_accept_invalid_certs": false, + "mqtt_namespace": "account_0", + "timezone": "Europe/London", + "port": 4000 + }, + "schema": { + "database_user": "str", + "database_pass": "str", + "database_name": "str", + "database_host": "str", + "database_ssl": "bool", + "database_port": "int", + "disable_mqtt": "bool", + "grafana_import_dashboards": "bool", + "grafana_folder_name": "str", + "grafana_host": "str", + "grafana_port": "int", + "grafana_user": "str", + "grafana_pass": "str", + "mqtt_host": "str", + "mqtt_user": "str", + "mqtt_pass": "str", + "mqtt_tls": "bool", + "mqtt_tls_accept_invalid_certs": "bool", + "mqtt_namespace": "str", + "timezone": "str", + "port": "int" + }, + "url": "https://github.com/matt-FFFFFF/hassio-addon-repository/blob/master/teslamate/README.md", + "image": "mattffffff/teslamate-{arch}" + } diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..f0cf5b3 Binary files /dev/null and b/icon.png differ diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..f0cf5b3 Binary files /dev/null and b/logo.png differ diff --git a/media/grafana-postgres.png b/media/grafana-postgres.png new file mode 100644 index 0000000..26d0949 Binary files /dev/null and b/media/grafana-postgres.png differ diff --git a/scripts/dashboards.sh b/scripts/dashboards.sh new file mode 100644 index 0000000..1f0a0c8 --- /dev/null +++ b/scripts/dashboards.sh @@ -0,0 +1,127 @@ +#!/usr/bin/env bashio + +# The script assumes that basic authentication is configured +# +# DASHBOARDS_DIRECTORY represents the path to the directory +# where the JSON files corresponding to the dashboards exist. +# The default location is relative to the execution of the +# script. +# +# Source: https://github.com/cirocosta/sample-grafana/blob/master/update-dashboards.sh + +set -o errexit + +readonly HOST=$(bashio::config 'grafana_host') +readonly PORT=$(bashio::config 'grafana_port') +readonly USER=$(bashio::config 'grafana_user') +readonly PASS=$(bashio::config 'grafana_pass') +readonly DASHBOARDS_DIRECTORY="/dashboards" +readonly FOLDER_NAME=$(bashio::config 'grafana_folder_name') + + + +main() { + local task=$1 + + URL="http://$HOST:$PORT" + LOGIN="$USER:$PASS" + + case $task in + backup) backup;; + restore) restore;; + *) exit 1;; + esac + +} + + +backup() { + local dashboard_json + + for dashboard in $(list_dashboards); do + dashboard_json=$(get_dashboard "$dashboard") + + if [[ -z "$dashboard_json" ]]; then + echo "ERROR: + Couldn't retrieve dashboard $dashboard. + " + exit 1 + fi + + echo "$dashboard_json" > "$DASHBOARDS_DIRECTORY/$dashboard".json + + echo "BACKED UP $(basename "$dashboard").json" + done +} + + +restore() { + bashio::log.info "Checking for Grafana folder: $FOLDER_NAME" + FLD=$(curl --silent --show-error \ + --user "$LOGIN" -H "Content-Type: application/json" \ + $URL/api/folders | jq ".[] | select(.title==\"$FOLDER_NAME\")") + + if [[ -z "$FLD" ]]; then + bashio::log.info "Not found... creating" + FLD=$(curl \ + --silent \ + --show-error \ + --user "$LOGIN" \ + -X POST -H "Content-Type: application/json" \ + -d "{\"title\":\"$FOLDER_NAME\"}" \ + "$URL/api/folders") + fi + + FOLDER_ID=$(echo $FLD | jq -r .id) + + if [[ -z "$FOLDER_ID" ]]; then + bashio::log.error "Could not determine Grafana folder id" + exit 1 + fi + + find "$DASHBOARDS_DIRECTORY" -type f -name \*.json -print0 | + while IFS= read -r -d '' dashboard; do + curl \ + --silent --show-error --output /dev/null \ + --user "$LOGIN" \ + -X POST -H "Content-Type: application/json" \ + -d "{\"dashboard\":$(cat "$dashboard"),\"overwrite\":true,\"folderId\":$FOLDER_ID, \ + \"inputs\":[{\"name\":\"DS_POSTGRES\",\"type\":\"datasource\", \ + \"pluginId\":\"postgres\",\"value\":\"TeslaMate\"}]}" \ + "$URL/api/dashboards/import" + + bashio::log.info "... RESTORED $(basename "$dashboard")" + done + bashio::log.info "Finished Importing Grafana Dashboards" +} + + +get_dashboard() { + local dashboard=$1 + + if [[ -z "$dashboard" ]]; then + echo "ERROR: + A dashboard must be specified. + " + exit 1 + fi + + curl \ + --silent \ + --user "$LOGIN" \ + "$URL/api/dashboards/db/$dashboard" | + jq '.dashboard | .id = null' +} + + +list_dashboards() { + curl \ + --silent \ + --user "$LOGIN" \ + "$URL/api/search" | + jq -r '.[] | select(.type == "dash-db") | .uri' | + cut -d '/' -f2 +} + + +main "$@" \ No newline at end of file diff --git a/scripts/ha-bootstrap.sh b/scripts/ha-bootstrap.sh new file mode 100755 index 0000000..9b0491d --- /dev/null +++ b/scripts/ha-bootstrap.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bashio + +# Database things +export DATABASE_USER=$(bashio::config 'database_user') +export DATABASE_PASS=$(bashio::config 'database_pass') +export DATABASE_NAME=$(bashio::config 'database_name') +export DATABASE_HOST=$(bashio::config 'database_host') +export DATABASE_PORT=$(bashio::config 'database_port') + +# MQTT things +export DISABLE_MQTT=$(bashio::config 'disable_mqtt') +export MQTT_HOST=$(bashio::config 'mqtt_host') +export MQTT_USERNAME=$(bashio::config 'mqtt_user') +export MQTT_PASSWORD=$(bashio::config 'mqtt_pass') +export MQTT_TLS=$(bashio::config 'mqtt_tls') +export MQTT_TLS_ACCEPT_INVALID_CERTS=$(bashio::config 'mqtt_tls_accept_invalid_certs') +export MQTT_NAMESPACE=export MQTT_TLS=$(bashio::config 'mqtt_namespace') + +# Other things +export TZ=$(bashio::config 'timezone') +export PORT=$(bashio::config 'port') + +# Import dashboards +if [ $(bashio::config 'grafana_import_dashboards') == 'true' ]; then + /dashboards.sh restore +fi + +exec $(/usr/bin/env sh) /entrypoint.sh "$@" \ No newline at end of file