Skip to content

Commit 5810e73

Browse files
authored
Merge branch 'openhab:main' into main
2 parents 0232ffd + d99adea commit 5810e73

10 files changed

Lines changed: 305 additions & 12 deletions

File tree

CONTRIBUTING.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ Get in contact early in the development to propose your idea.
1818
Fork the repo and make changes on your fork in a feature branch.
1919
Then be sure to also provide or update the documentation right when creating or modifying features.
2020

21+
* if adding a new function, see which of the functions/*.bash files it fits in best
22+
* create install_xxx() routine and make it work with arguments "install" and "remove"
23+
* Make sure install_xxx() works in interactive as well as non-interactive (unattended) mode
24+
If user input is required, create another parameter in openhabian.conf (source for that is in build-image/)
25+
To test:
26+
source functions/helpers.bash; source functions/packages.bash; set -x
27+
install_xxx arg1 arg2 ... argn
28+
* add BATS tests for "install" and "remove"
29+
30+
2131
### Code architecture
2232
Always write clean, modular and testable code.
2333
We have a simple [code-style](#codestyle) which in combination with the static linter [ShellCheck](https://www.shellcheck.net/) works as our coding guidelines.

build-image/openhabian.conf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ zram_reset=done # remove when zram is no longer needed to auto update
9090
hotspot=enable
9191
hotspotpw=openhabian
9292

93+
# Grott settings (only enable this if Growatt binding will be used)
94+
# grottSetupEnabled=false
95+
9396
# external SD card device to backup and mirror the internal SD card to
9497
# backupdrive=/dev/sda
9598
storageconfig=openhab-dir

docs/openhabian.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,12 +254,13 @@ Each of these are included as a part of `openhabian-config` menu option 20.
254254
- [OWServer](https://owfs.org) - 1-Wire system of Dallas/Maxim
255255
- [FIND](https://www.internalpositioning.com/) - Framework for Internal Navigation and Discovery
256256
- Mi Flora MQTT daemon
257+
- Grott Proxy server for [Growatt binding](https://www.openhab.org/addons/bindings/growatt/#grott-application-installation-and-setup)
257258

258259
## First boot configuration
259260

260261
Many settings are configurable prior to the first boot of openHABian by changing the key value pairs in the `/boot/openhabian.conf` file on the SD card once you have flashed the initial image onto it.
261262

262-
Please note that - in case you use a Windows system for writing the SD card - the `/boot/` partition will be mounted to a drive named `bootfs`. So, e.g. if this drive has the letter `D:`, `/boot/openhabian.conf` will be found as `D:\openhabian.conf`.
263+
Please note that - in case you use a Windows system for writing the SD card - the `/boot/` partition will be mounted to a drive named `bootfs`. So, e.g. if this drive has the letter `D:`, `/boot/openhabian.conf` will be found as `D:\openhabian.conf`.
263264

264265
The openHABian configuration file uses key value pairs, essentially a list of `option=value` settings in a plain text file.
265266
All supported options are already in the file but unused options and optional components are commented out by default.

functions/java-jre.bash

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ adoptium_fetch_apt() {
4444
if ! cond_redirect apt-get update; then echo "FAILED (update apt lists)"; return 1; fi
4545

4646
# if on 32 bit OS, install unsupported Adoptium 32 bit from OpenEMS community project
47-
if [[ $(getconf LONG_BIT) == 32 ]]; then
47+
if [[ $1 == "21" ]] && [[ $(getconf LONG_BIT) == 32 ]]; then
4848
if ! cond_redirect wget -nv -O "${cachedir}/${cachefile}" "${URL}/${pkgfile}"; then echo "FAILED (download JVM pkg)"; rm -f "${cachedir}/${cachefile}"; return 1; fi
4949
else
50-
if ! cond_redirect dpkg --configure -a; then echo "FAILED (dpkg)"; return 1; fi
50+
if ! cond_redirect dpkg --configure -a --confnew; then echo "FAILED (dpkg)"; return 1; fi
5151
if cond_redirect apt-get install --download-only --yes "temurin-${1}-jre"; then echo "OK"; else echo "FAILED"; return 1; fi
5252
fi
5353
}

functions/menu.bash

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ show_main_menu() {
7575
return 255
7676
fi
7777
if is_arm && [[ "$(getconf LONG_BIT)" == "32" ]]; then
78-
whiptail --title "32 bit OS" --msgbox "You are running a 32 bit Operating System. THIS IS NOT SUPPORTED ANY LONGER.\\nOpenHAB 5 and Java 21 require that you upgrade your OS to a 64 bit version, please read the release notes at\\nhttps://github.com/openhab/openhab-distro/releases/tag/5.0.0#openhabian\\nYou can still install manually via menus 45 and 41 if in vain but remember that will be an UNSUPPORTED setup.\\nPlease reinstall your system with the 64 bit image of openHABian." 11 80
78+
whiptail --title "32 bit OS" --msgbox "You are running a 32 bit Operating System. THIS IS NOT SUPPORTED ANY LONGER.\\nOpenHAB 5 and Java 21 require that you upgrade your OS to a 64 bit version, please read the release notes at\\nhttps://github.com/openhab/openhab-distro/releases/tag/5.0.0#openhabian\\nYou can still install manually via menus 45 and 41 if in vain but remember that will be an UNSUPPORTED setup.\\nPlease reinstall your system with the 64 bit image of openHABian." 13 80
7979
return 255
8080
fi
8181

@@ -110,7 +110,7 @@ show_main_menu() {
110110
esac
111111

112112
elif [[ "$choice" == "20"* ]]; then
113-
choice2=$(whiptail --title "openHABian Configuration Tool — $(get_git_revision)" --menu "Optional Components" 24 118 16 --cancel-button Back --ok-button Execute \
113+
choice2=$(whiptail --title "openHABian Configuration Tool — $(get_git_revision)" --menu "Optional Components (scroll to see more)" 24 118 16 --cancel-button Back --ok-button Execute \
114114
"21 | Log Viewer" "[DEPRECATED] openHAB Log Viewer webapp (frontail)" \
115115
" | Add log to viewer" "[DEPRECATED] Add a custom log to openHAB Log Viewer (frontail)" \
116116
" | Remove log from viewer" "[DEPRECATED] Remove a custom log from openHAB Log Viewer (frontail)" \
@@ -133,6 +133,8 @@ show_main_menu() {
133133
" | Setup EVCC" "Setup EVCC from command line (German only)" \
134134
"2E | Install ESPHome dashboard" "Deploy ESPHome dashboard" \
135135
" | Remove ESPHome dashboard" "Uninstall ESPHome dashboard" \
136+
"2F | Install Grott" "Install Grott Proxy server (for Growatt binding)" \
137+
" | Remove Grott" "Uninstall Grott Proxy server (for Growatt binding)" \
136138
3>&1 1>&2 2>&3)
137139
RET=$?
138140
if [ $RET -eq 1 ] || [ $RET -eq 255 ]; then return 0; fi
@@ -160,6 +162,8 @@ show_main_menu() {
160162
*Setup\ EVCC*) setup_evcc;;
161163
2E\ *) install_esphomedashboard "install";;
162164
*Remove\ ESPHome\ dashboard*) install_esphomedashboard "remove";;
165+
2F\ *) install_grott "install";;
166+
*Remove\ Grott*) install_grott "remove";;
163167
"") return 0 ;;
164168
*) whiptail --msgbox "An unsupported option was selected (probably a programming error):\\n \"$choice2\"" 8 80 ;;
165169
esac
@@ -217,13 +221,13 @@ show_main_menu() {
217221
"42 | Remote Console" "Bind the openHAB SSH console to all external interfaces" \
218222
"43 | Clean cache" "Clean the cache for openHAB" \
219223
"44 | Nginx Proxy" "Setup reverse and forward web proxy" \
220-
"45 | OpenJDK 17" "Install + activate OpenJDK 17 as Java provider (default for OH versions 4 and older)" \
221-
" | OpenJDK 21" "Install + activate OpenJDK 21 as Java provider (DO NOT USE WILL BREAK SYSTEM)" \
222-
" | Temurin 17" "Install + activate Temurin 17 as Java provider (fallback for OH versions 4 and older)" \
223-
" | Temurin 21" "Install + activate Temurin 21 as Java provider (default)" \
224-
" | OpenJDK 11" "Install + activate OpenJDK 11 as Java provider (legacy)" \
225-
"46 | Install openhab-js" "JS Scripting: Upgrade to latest version of openHAB JavaScript library (advanced)" \
226-
" | Uninstall openhab-js" "JS Scripting: Switch back to included version of openHAB JavaScript library" \
224+
"45 | OpenJDK 17" "Setup OpenJDK 17 as Java provider (default for OH v4 and older)" \
225+
" | OpenJDK 21" "Setup OpenJDK 21 as Java provider (DO NOT USE WILL BREAK SYSTEM)" \
226+
" | Temurin 17" "Setup Temurin 17 as Java provider (fallback for OH v4 and older)" \
227+
" | Temurin 21" "Setup Temurin 21 as Java provider (default)" \
228+
" | OpenJDK 11" "Setup OpenJDK 11 as Java provider (legacy)" \
229+
"46 | Install openhab-js" "JS Scripting: Upgrade to latest version of JavaScript library (advanced)" \
230+
" | Uninstall openhab-js" "JS Scripting: Switch back to included version of JavaScript library" \
227231
"47 | Install openhab_rules_tools" "JS Scripting: Manually install openhab_rules_tools (auto-installed)" \
228232
" | Uninstall openhab_rules_tools" "JS Scripting: Uninstall openhab_rules_tools" \
229233
3>&1 1>&2 2>&3)

functions/packages.bash

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,3 +922,140 @@ install_esphomedashboard() {
922922
return
923923
fi
924924
}
925+
926+
## Function for (un)installing Grott proxy server on the current system
927+
## Valid arguments: "install" or "remove"
928+
##
929+
## install_grott(String install|remove)
930+
##
931+
install_grott() {
932+
echo "$(timestamp) [openHABian] Setup Grott proxy... "
933+
934+
# Skip setup if in un-attended mode and openhabian.config grottSetupEnabled is missing or not true
935+
if [[ -n "$UNATTENDED" ]] && [[ "$grottSetupEnabled" != "true" ]]; then
936+
echo "SKIPPED (setup not enabled)"
937+
return 0
938+
fi
939+
940+
# Validate install type argument
941+
if [ "$#" -lt 1 ]; then
942+
echo "FAILED (missing install type - usage: $0 <install|remove>)"
943+
return 1
944+
elif [[ "$1" != "install" && "$1" != "remove" ]]; then
945+
echo "FAILED (invalid install type $1 - usage: $0 <install|remove>)"
946+
return 1
947+
fi
948+
local installType="$1"
949+
950+
# Constants for local system
951+
local grottFolder="/home/${username:-openhabian}/grott"
952+
local iniName="grott.ini"
953+
local serviceName="grott.service"
954+
local iniFile="${grottFolder}/${iniName}"
955+
local serviceFile="/etc/systemd/system/${serviceName}"
956+
local iniTemplate="${BASEDIR:-/opt/openhabian}/includes/${iniName}"
957+
local serviceTemplate="${BASEDIR:-/opt/openhabian}/includes/${serviceName}"
958+
local runScript="grott.py"
959+
960+
# Constants for Grott GitHub files
961+
local grottSourceUrl="https://raw.githubusercontent.com/johanmeijer/grott/master"
962+
local grottSourceFiles=(
963+
"grott.py"
964+
"grottconf.py"
965+
"grottdata.py"
966+
"grottproxy.py"
967+
"grottserver.py"
968+
"grottsniffer.py"
969+
)
970+
local grottExtUrl="${grottSourceUrl}/examples/Extensions"
971+
local grottExtFile="grottext.py"
972+
973+
## Install Grott proxy
974+
if [[ $installType == "install" ]]; then
975+
echo "$(timestamp) [openHABian] Installing Grott proxy... "
976+
977+
# Get default IPv4 address
978+
local ipAddress
979+
ipAddress="$(ip route get 8.8.8.8 | awk '{print $7}' | xargs)"
980+
if ! [[ "$ipAddress" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
981+
echo "FAILED (invalid ip address ${ipAddress})"
982+
return 1
983+
fi
984+
local extUrl="http://${ipAddress}:8080/growatt"
985+
986+
# Update system and install dependencies. NOTE: paho-mqtt is a required dependency (even if disabled)
987+
if ! cond_redirect apt-get update; then echo "FAILED (apt update)"; return 1; fi
988+
if ! cond_redirect apt-get install --yes -o DPkg::Lock::Timeout="$APTTIMEOUT" python3 python3-pip python3-paho-mqtt python3-requests; then echo "FAILED (install Python or dependencies)"; return 1; fi
989+
990+
# Prepare Grott folder
991+
if ! cond_redirect mkdir -p "$grottFolder"; then echo "FAILED (create ${grottFolder})"; return 1; fi
992+
if ! cond_redirect chown -R "${username:-openhabian}" "$grottFolder"; then echo "FAILED (chown ${grottFolder})"; return 1; fi
993+
if ! cond_redirect chmod -R 755 "$grottFolder"; then echo "FAILED (chmod ${grottFolder})"; return 1; fi
994+
995+
# Download Grott Python files into Grott folder
996+
local src tgt
997+
for file in "${grottSourceFiles[@]}"; do
998+
src="${grottSourceUrl}/${file}"
999+
tgt="${grottFolder}/${file}"
1000+
curl -fsSL "${src}" -o "${tgt}" || {
1001+
echo "FAILED (download ${file})"
1002+
return 1
1003+
}
1004+
done
1005+
1006+
# Download Grott extension file into Grott folder
1007+
src="${grottExtUrl}/${grottExtFile}"
1008+
tgt="${grottFolder}/${grottExtFile}"
1009+
curl -fsSL "${src}" -o "${tgt}" || {
1010+
echo "FAILED (download ${grottExtFile})"
1011+
return 1
1012+
}
1013+
1014+
# Create grott.ini configuration in Grott folder by modifying the template
1015+
if ! sed \
1016+
-e "s|%URL|$extUrl|g" \
1017+
"$iniTemplate" > "$iniFile"; then
1018+
echo "FAILED (configure ${iniName})"
1019+
return 1
1020+
fi
1021+
1022+
# Create grott.service configuration in systemd folder by modifying the template
1023+
if ! sed \
1024+
-e "s|%USERNAME|${username:-openhabian}|g" \
1025+
-e "s|%DIRECTORY|$grottFolder|g" \
1026+
-e "s|%RUNSCRIPT|$runScript|g" \
1027+
"$serviceTemplate" > "$serviceFile"; then
1028+
echo "FAILED (configure ${serviceName})"
1029+
return 1
1030+
fi
1031+
1032+
# Enable and start Grott service
1033+
if ! cond_redirect systemctl enable --now "${serviceName}"; then echo "FAILED (enable ${serviceName})"; return 1; fi
1034+
1035+
if [[ -n "$INTERACTIVE" ]]; then
1036+
whiptail --title "Grott Proxy Installed" --msgbox "We installed Grott proxy on your system." 7 80
1037+
fi
1038+
fi
1039+
1040+
## Remove Grott proxy
1041+
if [[ $installType == "remove" ]]; then
1042+
echo "$(timestamp) [openHABian] Removing Grott Proxy... "
1043+
1044+
# Stop and disable systemd service
1045+
if ! cond_redirect systemctl disable --now "${serviceName}"; then echo "FAILED (disable ${serviceName})"; return 1; fi
1046+
cond_redirect systemctl daemon-reload
1047+
1048+
# Remove systemd service file
1049+
if ! cond_redirect rm -f "$serviceFile"; then echo "FAILED (remove ${serviceFile})"; return 1; fi
1050+
1051+
# Remove Grott folder
1052+
if ! cond_redirect rm -rf "$grottFolder"; then echo "FAILED (remove ${grottFolder})"; return 1; fi
1053+
1054+
if [[ -n "$INTERACTIVE" ]]; then
1055+
whiptail --title "Grott Proxy Removed" --msgbox "We removed Grott proxy from your system." 7 80
1056+
fi
1057+
fi
1058+
1059+
echo "OK"
1060+
return 0
1061+
}

functions/packages.bats

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ teardown_file() {
1111
unset BASEDIR
1212
systemctl kill homegear.service || true
1313
systemctl kill mosquitto.service || true
14+
systemctl kill grott.service || true
1415
}
1516

1617
@test "destructive-homegear_install" {
@@ -64,3 +65,19 @@ teardown_file() {
6465
[ "$status" -eq 0 ]
6566
echo -e "# ${COL_GREEN}$(timestamp) [openHABian] 1wire installation successful.${COL_DEF}" >&3
6667
}
68+
69+
@test "destructive-grott_install" {
70+
## Confirm Grott Proxy install completes without error
71+
echo -e "# ${COL_CYAN}$(timestamp) [openHABian] Grott Proxy installation starting...${COL_DEF}" >&3
72+
run install_grott "install" 3>&-
73+
if [ "$status" -ne 0 ]; then echo "$output" >&3; fi
74+
[ "$status" -eq 0 ]
75+
echo -e "# ${COL_GREEN}$(timestamp) [openHABian] Grott Proxy installation successful.${COL_DEF}" >&3
76+
77+
## Confirm Grott service is running
78+
echo -e "# ${COL_CYAN}$(timestamp) [openHABian] Checking if Grott Proxy service is running...${COL_DEF}" >&3
79+
run systemctl is-active --quiet grott
80+
if [ "$status" -ne 0 ]; then echo "$output" >&3; fi
81+
[ "$status" -eq 0 ]
82+
echo -e "# ${COL_GREEN}$(timestamp) [openHABian] Grott Proxy service is running.${COL_DEF}" >&3
83+
}

includes/grott.ini

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Specify grott monitor configuration
2+
# Defaults are described
3+
# Remove # and update the value to enable the setting
4+
# Last updated: 2022-11-04
5+
# Version 2.7.0
6+
7+
[Generic]
8+
# Specify verbose for extended messaging
9+
verbose = True
10+
11+
# Specify minrecl for debugging purposes only (default = 100)
12+
#minrecl = 100
13+
14+
# Specify mode (sniff or proxy)(> 2.1.0 proxy is default)
15+
mode = proxy
16+
17+
# Specify port and IP address to listen to (only proxy), default port 5279, 0.0.0.0 ==> own ip address
18+
ip = default
19+
port = 5279
20+
21+
# To blocks commands from outside (to channge inverter and shine devices settings) specify blockcmd = True,
22+
# Specify noipf = True if you still want be able to set the destination ip addres from growatt server (advice
23+
# only to use this for a short time)
24+
#blockcmd = True
25+
#noipf = True
26+
27+
# Time = auto/server parameter enable/disable date/time retrieval from data record (server), default is
28+
# auto: grott decides which time is used (data record if valid otherwise Server)
29+
# If time = server Grott server time is alwas used
30+
#time = auto
31+
32+
# Sendbuf = True / False parameter to enable / disable sending historical (buffered) data. Default is sendbuf = True.
33+
#sendbuf = True
34+
35+
# Compat is True and valoffset needs to be set if offset / growatt protocol has been changed.
36+
compat = False
37+
#valueoffset = 6
38+
39+
# Specify inverter id (not necessary in version >2.1.0 if compat = false!)
40+
#inverterid = KUM0CLU03Y
41+
# Specify the type of the inverter (default/sph/spf/max)
42+
invtype = sph
43+
44+
# Decrypt is False if growatt communication is not encrypted (older inverters), (not necessary in version
45+
# >2.1.0 if compat = false!)
46+
#decrypt = True
47+
48+
[Growatt]
49+
# Server name/IP address and port of Growatt server
50+
# specify only if the IP address of server.growatt.com is changed
51+
# The address as of Nov 2022 is 47.91.67.66
52+
53+
ip = server.growatt.com
54+
#ip = 47.91.67.66
55+
#port = 5279
56+
57+
[MQTT]
58+
# Mqtt parameters definitions
59+
# Be aware nomqtt = True means no MQTT processing will be done!!!!!!
60+
61+
nomqtt = True
62+
#ip = localhost
63+
#port = 1883
64+
#topic= energy/growatt
65+
#auth = False
66+
#user = grott
67+
#password = growatt2020
68+
69+
[PVOutput]
70+
# PVOutput parameters definitions
71+
72+
pvoutput = False
73+
#apikey = yourapikey
74+
# Data upload limit (in minutes)
75+
#pvuplimit = 5
76+
# Use this if you have one inverter
77+
#systemid = 12345
78+
79+
# Use this if you have multiple inverters
80+
#pvinverters = 2
81+
#systemid1 = 12345
82+
#inverterid1 = inverter1
83+
#systemid2 = 67890
84+
#inverterid2 = inverter2
85+
86+
#systemid99 = 99999
87+
#inverterid99 = inverter99
88+
89+
[influx]
90+
# Influxdb parameters definitions
91+
92+
#influx = False
93+
#influx2 = False
94+
#dbname = grottdb
95+
#ip = localhost
96+
#port = 8086
97+
#user = grott
98+
#password = growatt2020
99+
#token = "influx_token"
100+
#org = "grottorg"
101+
#bucket = "grottdb"
102+
103+
[extension]
104+
# grott extension parameters definitions
105+
extension = True
106+
extname = grottext
107+
extvar = {"url": "%URL"}

0 commit comments

Comments
 (0)