Wechselrichter Statistik mit einem Raspberry Pi (als AP und Webserver)

Der Raspberry Pi ist ein Einplatinencomputer der Raspberry Pi Foundation, der sich u.a. hervorragend für kleine Projekte eignet. In meinem Fall als Visualisierung der Daten eines PIKO-Wechselrichters.
Für den Raspberry Pi gibt es verschiedene Betriebssysteme. Mittels Noobs ist es sehr einfach möglich einige davon auf einer SD-Karte zu installieren. Fü Einsteiger dürfte Raspbian am einfachsten sein. Inzwischen ist Raspbian die einzige Version die Teil des Noobs-Downloads ist. Die anderen müssen nachträglich hinzukopiert werden. Bis Version 1.3.9 von Noobs waren diese noch direkt enthalten.
In meinem Fall ist Archlinux (ohne Noobs) zum Einsatz gekommen, da ich Archlinux bereits im Einsatz habe und das Erstellen einer aktuellen Version von hostapd für den Edimax Wifi-Stick mir am einfachsten erschien. Der Verzicht auf Noobs spart Platz auf der SD-Karte.

Ziele

  • Datensätze vom Wechselrichter abholen, in eine DB schreiben und eine Visualisierung verschiedener Statistiken der Daten mittels Weboberfläche anbieten.
  • Zwei Netzwerkschnittstellen: eine Ethernetverbindung zum Wechselrichter, eine Wifi-Verbindung als gesicherter Accesspoint eingerichtet
  • Beide Netze bleiben 'getrennt' und sind nicht mittels 'forwarding' verbunden.
  • Accesspoint ist nachts abgeschaltet.
  • Echtzeituhr und/oder Funkuhr zur Erhaltung der Uhrzeit bzw. Einstellen der Uhrzeit.
  • Monitoring verschiedener Systemdaten.
  • Zugriff auf Status-Seite des Wechselrichter mittels Proxy

Archlinux Installation

Um die SD-Karte (8 GB - 4GB sind aber für Archlinux ohne Noobs auch ok) zu partitionieren habe ich cfdisk verwendet und eine 100MB 'W95 FAT32 (LBA)' (Typ 'c') Partition und eine 'Linux' (Typ '83') Partition mit dem restlichen Platz angelegt.

