owned this note
owned this note
Published
Linked with GitHub
# Remote Green house system
The project is about being able to manually control a green house remotely and more specifically a couple of plant watering valves and a couple of ventilation hatches. To support manual control, sensor data like temperature, humidity and weather forecast should be available. This is done via the course 1DT305 - Introduction to Applied IoT summer 2023 and student
# Author
Björn Siby
credentials is bs222vn
# Table of contents
- [Background](#Background)
- [Solution Overview](#Solution-Overview)
- [Connection](#Connection)
- [Hardware](#Hardware)
- [Schematics](#Schematics)
- [Wiring](#Wiring)
- [GPIO Mapping](#GPIO-mapping)
- [Software](#Software)
- [Setup](#Setup)
- [Procedure](#Procedure)
- [Tailscale](#Tailscale)
- [Enable Sensors](#Enable-Sensors)
- [Docker & Has](#Docker-and-HAS)
- [Enable IO in the Docker HAS container](#Enable-IO-in-the-Docker-HAS-container)
- [HAS integrations](#HAS-integrations)
- [HAS Dashboard](#HAS-Dashboard)
- [HAS Configuration](#HAS-Configuration)
- [HAS pyscript coding](#HAS-pyscript-coding)
- [Backup](#Backup)
- [Result and Demonstration](#Result-and-Demonstration)
- [Bonus](#Bonus)
- [SunGrow SG15rt](#SunGrow-SG15rt)
# Termonology
| Term | Verbose |
|----------------------------------------------|---------------------|
| HW | Hardware |
| RPI| Raspberry PI |
| SW |Software|
| IoT |Internet of things|
| HAS |Home assistant|
| GPIO |General Purpose Input Output|
| DNS |Domain Name System|
# Background
My mother and father in law have built a green house and would like to be able to remotly control the ventilation hatches and the water valves to activate irrigation of plants. Currently watering plants needs to be done every day so this will enable them to go away for shorter periods of time. I have mostly looked into Ardoino and Raspberry based cores and in the end I choose Raspberry. The main reason is the possibility to utilise a posix system which enables configuration, installation and programming remotely in real time via for example ssh.
Since I have previous experiance of setting up Home assistant, I think most time will go to harware assembly and specfic python coding, I estimate effort to be around 100 hours.
Video of the [green house](https://drive.google.com/file/d/1hDKk1syXcpkWav78L7RhmvITKJ5hofFQ/view?usp=sharing)




# Solution Overview

---
# Connection
I went for WLAN because of the bandwith and WLAN availability. The unit does also have grid power supply. The quality of the connection is not great but good enough to handle
* a few users via app/browser
* ssh connection from computer
* the home assitant webserver connection to other services
```
pi@raspberrypi:~ $ seq 5 | xargs -I{} cat /proc/net/wireless
Inter-| sta-| Quality | Discarded packets | Missed | WE
face | tus | link level noise | nwid crypt frag retry misc | beacon | 22
wlan0: 0000 23. -87. -256 0 0 0 61 0 0
Inter-| sta-| Quality | Discarded packets | Missed | WE
face | tus | link level noise | nwid crypt frag retry misc | beacon | 22
wlan0: 0000 23. -87. -256 0 0 0 61 0 0
Inter-| sta-| Quality | Discarded packets | Missed | WE
face | tus | link level noise | nwid crypt frag retry misc | beacon | 22
wlan0: 0000 23. -87. -256 0 0 0 61 0 0
Inter-| sta-| Quality | Discarded packets | Missed | WE
face | tus | link level noise | nwid crypt frag retry misc | beacon | 22
wlan0: 0000 23. -87. -256 0 0 0 61 0 0
Inter-| sta-| Quality | Discarded packets | Missed | WE
face | tus | link level noise | nwid crypt frag retry misc | beacon | 22
wlan0: 0000 23. -87. -256 0 0 0 61 0 0
```
# Hardware
| Part | Picture | Comment |
|----------------------------------------------|---------------------|----------------------|
| [Raspberry PI Zero W](https://www.raspberrypi.com/products/raspberry-pi-zero-w/) |  | Central computing and IO control ||
| [32 GB micro sdcard](https://www.teknikdelar.se/produkt/s-uhs-i-class-10?shopping_id_click=SDSQUA4-032G-GN6MN&gclid=Cj0KCQjwnf-kBhCnARIsAFlg491fGy8WYIwXSLQCKZIkMISZNY-zNzr4CC0ErTyH5yYVqrTmbFpI-n8aAu1YEALw_wcB) | | Software storage |
| [Pibow Zero W Case](https://www.adafruit.com/product/3471) |  | Reduce risk of damaging Hardware and more stylish |
| [Adafruit Perma Proto Bonnet Mini Kit](https://www.adafruit.com/product/3203) |  | Prototyp board used as connection board and a few soldered passive components |
| [AM2302/DHT22](https://www.adafruit.com/product/393) |  | Temperature and humidity sensor |
| [Sen-11050 Temperature Sensor](https://www.sparkfun.com/products/11050) |  | Waterprof temperature sensor, used for redundancy |
| 2 x [8 Channel 5V Relay Module](https://hitechchain.se/arduinokompatibel/relay-5v-8-channel-5v-relay-module-with-optocoupler-low-level-trigger-expansion-board-relay-for-arduino) |  | Relay board with isolation and protection of MCU pins |
| [Super Starter Kit for Raspberry Pi](https://hitechchain.se/raspberry-pi/super-starter-kit-for-raspberry-pi) |  | Start kit used for experimenting etc and wires used in final assembly ||
| [UPS HAT (C)](https://www.waveshare.com/wiki/UPS_HAT_(C)) |  | Backup energy if unit is disconnected from power supply and safe shutdown ||
| [DC-DC 12V to 5V Step Down Power Supply](https://www.ebay.co.uk/itm/193653785512) |  | Green house have 24v power supply, need to step down to supply RPI |
## Schematics
Schematic of controlling one dc motor which physically moves the hatch

* Init state and off state is illustrated
* Switching Relay 1 will spin motor in one direction, instead switching Relay 2 will spin motor in opposite direction, switching both will switch off energy to motor
Schematic of controlling one valve which enables water to pass pipe

## Wiring
Given the RPI Zero pinout

The Relayboard has a 10 pin array, where the first is GND and next 8 pins are digital relay switch signals and last is VCC

Adding the prototype board changes the RPI pinout to a long array, which simplifies wiring to the Relayboard

Solder Relay connectors to prototypeboard and also a header for connecting GND and 5v or 3v.
Connect Sen-11050 to GPIO pin 4
Connect DHT22 to GPIO 17
Connect all relay wires
Connect all GND
Connect all VCC

Connect wires to relayboard

UPS hat mounts under the RPI and connects with 6 Pogo pins to GNC, VCC and to two I2C serial interface pins

## GPIO mapping
| GPIO | Function |
|----------------------------------------------|---------------------|
| GPIO 0| Not made available on protoboard |
| GPIO 1| Not made available on protoboard |
| GPIO 2| UPS I2C |
| GPIO 3| UPS I2C |
| GPIO 4 |Sen-11050|
| GPIO 5| Spare Relay|
| GPIO 6| Spare Relay|
| GPIO 7 |Not made available on protoboard |
| GPIO 8| Not made available on protoboard |
| GPIO 9| Hatch 1 Close |
| GPIO 10 |Hatch 2 Close|
| GPIO 11| Hatch 1 Open |
| GPIO 12| Spare Relay |
| GPIO 13 |Spare Relay|
| GPIO 14| Not made available on protoboard |
| GPIO 15| Not made available on protoboard |
| GPIO 16 |Valve 4 Switch|
| GPIO 17| DHT22|
| GPIO 18| DHT22 VCC |
| GPIO 19 |Valve 3 Switch |
| GPIO 20| Valve 2 Switch|
| GPIO 21| Valve 1 Switch|
| GPIO 22 |Hatch 2 Close|
| GPIO 23| Hatch 3 Open |
| GPIO 24| Hatch 3 Close |
| GPIO 25 |Hatch 2 Open|
| GPIO 26 |Hatch 2 Open|
| GPIO 27 |Hatch 4 Close|
---
# Software
## Setup
* [Raspberry Pi OS Lite](https://www.raspberrypi.com/software/operating-systems/)
* The operating system
* [Auto reconnect to wifi](https://gist.github.com/carry0987/372b9fefdd8041d0374f4e08fbf052b1)
* Bash script to reconnect to wifi
* The WLAN is disconnected time to time
* [Docker](https://www.docker.com/)
* Containerize software
* enables upgrades, downgrades, test sandboxing
* [Home assistant](https://www.home-assistant.io/)
* Open-source homeautomation software platform
* It has a very active community, includes phone apps, webserver
* [Tailscale](https://tailscale.com/)
* Open-source peer-to-peer VPN
* simplifies remote connection, no need to add port forward rules in router etc
* [Idrive](https://www.idrive.com/)
* Cloud Backup, backups the RPI periodically every week
* I use Idrive for my everyday backup
* [Perl backup scripts](https://github.com/Taryck/idrive)
## Procedure
More or less all installation, configuration and coding of software has been done on target in real-time using either [VIM](https://www.vim.org/) and [Nano](https://www.nano-editor.org/). By connecting via ssh using tailscale from a PC via putty (windows) or bash (linux) or actually mobile phone using [Termius](https://termius.com/). This has allowed me to bassically being able to work on the solution whenever i have the possibility to do so.
The base is Raspberry PI OS Lite which is
* flashed via [etcher.io](https://etcher.balena.io/) on to the sdcard
* wifi configured
* add wpa_supplicant.conf to sdcard
* containing:
```
pi@raspberrypi:~ $ sudo cat /etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=SE
network={
ssid="YOUR-WIFI-SSID"
psk="YOUR-WIFI-PASSWORD"
scan_ssid=1
priority=1
}
```
* ssh enabled
* add ssh.txt to sdcard
* Mount the sdcard to the RPI HW
* Connect a keyboard and a screen
* Boot up RPI
* Go through installation process
* Setup user & password
### Tailscale
##### Reasoning
To simplify remote connection to the RPI a [Tailscale](https://tailscale.com/kb/1151/what-is-tailscale/) VPN network has been used.
It enables remote connection from an client on an external network connected to the tailscale network to services like ssh or http without adding router portforwarding rules
#### Commands
Download client to RPI
```
curl -fsSL https://tailscale.com/install.sh | sh
```
Connect RPI to VPN network and allow others to connect
```
sudo tailscale up
```
It is now possible to connect remotly via ssh, disconnect keyboard, screen and move the RPI to the assembly case within the green house
### Enable Sensors
#### Sen-11050
Enable 1-wire support on GPIO 4
```
sudo nano /boot/config.txt
# Enable 1-wire com on GPIO 4
dtoverlay=w1-gpio-pullup
```
To see all 1-wire devices
```
/sys/bus/w1/devices/
```
To get sensor data from a device
```
cat /sys/bus/w1/devices/YOUR-DEVICE-ID/w1_slave
```
Example
```
pi@raspberrypi:~ $ cat /sys/bus/w1/devices/28-00000c86aa3f/w1_slave
72 01 4b 46 7f ff 0e 10 57 : crc=57 YES
72 01 4b 46 7f ff 0e 10 57 t=23125
```
#### AM2303
[Adafruit](https://learn.adafruit.com/dht) have a extensive guide, but here are the few steps i used
Install python3
```
sudo apt install python3 idle3
```
Install python library
`sudo pip3 install Adafruit_DHT`
Test reading on GPIO 22
```
bash-5.1# python -c 'import Adafruit_DHT as dht;h, t = dht.read(dht.DHT22,17);print(f"{round(t,2)}");print(f"{round(h,2)}")'
21.8
99.9
```
#### Waveshare UPS I2C hat
[Waveshare](https://www.waveshare.com/wiki/UPS_HAT) have an extensive guide, but here are the steps I used.
Enable i2c
```
sudo raspi-config
```
Select Interfacing Options -> I2C ->yes to start the i2C kernel driver
```
sudo reboot
```
Check device availability
```
sudo apt-get install i2c-tools
sudo i2cdetect -y 1
```

Test device
```
sudo apt-get install p7zip
wget https://www.waveshare.com/w/upload/d/d9/UPS_HAT.7z
7zr x UPS_HAT.7z -r -o./UPS_HAT
cd UPS_HAT
python3 INA219.py
```
#### Docker and HAS
##### Reasoning
To simplify testing upgrades, downgrades, prototyping and backup recovery docker has been used. The downside is that HAS will not be executed in supervisor mode and Home assitant OS cannot be used. There are many discussions regarding this [subject](https://www.google.com/search?q=home+assistant+docker+downside). For my rather small project my choice became a container. In future if the project grows, i will most likely move the HAS platform to a different unit maybe a NUC or a RPI 4 and then refactor current unit to become a MQTT sensor and actuator
##### Commands
Get docker
```
curl -fsSL https://get.docker.com -o get-docker.sh
```
Add your user to the docker group to enable Home assistant to get 1-wire sensor data
`sudo usermod -aG docker $USER`
Home assistant is then installed and booted via an docker image
```
docker run -d -p 8123:8123 -v /home/pi/homeAssProd:/config --restart unless-stopped --privileged --name homeAssProd homeassistant/home-assistant
```
### Enable IO in the Docker HAS container
Get into Docker container command line
```
docker exec -it homeAssProd bash
```
Home assitant image is based on alpine so gcc needs to be installed
```
apk add build-base
```
Install dht22 python library
```
pip install Adafruit_DHT
```
Install RPI Zero GPIO mappings
```
pip install RPi.GPIO
```
Install i2c library for the ups
```
pip install smbus2
```
### HAS integrations
| Integration | Comment |Installation |
|----------------------------------------------|---------------------|---------------------|
|  | Needed by Sen-110501-Wire | Part of core platform so may be installed through HAS GUI |
| | Enables adding functionality to HAS by python code. Utilised to create services for hatches, valves and dht | Available through [HAS community store](https://hacs.xyz/) or manually by the [installation guide](https://hacs-pyscript.readthedocs.io/en/latest/installation.html#option-2-manual)
| [dht-sensor](https://github.com/richardzone/homeassistant-dht) |Needed by the DHT22 sensor, the dht-sensor integration is not part of core platform| Installed as [custom_component](https://community.home-assistant.io/t/dht-sensor-custom-components/390428)|
| [freeDNS](https://www.home-assistant.io/integrations/freedns/) | Used to update the DNS record for the green house external ip, father and mother in law do not use Tailscale but instead connects via the external ip which is now and then updated by the internet provider.| Part of the core integration but not via GUI: [guide](https://www.home-assistant.io/integrations/freedns/)
|  | The DNS IP integration will expose the external IP address| Part of the core integration and may be added by the [GUI](https://www.home-assistant.io/integrations/dnsip/)
### HAS Dashboard

#### HAS Configuration
```
cat homeAssProd/configuration.yaml
# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:
# Example configuration.yaml entry
logger:
default: warning
logs:
# log level for a custom component
custom_components.pyscript: info
# Update FreeDns dns record Example configuration.yaml entry
freedns:
url: http://sync.afraid.org/u/YOUR_TOKEN/
pyscript:
allow_all_imports: true
hass_is_global: true
# Text to speech
tts:
- platform: google_translate
group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
homeassistant:
allowlist_external_dirs:
- /config
sensor:
- platform: dht
sensor: DHT22
pin: 17
name: "AM2303"
scan_interval: 10
temperature_offset: 0.0
humidity_offset: 0.0
monitored_conditions:
- temperature
- humidity
- platform: onewire
names:
28-00000c86aa3f: SEN-11050
# To be able to monitor and log RPI temperature
- platform: command_line
name: "Raspberry Pi Temp"
command: "cat /sys/class/thermal/thermal_zone0/temp"
unit_of_measurement: "°C"
value_template: '{{ value | multiply(0.001) | round(1) }}'
# Removing incorrect sensor measures
- platform: filter
name: "filtered am2303 humidity"
entity_id: sensor.am2303_humidity
filters:
- filter: outlier
window_size: 10
radius: 5.0
# Removing incorrect sensor measures
- platform: filter
name: "filtered am2303 temperature"
entity_id: sensor.am2303_temperature
filters:
- filter: outlier
window_size: 10
radius: 5.0
# Monitor and log so that the has db size grow´s in a normal way
- platform: filesize
file_paths:
- /config/home-assistant_v2.db
scan_interval: 1800
# DNS IP Internet Status: ping host 8.8.8.8 with 2 packets every 600 seconds.
binary_sensor:
- platform: ping
host: 8.8.8.8
count: 2
scan_interval: 600
name: "Internet Connection"
# Calibrate the hatches, time to time do they become inconsistent, there is no sensor feedback on posistion
- platform: template
switches:
reset:
value_template: >
{% if is_state('switch.test','on') %}
false
{% endif %}
turn_on:
service: pyscript.hatch_reset
turn_off:
# Valve switches
- platform: template
switches:
valve1:
turn_on:
turn_off:
- platform: template
switches:
valve2:
turn_on:
turn_off:
- platform: template
switches:
valve3:
turn_on:
turn_off:
- platform: template
switches:
valve4:
turn_on:
turn_off:
- platform: template
switches:
fan:
turn_on:
turn_off:
- platform: template
switches:
am2303_supply:
turn_on:
turn_off:
# Hatch input_sliders in procentage of openess
input_number:
hatch1:
name: Hatch1
min: 0
max: 100
step: 10
mode: slider
unit_of_measurement: "%"
hatch2:
name: Hatch2
min: 0
max: 100
step: 10
mode: slider
unit_of_measurement: "%"
hatch3:
name: Hatch3
min: 0
max: 100
step: 10
mode: slider
unit_of_measurement: "%"
hatch4:
name: Hatch4
min: 0
max: 100
step: 10
f mode: slider
unit_of_measurement: "%"
```
### HAS pyscript coding
This code is placed in the pyscript directory and is included in the HAS platform. It is the worker code for opening, closing and calibrating the hatches and opening and closing the valves
```
import traceback
import RPi.GPIO as GPIO
from datetime import datetime, timedelta
import board
# GPIO mapping
ui_to_GPIO = {
"input_number.hatch1":(11,9),
"input_number.hatch2":(25,10),
"input_number.hatch3":(23,24),
"input_number.hatch4":(22,27)
}
valve_to_GPIO = [21,20,19,16]
# Movement constant
TIME_CONSTANT = 0.4
# Open Valve for 35 minutes
VALVE_SLEEP_CONSTANT = 60*35 # 60 sec × 35 min
@state_trigger("input_number.hatch1")
def ui_hatch1(**kwargs):
""" Triggered when a hatch 1 slider has changed its value"""
task.unique("ui_hatch1",kill_me=True)
hatch_change(kwargs['var_name'],kwargs['value'],kwargs['old_value'])
input_number.hatch1 = kwargs['value']
@state_trigger("input_number.hatch2")
def ui_hatch2(**kwargs):
""" Triggered when a hatch 2 slider has changed its value"""
task.unique("ui_hatch2",kill_me=True)
hatch_change(kwargs['var_name'],kwargs['value'],kwargs['old_value'])
input_number.hatch2 = kwargs['value']
@state_trigger("input_number.hatch3")
def ui_hatch3(**kwargs):
""" Triggered when a hatch 3 slider has changed its value"""
task.unique("ui_hatch3",kill_me=True)
hatch_change(kwargs['var_name'],kwargs['value'],kwargs['old_value'])
input_number.hatch3 = kwargs['value']
@state_trigger("input_number.hatch4")
def ui_hatch4(**kwargs):
""" Triggered when a hatch 4 slider has changed its value"""
task.unique("ui_hatch4",kill_me=True)
hatch_change(kwargs['var_name'],kwargs['value'],kwargs['old_value'])
input_number.hatch4 = kwargs['value']
def hatch_change(name=None, value=None, prev=None):
""" Calculate how much a hatch should move """
move_hatch(name,float(value)-float(prev))
@service
def move_hatch(id=None,value=None):
"""Move a hatch to procentage of open, Doing so by enable GPIO for a certain time. Only allow one movement at the time """
log.warning(f"move_hatch: id {id} value {value}")
if not hatch_moving(id):
if id in ui_to_GPIO:
if value < 0:
GPIO.output(ui_to_GPIO[id][0], GPIO.LOW)
task.sleep(abs(value) * TIME_CONSTANT)
GPIO.output(ui_to_GPIO[id][0], GPIO.HIGH)
else:
GPIO.output(ui_to_GPIO[id][1], GPIO.LOW)
task.sleep(abs(value) * TIME_CONSTANT)
GPIO.output(ui_to_GPIO[id][1], GPIO.HIGH)
@service
def hatch_init():
GPIO.setmode(GPIO.BCM)
for h in ui_to_GPIO.values():
GPIO.setup(h[0], GPIO.OUT)
GPIO.setup(h[1], GPIO.OUT)
GPIO.output(h[0], GPIO.HIGH)
GPIO.output(h[1], GPIO.HIGH)
# Check if any hatch is moving
def hatch_moving(id=None):
res = None
if id in ui_to_GPIO:
if (not GPIO.input(ui_to_GPIO[id][0])) or (not GPIO.input(ui_to_GPIO[id][1])):
res = True
else:
res = False
return res
@service
def hatch_reset():
"""Move all hatches to fully closed only if not already moving"""
anyMoving = False
for id in ui_to_GPIO.keys():
if hatch_moving(id):
log.warning(f"hatch_reset: id {id} moving")
anyMoving = True
if not anyMoving:
for id in ui_to_GPIO.values():
GPIO.output(id[0], GPIO.LOW)
task.sleep(abs(120) * TIME_CONSTANT)
for id in ui_to_GPIO.values():
GPIO.output(id[0], GPIO.HIGH)
input_number.hatch1 = "0"
input_number.hatch2 = "0"
input_number.hatch3 = "0"
input_number.hatch4 = "0"
@service
def valve_init():
GPIO.setmode(GPIO.BCM)
for p in valve_to_GPIO:
GPIO.setup(p, GPIO.OUT)
GPIO.output(p, GPIO.HIGH)
@service
def valve_service(valve=None, value=None):
log.warning(f"valve_service: {valve} {value}")
if int(valve) > 0 and int(valve) <= len(valve_to_GPIO):
if value == 'on':
log.warning(f"valve_service: {value}")
GPIO.output(valve_to_GPIO[int(valve)-1], GPIO.LOW)
task.sleep(VALVE_SLEEP_CONSTANT)
value='off'
if value == 'off':
GPIO.output(valve_to_GPIO[int(valve)-1], GPIO.HIGH)
log.warning(f"valve_service: {value}")
exec("%s = '%s'" %('switch.valve' + valve,'off'))
@state_trigger("switch.valve1 or switch.valve2 or switch.valve3 or switch.valve4")
def ui_valve(**kwargs):
log.warning(f"ui_valve: {kwargs['var_name']} old {kwargs['old_value']} new {kwargs['value']}")
valve_service(kwargs['var_name'][-1],kwargs['value'])
# Triggered when Home assistant initialises
@time_trigger
def startup_event():
hatch_init()
valve_init()
```
#### UPS
The UPS is used to supply the RPI with power even if main supply is disconnected. It will supply for an hour. Home assistant will ask the UPS for the charge precentage every 5 minute. If mean of five consecutive samples is below 40 will home assistant create a shutdown file and then call home assistant stop service to safely stop the instance. Following code:
Copy INA219.py to pyscript directory
```
cp UPS_HAT/INA219.py homeAssProd/pyscript
```
Replace smbus with smbus2
import os for the os.open function
Replace main function with
```
ina219 = INA219(addr=0x43)
q =queue.Queue(5)
@service
@time_trigger("period(now, 5m)")
def ups_precentage(**kwargs):
bus_voltage = ina219.getBusVoltage_V()
p = (bus_voltage - 3)/1.2*100
if(p > 100):p = 100
if(p < 0):p = 0
log.warning("ups_percentage: {:3.1f}%".format(p))
entity = "sensor.ups_precentage"
state.set(entity, float("{:3.1f}".format(p)), {"unit_of_measurement":"%"})
if q.full():
q.get()
log.warning(f"ups: {mean(list(q.queue))}")
if mean(list(q.queue)) < 40:
os.open("shutdown",os.O_WRONLY|os.O_CREAT)
homeassistant.stop()
q.put(p)
```
Set docker restart policy to no too finish the container if home assistant is stopped
```
docker update --restart no homeAssProd
```
Then schedule a cron job to check for the shutdown file and if it exist shutdown the rpi
```
FILE=/home/pi/homeAssProd/shutdown
if [ -f "$FILE" ]; then
echo "`date -Is` shutdown due to low battery" >> /home/pi/shutdown.txt
mv -f "$FILE" "$FILE".PREV
sudo shutdown now
fi
```
To get it back on track after a power shortage. Power on the RPI and restart the home assistant container
```
docker container restart homeAssProd
```
### Backup
As backup solution [Idrive](https://www.idrive.com/) is used, main reason is that i use idrive for all my cloud backup.
Everything under the user pi is backed up using the idrive [perl backup scripts](https://github.com/Taryck/idrive). It means that all the HAS configurations and custom_components code etc are backed up. But not the HAS container. Iam therefore exporting the container after big changes or upgrades.
```
docker export homeAssProd > HA.tar
```
It is scheduled to backup once every week but is triggered manually for bigger changes.
#### Procedure
Install git
```
sudo apt-get install git
```
Clone latest perl script base
```
git clone https://github.com/Taryck/idrive.git IDriveForLinux
```
Setup account on RPI
```
sudo ./account_settings.pl
```
Backup files to cloud
```
sudo ./Backup_Script.pl
```
Schedule backup automation
```
sudo ./scheduler.pl
```
# Result and Demonstration
Final assembly in the waterproof case
Assemblied Hardware except Valves and Hatches and wires to them

Video of [Irrigation](https://drive.google.com/file/d/1F8C2rLZ70Xyzq51tUXvh61jZLBuPde-M/view?usp=sharing) of plants
Video of Opening and Closing [hatches](https://drive.google.com/file/d/19fICo8tYLXeECnyuuU18EW9qhTh0-2mg/view?usp=sharing)
# Bonus
This section contains extra features which is implemented in the home assistant system but really in relation with the green house
## SunGrow SG15rt
My parents in law bought solar panels together with an SunGrow SG15rt inverter. So ofcourse did we want the Home assistant dashboard to include daily and total produced energy

To get this data into Home assistant i reused solutions provided by [bohdan](https://github.com/bohdan-s).
I used the SunGrowClient with http SunGrowModbusWebClient. I choosed not to use the SunGather application but instead created a pyscript periodic function which polls data every 30 minute from the inverter websocket.
Here are the steps i used to get it going.
login to docker container
```
docker exec -it homeAssProd bash
```
Install SunGrowClient
```
pip install SunGrowClient
```
added following code to sg15rt.py in the pyscript folder and a [registers](https://github.com/bohdan-s/SunGather/blob/main/SunGather/registers-sungrow.yaml) file containing all modbus sungrow registers
```
import sys
import yaml
import os
from SungrowClient.SungrowClient import SungrowClient
@time_trigger("period(now, 30m)")
def sg15rt_scrape():
filename = "pyscript/registers-sungrow.yaml"
reg_fd = os.open(filename,os.O_RDONLY)
r = os.read(reg_fd, os.stat(filename).st_size)
registersfile = yaml.safe_load(r.decode('utf-8'))
config_inverter = {
"host": "YOUR IP",
"connection": "http",
"level":1,
"slave":1,
"scan_interval":30
}
inverter = SungrowClient(config_inverter)
con = task.executor(inverter.checkConnection)
if not con:
return
con = task.executor(inverter.configure_registers,registersfile)
if not con:
return
inverter.checkConnection()
con = task.executor(inverter.scrape)
if con and hasattr(inverter,'latest_scrape') and "daily_power_yields" in inverter.latest_scrape.keys():
entity = "sensor.sg15rt_daily"
state.set(entity, float("{:3.1f}".format(d)), {"unit_of_measurement":"kWh"})
entity = "sensor.sg15rt_total"
t = inverter.latest_scrape["total_power_yields"]
state.set(entity, float("{:3.1f}".format(t)), {"unit_of_measurement":"kWh"})
```
and then finally add following to home assistant configuration.yaml
```
- platform: command_line
name: "sg15rt_daily"
unit_of_measurement: "kWh"
scan_interval: 3600
command: ""
- platform: command_line
name: "sg15rt_total"
unit_of_measurement: "kWh"
scan_interval: 3600
command: ""
```