diff --git a/.hadolint.yaml b/.hadolint.yaml new file mode 100644 index 0000000..ec8794b --- /dev/null +++ b/.hadolint.yaml @@ -0,0 +1,2 @@ +ignored: + - SC1091 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e299e75..9c4fb45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] +- path for logs is now configurable by cli args +- configure the number of keeped logfiles by cli args +- add DOCS.md for add-ons +- pin library version und update them with renovate +- build config.yaml for add-ons by a jinja2 template +- use gnu make to build proxy and add-on - make the configuration more flexible, add command line args to control this - fix the python path so we don't need special import paths for unit tests anymore - support test coverager in vscode diff --git a/Makefile b/Makefile index afda9e9..24f9ab6 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ -.PHONY: build clean addon-dev addon-debug sddon-rc +.PHONY: build clean addon-dev addon-debug addon-rc addon-rel debug dev preview rc rel -# debug dev: -# $(MAKE) -C app $@ +debug dev preview rc rel: + $(MAKE) -C app $@ clean build: $(MAKE) -C ha_addons $@ -addon-dev addon-debug addon-rc: +addon-dev addon-debug addon-rc addon-rel: $(MAKE) -C ha_addons $(patsubst addon-%,%,$@) check-docker-compose: diff --git a/app/Makefile b/app/Makefile new file mode 100644 index 0000000..b68f782 --- /dev/null +++ b/app/Makefile @@ -0,0 +1,67 @@ +#!make +include ../.env + +SHELL = /bin/sh +IMAGE = tsun-gen3-proxy + + +# Folders +SRC=. +SRC_PROXY=$(SRC)/src +CNF_PROXY=$(SRC)/config + +DST=rootfs +DST_PROXY=$(DST)/home/proxy + +# collect source files +SRC_FILES := $(wildcard $(SRC_PROXY)/*.py)\ + $(wildcard $(SRC_PROXY)/*.ini)\ + $(wildcard $(SRC_PROXY)/cnf/*.py)\ + $(wildcard $(SRC_PROXY)/gen3/*.py)\ + $(wildcard $(SRC_PROXY)/gen3plus/*.py) +CNF_FILES := $(wildcard $(CNF_PROXY)/*.toml) + +# determine destination files +TARGET_FILES = $(SRC_FILES:$(SRC_PROXY)/%=$(DST_PROXY)/%) +CONFIG_FILES = $(CNF_FILES:$(CNF_PROXY)/%=$(DST_PROXY)/%) + +export BUILD_DATE := ${shell date -Iminutes} +VERSION := $(shell cat $(SRC)/.version) +export MAJOR := $(shell echo $(VERSION) | cut -f1 -d.) + +PUBLIC_URL := $(shell echo $(PUBLIC_CONTAINER_REGISTRY) | cut -f1 -d/) +PUBLIC_USER :=$(shell echo $(PUBLIC_CONTAINER_REGISTRY) | cut -f2 -d/) + + +dev debug: + @echo version: $(VERSION) build-date: $(BUILD_DATE) image: $(PRIVAT_CONTAINER_REGISTRY)$(IMAGE) + export VERSION=$(VERSION)-$@ && \ + export IMAGE=$(PRIVAT_CONTAINER_REGISTRY)$(IMAGE) && \ + docker buildx bake -f docker-bake.hcl $@ + +preview rc rel: + @echo version: $(VERSION) build-date: $(BUILD_DATE) image: $(PUBLIC_CONTAINER_REGISTRY)$(IMAGE) + @echo login at $(PUBLIC_URL) as $(PUBLIC_USER) + @DO_LOGIN="$(shell echo $(PUBLIC_CR_KEY) | docker login $(PUBLIC_URL) -u $(PUBLIC_USER) --password-stdin)" + export VERSION=$(VERSION)-$@ && \ + export IMAGE=$(PUBLIC_CONTAINER_REGISTRY)$(IMAGE) && \ + docker buildx bake -f docker-bake.hcl $@ + + + +.PHONY: debug dev preview rc rel + + +$(CONFIG_FILES): $(DST_PROXY)/% : $(CNF_PROXY)/% + @echo Copy $< to $@ + @mkdir -p $(@D) + @cp $< $@ + +$(TARGET_FILES): $(DST_PROXY)/% : $(SRC_PROXY)/% + @echo Copy $< to $@ + @mkdir -p $(@D) + @cp $< $@ + +$(DST)/requirements.txt : $(SRC)/requirements.txt + @echo Copy $< to $@ + @cp $< $@ diff --git a/app/docker-bake.hcl b/app/docker-bake.hcl index 56317d2..ba9d92b 100644 --- a/app/docker-bake.hcl +++ b/app/docker-bake.hcl @@ -18,7 +18,7 @@ variable "DESCRIPTION" { } target "_common" { - context = "app" + context = "." dockerfile = "Dockerfile" args = { VERSION = "${VERSION}" diff --git a/app/src/logging.ini b/app/src/logging.ini index 34db695..88f15ef 100644 --- a/app/src/logging.ini +++ b/app/src/logging.ini @@ -58,13 +58,13 @@ formatter=console_formatter class=handlers.TimedRotatingFileHandler level=INFO formatter=file_formatter -args=('log/proxy.log', when:='midnight') +args=(handlers.log_path + 'proxy.log', when:='midnight', backupCount:=handlers.log_backups) [handler_file_handler_name2] class=handlers.TimedRotatingFileHandler level=NOTSET formatter=file_formatter -args=('log/trace.log', when:='midnight') +args=(handlers.log_path + 'trace.log', when:='midnight', backupCount:=handlers.log_backups) [formatter_console_formatter] format=%(asctime)s %(levelname)5s | %(name)4s | %(message)s' diff --git a/app/src/server.py b/app/src/server.py index ce5077f..5725296 100644 --- a/app/src/server.py +++ b/app/src/server.py @@ -1,5 +1,6 @@ import logging import asyncio +import logging.handlers import signal import os import argparse @@ -133,14 +134,19 @@ def get_log_level() -> int: if __name__ == "__main__": # pragma: no cover parser = argparse.ArgumentParser() - parser.add_argument('-p', '--config_path', type=str, + parser.add_argument('-c', '--config_path', type=str, default='./config/', help='set path for the configuration files') parser.add_argument('-j', '--json_config', type=str, help='read user config from json-file') parser.add_argument('-t', '--toml_config', type=str, help='read user config from toml-file') - parser.add_argument('--add_on', action='store_true') + parser.add_argument('-l', '--log_path', type=str, + default='log/', + help='set path for the logging files') + parser.add_argument('-b', '--log_backups', type=int, + default=0, + help='set max number of daily log-files') args = parser.parse_args() # # Setup our daily, rotating logger @@ -148,12 +154,16 @@ def get_log_level() -> int: serv_name = os.getenv('SERVICE_NAME', 'proxy') version = os.getenv('VERSION', 'unknown') + setattr(logging.handlers, "log_path", args.log_path) + setattr(logging.handlers, "log_backups", args.log_backups) + logging.config.fileConfig('logging.ini') logging.info(f'Server "{serv_name} - {version}" will be started') - logging.info(f"AddOn: {args.add_on}") logging.info(f"config_path: {args.config_path}") logging.info(f"json_config: {args.json_config}") logging.info(f"toml_config: {args.toml_config}") + logging.info(f"log_path: {args.log_path}") + logging.info(f"log_backups: {args.log_backups} days") log_level = get_log_level() logging.info('******') diff --git a/ha_addons/ha_addon/DOCS.md b/ha_addons/ha_addon/DOCS.md index b5c1a29..310c54a 100644 --- a/ha_addons/ha_addon/DOCS.md +++ b/ha_addons/ha_addon/DOCS.md @@ -83,7 +83,7 @@ inverters: **Note**: _This is just an example, you need to replace the values with your own!_ -## MQQT settings +## MQTT settings By default, this add-on requires no `mqtt` config from the user. **This is not an error!** @@ -153,4 +153,4 @@ SOFTWARE. [Mosquitto]: https://github.com/home-assistant/addons/blob/master/mosquitto/DOCS.md [AdGuard]: https://github.com/hassio-addons/addon-adguard-home [repository-badge]: https://img.shields.io/badge/Add%20repository%20to%20my-Home%20Assistant-41BDF5?logo=home-assistant&style=for-the-badge -[repository-url]: https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Fs-allius%2Ftsun-gen3-proxy +[repository-url]: https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Fs-allius%2Fha-addons diff --git a/ha_addons/ha_addon/Dockerfile b/ha_addons/ha_addon/Dockerfile index 480bbb9..bcb941a 100755 --- a/ha_addons/ha_addon/Dockerfile +++ b/ha_addons/ha_addon/Dockerfile @@ -18,7 +18,11 @@ ARG BUILD_FROM="ghcr.io/hassio-addons/base:stable" FROM $BUILD_FROM AS base # Installiere Python, pip und virtuelle Umgebungstools -RUN apk add --no-cache python3=3.12.8-r1 py3-pip=24.3.1-r0 +RUN apk add --no-cache python3=3.12.8-r1 py3-pip=24.3.1-r0 && \ + python -m venv /opt/venv && \ + . /opt/venv/bin/activate + +ENV PATH="/opt/venv/bin:$PATH" diff --git a/ha_addons/ha_addon/rootfs/run.sh b/ha_addons/ha_addon/rootfs/run.sh index 5329d6f..4e42950 100755 --- a/ha_addons/ha_addon/rootfs/run.sh +++ b/ha_addons/ha_addon/rootfs/run.sh @@ -8,7 +8,7 @@ MQTT_PORT=$(bashio::services mqtt "port") MQTT_USER=$(bashio::services mqtt "username") MQTT_PASSWORD=$(bashio::services mqtt "password") -# wenn host gefunden wurde, dann nachricht ausgeben +# if a MQTT was/not found, drop a note if [ -z "$MQTT_HOST" ]; then echo "MQTT not found" else @@ -21,15 +21,13 @@ fi -cd /home || exit -# Erstelle Ordner für log und config -mkdir -p proxy/log -mkdir -p proxy/config +# Create folder for log und config files +mkdir -p /homeassistant/tsun-proxy/logs cd /home/proxy || exit export VERSION=$(cat /proxy-version.txt) echo "Start Proxyserver..." -python3 server.py --json_config=/data/options.json +python3 server.py --json_config=/data/options.json --log_path=/homeassistant/tsun-proxy/logs/ --config_path=/homeassistant/tsun-proxy/ --log_backups=2 diff --git a/ha_addons/templates/config.jinja b/ha_addons/templates/config.jinja index b0c3d2a..b8d40c4 100755 --- a/ha_addons/templates/config.jinja +++ b/ha_addons/templates/config.jinja @@ -4,6 +4,8 @@ version: {% if version is defined and version|length %} {{version}} {% else %} { image: docker.io/sallius/tsun-gen3-addon url: https://github.com/s-allius/tsun-gen3-proxy slug: {{slug}} +advanced: {{advanced}} +stage: {{stage}} init: false arch: - aarch64 @@ -12,13 +14,19 @@ arch: - armv7 startup: services homeassistant_api: true +map: + - type: addon_config + path: /homeassistant/tsun-proxy + read_only: False services: - mqtt:want ports: - 8127/tcp: 8127 5005/tcp: 5005 10000/tcp: 10000 +# FIXME: we disabled the watchdog due to exceptions in the ha supervisor. See: https://github.com/s-allius/tsun-gen3-proxy/issues/249 +# watchdog: "http://[HOST]:[PORT:8127]/-/healthy" + # Definition of parameters in the configuration tab of the addon # parameters are available within the container as /data/options.json # and should become picked up by the proxy - current workaround as a transfer script diff --git a/ha_addons/templates/debug_data.json b/ha_addons/templates/debug_data.json index ce61957..d325875 100644 --- a/ha_addons/templates/debug_data.json +++ b/ha_addons/templates/debug_data.json @@ -3,5 +3,7 @@ "name": "TSUN-Proxy (Debug)", "description": "MQTT Proxy for TSUN Photovoltaic Inverters with Debug Logging", "version": "debug", - "slug": "tsun-proxy-debug" + "slug": "tsun-proxy-debug", + "advanced": true, + "stage": "experimental" } \ No newline at end of file diff --git a/ha_addons/templates/dev_data.json b/ha_addons/templates/dev_data.json index 8dd6614..a3365f8 100644 --- a/ha_addons/templates/dev_data.json +++ b/ha_addons/templates/dev_data.json @@ -3,5 +3,7 @@ "name": "TSUN-Proxy (Dev)", "description": "MQTT Proxy for TSUN Photovoltaic Inverters", "version": "dev", - "slug": "tsun-proxy-dev" + "slug": "tsun-proxy-dev", + "advanced": false, + "stage": "experimental" } \ No newline at end of file diff --git a/ha_addons/templates/rel_data.json b/ha_addons/templates/rel_data.json index a106323..e7b5acb 100644 --- a/ha_addons/templates/rel_data.json +++ b/ha_addons/templates/rel_data.json @@ -2,5 +2,7 @@ { "name": "TSUN-Proxy", "description": "MQTT Proxy for TSUN Photovoltaic Inverters", - "slug": "tsun-proxy" + "slug": "tsun-proxy", + "advanced": false, + "stage": "stable" } \ No newline at end of file