Formatieren und Mounten der Partitionen:
$ mkfs.vfat /dev/sdX1
$ mkdir boot
$ mount /dev/sdX1 boot
$ mkfs.ext4 /dev/sdX2
$ mkdir root
$ mount /dev/sdX2 root
Download und 'Installation':
$ wget http://archlinuxarm.org/os/ArchLinuxARM-rpi-latest.tar.gz # Achtung Raspberry Pi 2 hat ein eigenes Image
$ bsdtar -xpf ArchLinuxARM-rpi-latest.tar.gz -C root
$ mv root/boot/* boot
$ umount boot root

Vorhandene Nutzer sind alarm und root mit jeweils gleichem Passwort wie der Benutzername. SSH ist bereits aktiv und eth0 verwendet DHCP.

$ timedatectl set-timezone Europe/Berlin
$ timedatectl set-local-rtc 0
$ hostnamectl set-hostname myhostname
Entferne '#' vor de_DE.UTF-8 in /etc/locale.gen
$ locale-gen
$ localectl set-locale LANG=de_DE.UTF-8
$ localectl set-keymap de-latin1

weitere Pakete

$ pacman -S vim mc htop lsof base-devel git abs dnsmasq apache php-apache php-sqlite awstats i2c-tools opensmtpd wiringpi

Accesspoint

Hostapd einrichten (aufgrund des Edimax WLAN-Sticks wird eine Variante mit AP Unterstützung für den passenden RTL-Chip gewählt):
$ mkdir -p /var/abs/local/hostapd-rtl871xdrv
$ chown alarm:users /var/abs/local/hostapd-rtl871xdrv
alarm $ cd /var/abs/local/hostapd-rtl871xdrv
alarm $ wget https://aur.archlinux.org/cgit/aur.git/snapshot/hostapd-rtl871xdrv.tar.gz
alarm $ tar -xzf hostapd-rtl871xdrv.tar.gz
alarm $ mv hostapd-rtl871xdrv/* .
alarm $ rmdir hostapd-rtl871xdrv
alarm $ makepkg
$ pacman -U /var/abs/local/hostapd-rtl871xdrv/hostapd-rtl871xdrv-<version>-<arch>.pkg.tar.xz
/etc/hostapd/hostapd.conf
interface=wlan0
driver=rtl871xdrv
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
ssid=RaspberryPi
country_code=DE
ieee80211d=1
hw_mode=g
channel=1
beacon_int=100
dtim_period=2
max_num_sta=255
rts_threshold=2347
fragm_threshold=2346
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wmm_enabled=1
wmm_ac_bk_cwmin=4
wmm_ac_bk_cwmax=10
wmm_ac_bk_aifs=7
wmm_ac_bk_txop_limit=0
wmm_ac_bk_acm=0
wmm_ac_be_aifs=3
wmm_ac_be_cwmin=4
wmm_ac_be_cwmax=10
wmm_ac_be_txop_limit=0
wmm_ac_be_acm=0
wmm_ac_vi_aifs=2
wmm_ac_vi_cwmin=3
wmm_ac_vi_cwmax=4
wmm_ac_vi_txop_limit=94
wmm_ac_vi_acm=0
wmm_ac_vo_aifs=2
wmm_ac_vo_cwmin=2
wmm_ac_vo_cwmax=3
wmm_ac_vo_txop_limit=47
wmm_ac_vo_acm=0
ieee80211n=1
eapol_key_index_workaround=0
own_ip_addr=127.0.0.1
wpa=2
wpa_passphrase=<dein_passwort>
wpa_key_mgmt=WPA-PSK
wpa_pairwise=CCMP
rsn_pairwise=CCMP
device_name=RTL8192CU
manufacturer=Realtek
/etc/dnsmasq.conf
address=/wechselrichter.deine.domain.home/192.168.1.1
interface=wlan0
no-dhcp-interface=eth0
domain=deine.domain.home
dhcp-range=192.168.1.100,192.168.1.150,255.255.255.0,2h
dhcp-option=3
/usr/lib/systemd/scripts/my-accesspoint:
#!/bin/bash

while getopts ":abc" opt; do
  case $opt in
    a)
      /usr/bin/ifconfig wlan0 192.168.1.1 netmask 255.255.255.0 up
      /usr/bin/systemctl start hostapd.service
      /usr/bin/systemctl start dnsmasq.service
      ;;
    b)
      /usr/bin/systemctl stop dnsmasq.service
      /usr/bin/systemctl stop hostapd.service
      /usr/bin/ifconfig wlan0 down
      ;;
    c)
      /usr/bin/systemctl status dnsmasq.service
      /usr/bin/systemctl status hostapd.service
      /usr/bin/ifconfig wlan0
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      echo "a - start"
      echo "b - stop"
      echo "c - status"
      ;;
  esac
done
/usr/lib/systemd/system/my-accesspoint-ip.service:
[Unit]
Description=Accesspoint IP Up
Before=hostapd.service

[Service]
Type=oneshot
ExecStart=/usr/bin/ifconfig wlan0 192.168.1.1 netmask 255.255.255.0 up

[Install]
WantedBy=multi-user.target
/usr/lib/systemd/system/my-accesspoint-up.service:
[Unit]
Description=Accesspoint Up
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/lib/systemd/scripts/my-accesspoint -a

[Install]
WantedBy=multi-user.target
/usr/lib/systemd/system/my-accesspoint-down.service:
[Unit]
Description=Accesspoint Down
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/lib/systemd/scripts/my-accesspoint -b

[Install]
WantedBy=multi-user.target
/usr/lib/systemd/system/my-accesspoint-up.timer:
[Unit]
Description=Accesspoint Up Timer
After=my-piface-rtc.service

[Timer]
# Time of day to run the unit
OnCalendar=08:30
# Service to start
Unit=my-accesspoint-up.service

[Install]
WantedBy=multi-user.target
/usr/lib/systemd/system/my-accesspoint-down.timer:
[Unit]
Description=Accesspoint Down Timer
After=my-piface-rtc.service

[Timer]
# Time of day to run the unit
OnCalendar=21:30
# Service to start
Unit=my-accesspoint-down.service

[Install]
WantedBy=multi-user.target
$ systemctl disable systemd-resolved
$ systemctl enable dnsmasq
$ systemctl enable hostapd
$ systemctl enable my-accesspoint-ip.service 
$ systemctl enable my-accesspoint-up.timer
$ systemctl enable my-accesspoint-down.timer

Webserver

Auszug aus /etc/http/conf/httpd.conf:
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
#LoadModule mpm_worker_module modules/mod_mpm_worker.so
LoadModule php7_module modules/libphp7.so
## Setze ServerAdmin und ServerName entsprechend
## Aktiviere combined logs und deaktiviere common logs
<IfModule php7_module>
Include conf/extra/php7_module.conf
</IfModule>
Auszug aus /etc/php/php.ini:
open_basedir = /srv/http/:/usr/share/pear/:/usr/share/fonts/
disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,system,exec,shell_exec,passthru,phpinfo,show_source,popen,proc_open
enable_dl = Off
file_uploads = Off
allow_url_fopen = Off
allow_url_include = Off
extension=calendar.so
extension=curl.so
extension=gettext.so
extension=iconv.so
extension=pdo_sqlite.so
extension=sqlite3.so
extension=zip.so
$ systemctl enable httpd

awstats

$ useradd -r -d /var/lib/awstats -g log -s /bin/bash awstats
$ chown awstats.log /var/lib/awstats
$ mkdir /srv/http/awstats
$ chown awstats.http /srv/http/awstats
Auszug aus /etc/awstats/awstats.www.conf:
LogFile="/var/log/httpd/access_log"
# Stelle sicher dass dein Webserver z.B. apache auch das Logformat 'combined' verwendet
LogFormat=1
# Setze SiteDomain und HostAliases entsprechend
/etc/logrotate.d/httpd:
/var/log/httpd/*log {
   missingok
   sharedscripts
   prerotate
      su - awstats -c '/usr/share/webapps/awstats/cgi-bin/awstats.pl -config=www -update > /dev/null'
      su - awstats -c '/usr/share/webapps/awstats/cgi-bin/awstats.pl -config=www -output -staticlinks > /srv/http/awstats/awstats.www.html 2> /dev/null'
   endscript
   postrotate
      /usr/bin/systemctl reload httpd.service 2>/dev/null || true
   endscript
}

System Monitoring

z.B. monitorix aus AUR installieren.

Uhrzeit

PiFace RTC

Folgende Zeile zu /boot/config.txt hinzufügen:
device_tree_param=i2c_arm=on
/etc/modules-load.d/piface-rtc.conf:
i2c-dev
i2c:mcp7941x
i2c-bcm2708
/usr/lib/systemd/scripts/my-piface-rtc:
#!/bin/bash

# setup rtc
echo mcp7941x 0x6f > /sys/class/i2c-dev/i2c-1/device/new_device
# set time from hwclock
hwclock -s
/usr/lib/sytemd/system/my-piface-rtc.service:
[Unit]
Description=Run /usr/lib/systemd/scripts/my-piface-rtc
After=systemd-modules-load.service

[Service]
Type=oneshot
#RemainAfterExit=yes
ExecStart=/usr/lib/systemd/scripts/my-piface-rtc

[Install]
WantedBy=multi-user.target
$ systemctl enable my-piface-rtc.service

NTP DCF

$ abs extra/ntp
$ chown -R alarm.users /var/abs/extra/ntp
Füge '--enable-RAWDCF' dem 'configure'-Aufruf hinzu.
alarm $ cd /var/abs/extra/ntp
alarm $ makepkg
$ pacman -U /var/abs/extra/ntp/ntp-<version>-<arch>.pkg.tar.xz
/etc/ntp.conf:
driftfile /var/lib/ntp/ntp.drift
logfile /var/log/ntpd
logconfig =all
statsdir /var/log/ntpstats/
statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable
restrict -4 default kod notrap nomodify nopeer noquery
restrict -6 default kod notrap nomodify nopeer noquery
restrict 127.0.0.1
restrict ::1
server 127.127.8.0 mode 5
$ timedatectl set-ntp 0
$ systemctl enable ntpd

SMTP

/etc/smtpd/smtpd.conf:
listen on lo port 25
accept for local deliver to mbox
$ systemctl enable smtpd

Webinterface

Abhängigkeiten: highcharts jquery jquery-ui-datepicker (php: sqlite3 curl)
 
© 2001 - 2017 Frank Remetter