diff --git a/grott-current/CHANGELOG.md b/grott-current/CHANGELOG.md new file mode 100644 index 0000000..bc093e4 --- /dev/null +++ b/grott-current/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog + +## 0.1 + +- Initial version +- Based on grott v2.7.6 diff --git a/grott-current/DOCS.md b/grott-current/DOCS.md new file mode 100644 index 0000000..bc95320 --- /dev/null +++ b/grott-current/DOCS.md @@ -0,0 +1,30 @@ +# Home Assistant Add-on: Grott - The Growatt inverter monitor + +## Installation + +Follow these steps to get the add-on installed on your system: + +1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +2. Find the "Grott" add-on and click it. +3. Click on the "INSTALL" button. + +## How to use + +The add-on has a couple of options available. To get the add-on running: + +1. Start the add-on. +2. Have some patience and wait a couple of minutes. +3. Check the add-on log output to see the result. + +## Add-on configuration: +All options from grott are available as options in this add-on. They need to follow the naming convention of the environment variables. Eg: +```yaml + gmode: proxy + gnomqtt: False + gmqttip: 127.0.0.1 + gmqttport: 5288 + gmqttauth: False + gmqtttopic: energy/grott + gmqttuser: user + gmqttpassword: password +``` diff --git a/grott-current/Dockerfile b/grott-current/Dockerfile new file mode 100644 index 0000000..376b370 --- /dev/null +++ b/grott-current/Dockerfile @@ -0,0 +1,34 @@ +ARG BUILD_FROM +FROM $BUILD_FROM + +ENV LANG C.UTF-8 + +# Run updates +# RUN apt-get clean && apt-get update && apt-get upgrade -y + +# Set the locale +# RUN apt-get install -y locales && locale-gen en_US.UTF-8 + +# Install python/pip +ENV PYTHONUNBUFFERED=1 +RUN apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python +RUN python3 -m ensurepip +RUN pip3 install --no-cache --upgrade pip setuptools + + +#RUN curl -k https://codeload.github.com/johanmeijer/grott/zip/master --output files.zip && unzip files.zip +#RUN unzip files.zip + +# Copy data for add-on +COPY script.sh /app/script.sh +WORKDIR /app +RUN curl -Lk 'https://github.com/johanmeijer/grott/archive/refs/heads/2.7-(Beta).zip' --output files.zip && unzip -o files.zip && rm files.zip && mv grott-*/*.py ./ +# Move the addon +RUN curl -L 'https://raw.githubusercontent.com/egguy/grott/feature/ha-extension/examples/Home%20Assistent/grott_ha.py' -o grott_ha.py + +#Install required python packages +RUN pip install paho-mqtt requests influxdb influxdb + + +RUN chmod a+x script.sh +CMD [ "./script.sh" ] diff --git a/grott-current/README.md b/grott-current/README.md new file mode 100644 index 0000000..c7246f1 --- /dev/null +++ b/grott-current/README.md @@ -0,0 +1,157 @@ +## The Growatt Inverter Monitor +[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/donate?business=RQFS46F9JTESQ&item_name=Grott+¤cy_code=EUR) + +(Per 28-12-2021 version 2.6 (2.6.1g) has been promoted to master branche) + +Growatt inverters can send performance and status metrics (log data) to the Growatt company servers. The inverters rely on either a ShineWIFI module or a ShineLAN box to relay the data to Growatt. The metrics stored on the Growatt servers then can be viewed on the Growatt website or using the ShinePhone mobile app. + +The purpose of Grott is to read, parse and forward the *raw metrics as they are sent* to Growatt servers. This means other applications can consume the raw Growatt metrics without relying on the Growatt API and servers and without delay. + + +### Two modes of metric data retrieval +Grott can intercept the inverter metrics in two distinct modes: +* Proxy mode (man in the middle): The Growatt ShineWifi or ShineLAN box can be easily configured to use Grott as an alternative server to the default server.growatt.com. Grott then acts as a relay to the Growatt servers. Grott reads the transmitted data, and then forwards the data to server.grott.com. +* Sniff mode (original connection): Can be used if your router is linux based. IPTables NAT masquerading is used in conjuction with a python packet sniffer to read the data. (This is more resource intensive on the linux host). + + +### Where Grott can forward metric data to +Grott can forward the parsed metrics to: +* MQTT (suggested option for many home automation systems such as Home Assistant, OpenHAB and Domoticz) +* InfluxDB v1 and v2 (a time series database with dashboarding functionality) +* PVOutput.org (a service for sharing and comparing PV output data) +* Custom output using the extension functionality (Examples available for Export to CSV files and writing to a Http Server). + + +### Compatibility +The program is written in python and runs under Linux, Windows. +It can run: +* Interactive from the command line interface +* As a Linux or Windows service +* As a [Docker container](https://github.com/johanmeijer/grott/wiki/Docker-support). + +And is tested, but not limited to, inverter models: ++ 1500-S (ShineWiFi) ++ 3000-S (Shinelan) ++ 2500-MTL-S (ShineWiFi) ++ 4200-MTL-S (Shinelan) ++ 5000TL-X (ShineWifi-X) ++ 3600TL-XE (ShineLink-X) ++ 3600TL-XE (ShineLan) ++ MOD 5000TL3-X* (ShineLan) ++ MOD 9000TL3-X* + +**Experimental in latest 2.6 branch* + +The Docker images are tested RPI(arm32), Ubuntu and Synology NAS + +## Grott installation + +### ShineLAN or ShineWIFI configuration +If Grott is running in proxy mode the ShineLAN box or ShineWIFI module [needs to be configured](https://github.com/johanmeijer/grott/wiki/Rerouting-Growatt-Wifi-TCPIP-data-via-your-Grott-Server) to send data to Grott instead of the Growatt server API. +Please see the [Wiki](https://github.com/johanmeijer/grott/wiki) for further information and installation details. + +## What's new +### New in Version 2.6.1 (Master) +#### TL3-X 3 phase inverter support +see issue #81/#82/#85: add invtype=tl3 in grott.ini [Generic] section (or use ginvtype="tl3" environmental variable e.g. for docker ledidome/grott:2.6.1f) +#### SPF off grid inverter support +see issue #42/#46: add invtype=spf in grott.ini [Generic] section (or use ginvtype=spf environmental variable e.g. for docker) +#### SPH hybrid (grid/battery) support +see issue #34: add invtype=sph in grott.ini [Generic] section (or use ginvtype=sph environmental variable e.g. for docker) +#### Growatt Smart Meter support +see issue #47: data will be processed automatically and send to MQTT, InfluxDB and PVOutput.org +#### Export to CSV file +see issue #79, pull request #91. Moe information can be found in the wiki: https://github.com/johanmeijer/grott/wiki/Extensions + +### New in Version 2.5.x +Improved dynamic data processing and dynamic generation of output allowing: +* add new output (values) without changing code (using external layout definitions) +* rename keywords in MQTT JSON message and influxDB to own naming convention +* format the verbose output values +* Allow negative values for pvpowerout. New (always on) inverters can also use power. +* Bugfix inluxdb port error + +see: https://github.com/johanmeijer/grott/wiki/Grott-advanced-(customize-behaviour) +
+Added new outout values to mqtt and influxDB to support 3 phase grid connection (actual information on voltage, current and power delivered), total active worktime (in 0.5 S) and energy generation per PV string (day and total) +
+ +Improve environmental processing for mqtt/influxDB/growatt ip and port definitions + +### New in Version 2.4.0 +Introduce possibility to add extensions for additional (personalized) processing. +,br. +see: https://github.com/johanmeijer/grott/wiki/Extensions + +### New in Version 2.3.1 +Direct output to inlfuxdb (v1 and v2) +
+see: https://github.com/johanmeijer/grott/wiki/InfluxDB-Support +### New in Version 2.2.6 +Mulitiple inverter (multiple system id's) support in PVOutput.org +
+see: https://github.com/johanmeijer/grott/wiki/PVOutput.org-support + +#### Be aware: Wiith this release the default grott.ini moved to examples directory +This file is deleted from the grott default directory to simply github installation (not overwrite your settings). +It is advised to copy this file into the Grott default directory (and customise it) during first time installation + +### New in Version 2.2.1 +#### Automatic protocol detection and processing +Limited .ini configuration needed (inverterid, encryption, offset and record layout is automaticially detected) +#### Direct output to PVOutput.org (no mqtt processing needed). +Specify pvoutput = True and apikey and systemid in .ini file to enable it. +#### Docker support +2 docker containers are created ledidobe/grottrpi (specific old RPI with ARM32) and ledidobe/grott (generic one, tested on synology NAS and Ubuntu). See https://hub.docker.com/search?q=ledidobe&type=image. +See issue 4 and 15 on how to use it (wiki will be updated soon) +#### Command Blocking / Filtering +with blockcmd = True specified in .ini (configure/reboot) commands from outside to the inverter are blocked. This protects the inverter from beeing controlled from the outside while data exchange with server.growatt.com for reporting is still active. +#### Use date/time from data record +If date/time is available in the data (inserted by the inverter) this will be used. In this way buffered records will be sent with the original creation time (in the past). +If date/time is not available in the data record the server time will be used (as it was originally). +In the mqtt message the key buffered is added (yes/no) which indicates that the message is from the buffer (past) or actual. + +### Version 2: Introduction of 2 modes support: sniff and proxy. +In sniff mode (default and compatable with older Grott versions) IP sniffering technology is used (based on: https://github.com/buckyroberts/Python-Packet-Sniffer). In this mode the data needs to be "re-routed" using linux IP forwarding on the device Grott is running. In this mode Grott "sees" every IP package and when a Growatt TCP packages passes it will be processed and a MQTT will be sent if inverter status information is detected. + +With the proxy mode Grott is listening on a IP port (default 5279), processes the data (sent MQTT message) and routes the original packet to the growatt website. + +The proxy mode functionality can be enabled by: + +- mode = proxy in the conf.ini file +- m proxy parameter during startup + +Pro / Cons: + + sniff mode + + Data will also be routed to the growatt server if Grott is not active + - All TCP packages (also not growatt) need to be processed by Grott. + This is more resource (processor) intesive and can have a negative impact on the device performance. + - Configure IP forwarding can be complex if a lot of other network routing is configured (e.g. by Docker). + - Sudo rights necessary to allow network sniffering + + proxy mode: + + Simple configuration + + Only Growatt IP records are being analysed and processed by Grott + + Less resource intensive + + No sudo rights needed + + Blocking / Filtering of commands from the outside is possible + - If Grott is not running no data will be sent to the Growatt server + +The adivse is to use the proxy mode. This mode is strategic and will be used for enhanced features like automatic protocol detection and command blocking filtering. +
+Sniff mode is not supported under Windows +
+In sniff mode it is necessary to run Grott with SUDO rights. + +#### Minimal installation +The following modules are needed the use Grott: +- grott.py +- grott.ini (available in examples direcory) +- grottconf.py +- grottdata.py +- grottproxy.py +- grottsniffer.py + +#### More Version History: see Version_history.txt file. +#### Grott is a "hobby" project you can use it as it is (with the potential errors and imperfections). Remarks and requests for improvement are welcome. diff --git a/grott-current/build.yaml b/grott-current/build.yaml new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/grott-current/build.yaml @@ -0,0 +1 @@ + diff --git a/grott-current/config.json b/grott-current/config.json new file mode 100644 index 0000000..2763035 --- /dev/null +++ b/grott-current/config.json @@ -0,0 +1,80 @@ +{ + "name": "Grott - HA extension - current", + "version": "2.7.7-current", + "slug": "grott-current", + "description": "The Growatt inverter monitor - current HA plugin", + "url": "https://github.com/johanmeijer/grott", + "arch": [ + "armhf", + "armv7", + "aarch64", + "amd64", + "i386" + ], + "startup": "application", + "services": [ + "mqtt:need" + ], + "init": false, + "boot": "auto", + "ports": { + "5279/tcp": 5279 + }, + "watchdog": "tcp://[HOST]:[PORT:5279]", + "options": { + "gmode": "proxy", + "gnomqtt": "False", + "ginvtype": "default", + "mqtt": {} + }, + "schema": { + "gverbose": "bool?", + "gminrecl": "int?", + "gmode": "str", + "ggrottip": "str?", + "ggrottport": "port?", + "gblockcmd": "bool?", + "gnoipf": "bool?", + "gtime": "str?", + "gtimezone": "str?", + "gsendbuf": "bool?", + "gcompat": "bool?", + "gvalueoffset": "int?", + "ginverterid": "str?", + "gincludeall": "bool?", + "ginvtype": "str?", + "gdecrypt": "bool?", + "ggrowattip": "str?", + "ggrowattport": "port?", + "gnomqtt": "bool?", + "gmqttip": "str?", + "gmqttport": "str?", + "gmqtttopic": "str?", + "gmqttauth": "bool?", + "gmqttuser": "str?", + "gmqttpassword": "password?", + "gpvoutput": "bool?", + "gpvapikey": "str?", + "gpvsystemid": "int?", + "gpvinverters": "int?", + "ginflux": "bool?", + "ginflux2": "bool?", + "gifdbname": "str?", + "gifip": "str?", + "gifport": "port?", + "gifuser": "str?", + "gifpassword": "password?", + "giforg": "str?", + "gifbucket": "str?", + "giftoken": "str?", + "gextension": "bool?", + "gextname": "str?", + "gextvar": "str?", + "ginvtypemap": "str?", + "mqtt": { + "server": "str?", + "user": "str?", + "password": "str?" + } + } +} diff --git a/grott-current/icon.png b/grott-current/icon.png new file mode 100644 index 0000000..b3a89bc Binary files /dev/null and b/grott-current/icon.png differ diff --git a/grott-current/logo.png b/grott-current/logo.png new file mode 100644 index 0000000..4db5614 Binary files /dev/null and b/grott-current/logo.png differ diff --git a/grott-current/script.sh b/grott-current/script.sh new file mode 100644 index 0000000..07ed0f1 --- /dev/null +++ b/grott-current/script.sh @@ -0,0 +1,49 @@ +#!/usr/bin/with-contenv bashio + +if bashio::config.has_value 'gverbose'; then export gverbose="$(bashio::config 'gverbose')"; fi +if bashio::config.has_value 'gminrecl'; then export gminrecl="$(bashio::config 'gminrecl')"; fi +if bashio::config.has_value 'gmode'; then export gmode="$(bashio::config 'gmode')"; fi +if bashio::config.has_value 'ggrottip'; then export ggrottip="$(bashio::config 'ggrottip')"; fi +if bashio::config.has_value 'ggrottport'; then export ggrottport="$(bashio::config 'ggrottport')"; fi +if bashio::config.has_value 'gblockcmd'; then export gblockcmd="$(bashio::config 'gblockcmd')"; fi +if bashio::config.has_value 'gnoipf'; then export gnoipf="$(bashio::config 'gnoipf')"; fi +if bashio::config.has_value 'gtime'; then export gtime="$(bashio::config 'gtime')"; fi +if bashio::config.has_value 'gtimezone'; then export gtimezone="$(bashio::config 'gtimezone')"; fi +if bashio::config.has_value 'gsendbuf'; then export gsendbuf="$(bashio::config 'gsendbuf')"; fi +if bashio::config.has_value 'gcompat'; then export gcompat="$(bashio::config 'gcompat')"; fi +if bashio::config.has_value 'gvalueoffset'; then export gvalueoffset="$(bashio::config 'gvalueoffset')"; fi +if bashio::config.has_value 'ginverterid'; then export ginverterid="$(bashio::config 'ginverterid')"; fi +if bashio::config.has_value 'gincludeall'; then export gincludeall="$(bashio::config 'gincludeall')"; fi +if bashio::config.has_value 'ginvtype'; then export ginvtype="$(bashio::config 'ginvtype')"; fi +if bashio::config.has_value 'gdecrypt'; then export gdecrypt="$(bashio::config 'gdecrypt')"; fi +if bashio::config.has_value 'ggrowattip'; then export ggrowattip="$(bashio::config 'ggrowattip')"; fi +if bashio::config.has_value 'ggrowattport'; then export ggrowattport="$(bashio::config 'ggrowattport')"; fi +if bashio::config.has_value 'gnomqtt'; then export gnomqtt="$(bashio::config 'gnomqtt')"; fi +if bashio::config.has_value 'gmqttip'; then export gmqttip="$(bashio::config 'gmqttip')"; fi +if bashio::config.has_value 'gmqttport'; then export gmqttport="$(bashio::config 'gmqttport')"; fi +if bashio::config.has_value 'gmqtttopic'; then export gmqtttopic="$(bashio::config 'gmqtttopic')"; fi +if bashio::config.has_value 'gmqttauth'; then export gmqttauth="$(bashio::config 'gmqttauth')"; fi +if bashio::config.has_value 'gmqttuser'; then export gmqttuser="$(bashio::config 'gmqttuser')"; fi +if bashio::config.has_value 'gmqttpassword'; then export gmqttpassword="$(bashio::config 'gmqttpassword')"; fi +if bashio::config.has_value 'gpvoutput'; then export gpvoutput="$(bashio::config 'gpvoutput')"; fi +if bashio::config.has_value 'gpvapikey'; then export gpvapikey="$(bashio::config 'gpvapikey')"; fi +if bashio::config.has_value 'gpvsystemid'; then export gpvsystemid="$(bashio::config 'gpvsystemid')"; fi +if bashio::config.has_value 'gpvinverters'; then export gpvinverters="$(bashio::config 'gpvinverters')"; fi +if bashio::config.has_value 'ginflux'; then export ginflux="$(bashio::config 'ginflux')"; fi +if bashio::config.has_value 'ginflux2'; then export ginflux2="$(bashio::config 'ginflux2')"; fi +if bashio::config.has_value 'gifdbname'; then export gifdbname="$(bashio::config 'gifdbname')"; fi +if bashio::config.has_value 'gifip'; then export gifip="$(bashio::config 'gifip')"; fi +if bashio::config.has_value 'gifport'; then export gifport="$(bashio::config 'gifport')"; fi +if bashio::config.has_value 'gifuser'; then export gifuser="$(bashio::config 'gifuser')"; fi +if bashio::config.has_value 'gifpassword'; then export gifpassword="$(bashio::config 'gifpassword')"; fi +if bashio::config.has_value 'giforg'; then export giforg="$(bashio::config 'giforg')"; fi +if bashio::config.has_value 'gifbucket'; then export gifbucket="$(bashio::config 'gifbucket')"; fi +if bashio::config.has_value 'giftoken'; then export giftoken="$(bashio::config 'giftoken')"; fi +if bashio::config.has_value 'ginvtypemap'; then export ginvtypemap="$(bashio::config 'ginvtypemap')"; fi + + +export gextension="True" +export gextname="grott_ha" +export gextvar="{\"ha_mqtt_host\": \"$(bashio::services mqtt "host")\", \"ha_mqtt_port\": \"$(bashio::services mqtt "port")\", \"ha_mqtt_user\": \"$(bashio::services mqtt "username")\", \"ha_mqtt_password\": \"$(bashio::services mqtt "password")\"}" + +python -u grott.py -v