#!/bin/bash P1_STATUS=`mosquitto_sub -t domoctopus/p1/status -C 1` SB40_IP='192.168.1.126' SI60_IP='192.168.1.134' # test max amp at 25A, shouldn't be too limited, but it is easily reached MAX_AMP=30 #MAX_AMP=15 TIME=`date "+%s"` function modbus_read() { mbpoll $SI60_IP -a 3 -B -0 -r $1 -q -1 -c 1 -t 3:int | grep -e $1 | cut -f 2 } function modbus_read_fix() { TMP=`modbus_read $1` echo "scale=$2; $TMP/10^$2" | bc } . ./db.credentials #COMMAND=`./readcommand.sh` COMMAND=`mariadb -B --skip-column-names --user=$USERNAME --password=$PASSWORD stroom << EOQ SELECT IFNULL(GROUP_CONCAT(commands.command), 'IDLE') FROM commands AS next_commands JOIN commands ON next_commands.prev_command_id = commands.command_id WHERE commands.command_start <= $TIME AND next_commands.command_start > $TIME EOQ` if [ "$COMMAND" != "IDLE" -a "$COMMAND" != "CHARGE" -a "$COMMAND" != "DISCHARGE" -a "$COMMAND" != "ZERO" -a "$COMMAND" != "NODISC" -a "$COMMAND" != "NOCHRG" ]; then echo "command from DB is not recognized, should be IDLE, CHARGE, DISCHARGE, NODISC, NOCHRG or ZERO, but value from DB is $COMMAND" COMMAND="IDLE" fi if [ "$P1_STATUS" != "online" ]; then # no info from P1 # set machine to idle echo "P1 is down, set SI to IDLE" COMMAND="IDLE" fi SI_OPERSTATUS=`mbpoll 192.168.1.134 -a 3 -B -0 -r 40029 -q -1 -c 1 -t 3:int | grep -e 40029 | cut -f 2` if [ "x$SI_OPERSTATUS" = "x" ]; then echo "unable to read Operating Status, device offline" exit fi ## Reactive power L1 #SI60_VAR_L1=`modbus_read 30807` ## Power L1 #SI60_W_L1=`modbus_read 30777` #echo SI60 VAr L1 $SI60_VAR_L1 #echo SI60 W L1 $SI60_W_L1 echo "command" $COMMAND SMA_ENERGY_METER=`./sma-em01-production --oneshot` if [ "$?" = "1" ]; then echo error reading from SMA ENERGY METER, switch CHARGE and DISCHARGE to IDLE if [ "$COMMAND" = "DISCHARGE" -o "$COMMAND" = "CHARGE" ]; then COMMAND="IDLE" fi fi L1_CURRENT=`echo $SMA_ENERGY_METER | jq .l1_current` L1_VOLTAGE=`echo $SMA_ENERGY_METER | jq .l1_voltage` L1_ACTIVE_POWER_IN=`echo $SMA_ENERGY_METER | jq .l1_active_power_in | cut -f 1 -d .` L1_ACTIVE_POWER_OUT=`echo $SMA_ENERGY_METER | jq .l1_active_power_out | cut -f 1 -d .` L1_ACTIVE_POWER=$(($L1_ACTIVE_POWER_IN - $L1_ACTIVE_POWER_OUT)) echo L1 Grid active power to hub $L1_ACTIVE_POWER W echo L1 Grid voltage/current $L1_VOLTAGE V / $L1_CURRENT A L1_REACTIVE_POWER_IN=`echo $SMA_ENERGY_METER | jq .l1_reactive_power_in | cut -f 1 -d .` L1_REACTIVE_POWER_OUT=`echo $SMA_ENERGY_METER | jq .l1_reactive_power_out | cut -f 1 -d .` L1_REACTIVE_POWER=$(($L1_REACTIVE_POWER_IN - $L1_REACTIVE_POWER_OUT)) L1_APPARENT_POWER=`echo "scale=0; sqrt(($L1_ACTIVE_POWER)^2+($L1_REACTIVE_POWER)^2)" | bc` L1_MAX_APPARENT_POWER=`echo "scale=0; $L1_VOLTAGE*$MAX_AMP" | bc` L1_MAX_ACTIVE_POWER=`echo "scale=0; sqrt($L1_MAX_APPARENT_POWER^2 - ($L1_REACTIVE_POWER)^2)" | bc | cut -f 1 -d .` L1_SI60_ACTIVE_POWER=`modbus_read 31419` # combine data from SI60 and Grid L1_LOADS_AND_SOLAR_ACTIVE_POWER_FROM_HUB=$(($L1_ACTIVE_POWER-$L1_SI60_ACTIVE_POWER)) # compute max charge active power and max discharge active power L1_SI60_MAX_ACTIVE_POWER_FROM_HUB=$(($L1_MAX_ACTIVE_POWER-$L1_LOADS_AND_SOLAR_ACTIVE_POWER_FROM_HUB)) L1_SI60_MAX_ACTIVE_POWER_TO_HUB=$(($L1_MAX_ACTIVE_POWER+$L1_LOADS_AND_SOLAR_ACTIVE_POWER_FROM_HUB)) MAX_CHARGE=$L1_SI60_MAX_ACTIVE_POWER_FROM_HUB MAX_DISCHARGE=$L1_SI60_MAX_ACTIVE_POWER_TO_HUB echo L1 Grid max active power to/from hub $L1_MAX_ACTIVE_POWER W echo L1 loads and solar active power from hub $L1_LOADS_AND_SOLAR_ACTIVE_POWER_FROM_HUB W echo L1 SI60 active power from hub $L1_SI60_ACTIVE_POWER W echo L1 SI60 max active power from hub $L1_SI60_MAX_ACTIVE_POWER_FROM_HUB W echo L1 SI60 max active power to hub $L1_SI60_MAX_ACTIVE_POWER_TO_HUB W SI_BATVOLT=`mbpoll 192.168.1.134 -a 3 -B -0 -r 30851 -q -1 -c 1 -t 3:int | grep -e 30851 | cut -f 2` SI_BATCURR=`mbpoll 192.168.1.134 -a 3 -B -0 -r 30843 -q -1 -c 1 -t 3:int | grep -e 30843 | cut -f 2` AHIN=`mbpoll 192.168.1.134 -a 3 -B -0 -r 30567 -q -1 -c 1 -t 3:int | grep -e 30567 | cut -f 2` AHOUT=`mbpoll 192.168.1.134 -a 3 -B -0 -r 30569 -q -1 -c 1 -t 3:int | grep -e 30569 | cut -f 2` TOTALVOLT=`echo "scale=2; $SI_BATVOLT/100" | bc` VOLTPERCELL=`echo "scale=2; $SI_BATVOLT/1600" | bc` TOTALCURR=`echo "scale=3; $SI_BATCURR/1000" | bc` echo SI battery charge in/out $AHIN/$AHOUT Ah echo SI battery voltage $TOTALVOLT V \($VOLTPERCELL V\) echo SI battery current $TOTALCURR A SI_POWER2=`mbpoll 192.168.1.134 -a 3 -B -0 -r 30777 -q -1 -c 1 -t 4:int | grep -e 30777 | cut -f 2` #SI_POWER2=`modbus_read 30777` SI_CONDITION=`mbpoll 192.168.1.134 -a 3 -B -0 -r 30201 -q -1 -c 1 -t 3:int | grep -e 30201 | cut -f 2` SI_GRID_STATUS=`mbpoll 192.168.1.134 -a 3 -B -0 -r 30883 -q -1 -c 1 -t 3:int | grep -e 30883 | cut -f 2` case $SI_CONDITION in 35) echo SI Condition Fault ;; 303) echo SI Condition Off ;; 307) echo SI Condition OK ;; 455) echo SI Condition Warning ;; *) echo SI Condition $SI_CONDITION \(unknown code\) ;; esac case $SI_OPERSTATUS in 303) echo SI Operating Status OFF ;; 569) echo SI Operating Status Activated ;; 1295) echo SI Operating Status Standby ;; 1795) echo SI Operating Status Bolted ;; 16777213) echo SI Operating Status NaNStt ;; *) echo SI Operating Status $SI_OPERSTATUS \(unknown code\) ;; esac case $SI_GRID_STATUS in 35) echo SI Grid Status Fault \(Alm\) ;; 303) echo SI Grid Status Off ;; 1394) echo SI Grid Status Waiting for valid AC grid ;; 1787) echo SI Grid Status Initialization ;; 2183) echo SI Grid Status Mains oper. without feed back ;; 2184) echo SI Grid Status Energy saving in the network ;; 2185) echo SI Grid Status End energy saving in the network ;; 2186) echo SI Grid Status Start energy saving in the network ;; 1466) echo SI Grid Status About to enable Grid connection ;; 3068) echo SI Grid Status Mains operation with feedback ;; 16777213) echo SI Grid Status Information not available ;; *) echo SI Grid Status $SI_GRID_STATUS \(unknown code\) ;; esac #echo "SI power in" $SI_POWER_IN #echo "SI power out" $SI_POWER_OUT # negative means we are exporting power to the grid # positive means we are taking power from the grid #P1_POWER=$(($P1_POWER_IN - $P1_POWER_OUT)) # negative means we are exporting power to the grid # positive means we are taking power from the grid #SI_POWER=$(($SI_POWER_IN - $SI_POWER_OUT)) SI_POWER=$(($L1_ACTIVE_POWER_IN - $L1_ACTIVE_POWER_OUT)) # positive is from grid, negative is to grid #echo "P1 power" $P1_POWER # positive is from SI, negative is to SI # SI60 has a max power of 4600W MAX_POWER=4600 case $COMMAND in IDLE) SI_POWER_REQ=0 ;; CHARGE) if [ "$MAX_CHARGE" -le 0 ]; then echo "cant charge, no amps available at grid" COMMAND="IDLE" elif [ "-$MAX_POWER" -lt "-$MAX_CHARGE" ]; then echo "LIMITING CHARGING DUE TO MAX AMP AT GRID" SI_POWER_REQ=-$MAX_CHARGE else SI_POWER_REQ=-$MAX_POWER fi ;; DISCHARGE) if [ "$MAX_DISCHARGE" -le 0 ]; then echo "cant discharge, no amps available at grid" COMMAND="IDLE" elif [ "$MAX_POWER" -gt "$MAX_DISCHARGE" ]; then echo "LIMITING DISCHARGING DUE TO MAX AMP AT GRID" SI_POWER_REQ=-$MAX_CHARGE else SI_POWER_REQ=$MAX_POWER fi ;; ZERO) SI_POWER_REQ=$(($SI_POWER+$SI_POWER2)) ;; NOCHRG) SI_POWER_REQ=$(($SI_POWER+$SI_POWER2)) if [ "$SI_POWER_REQ" -le 0 ]; then # charge is requested, we don't do that, so switch to idle COMMAND="IDLE" fi #MAXCHRG=0 ;; NODISC) SI_POWER_REQ=$(($SI_POWER+$SI_POWER2)) if [ "$SI_POWER_REQ" -ge 0 ]; then # discharge is requested, we don't do that, so switch to idle COMMAND="IDLE" fi #MAXDISC=0 ;; *) echo "IMPOSSIBLE -> IDLE" COMMAND="IDLE" SI_POWER_REQ=0 esac echo Computed Active power setpoint $SI_POWER_REQ W BAT_PERC=`mbpoll 192.168.1.134 -a 3 -B -0 -r 30845 -q -1 -c 1 -t 3:int | grep -e 30845 | cut -f 2` echo "Battery SoC" $BAT_PERC % #if [ "$SI_POWER_REQ" -lt 0 -a "$BAT_PERC" -gt 99 ]; then # echo "battery full, do not charge" # SI_POWER_REQ=0 #fi if [ "x$COMMAND" != "xIDLE" -a "$SI_POWER_REQ" -ge 0 -a "$BAT_PERC" -le 11 ]; then # inverter will misbehave when percentage is too low echo "battery low, do not discharge, we set the command to IDLE" COMMAND="IDLE" fi if [ "$SI_POWER_REQ" -ge 0 -a "$SI_BATVOLT" -le "4480" ]; then echo "battery voltage low. force idle" COMMAND="IDLE" fi if [ "x$COMMAND" = "xIDLE" ]; then #mbpoll 192.168.1.134 -a 3 -B -0 -r 40805 -q -t 4:int 303 > /dev/null #mbpoll 192.168.1.134 -a 3 -B -0 -r 40149 -q -t 4:int -- $SI_POWER_REQ > /dev/null #mbpoll 192.168.1.134 -a 3 -B -0 -r 40151 -q -t 4:int 802 > /dev/null mbpoll 192.168.1.134 -a 3 -B -0 -r 40805 -q -t 4:int 308 > /dev/null else mbpoll 192.168.1.134 -a 3 -B -0 -r 40805 -q -t 4:int 303 > /dev/null fi if [ "x$COMMAND" = "xZERO" -o "x$COMMAND" = "xNODISC" -o "x$COMMAND" = "xNOCHRG" ]; then #mbpoll 192.168.1.134 -a 3 -B -0 -r 40795 -q -t 4:int $MAXCHRG > /dev/null #mbpoll 192.168.1.134 -a 3 -B -0 -r 40799 -q -t 4:int $MAXDISC > /dev/null mbpoll 192.168.1.134 -a 3 -B -0 -r 40151 -q -t 4:int 803 > /dev/null mosquitto_pub -t si60h/command -m ZERO else #echo "setpoint comm. $SI_POWER_REQ" mbpoll 192.168.1.134 -a 3 -B -0 -r 40149 -q -t 4:int -- $SI_POWER_REQ > /dev/null mbpoll 192.168.1.134 -a 3 -B -0 -r 40151 -q -t 4:int 802 > /dev/null mosquitto_pub -t si60h/command -m $COMMAND fi echo "---------" mariadb -B --skip-column-names --user=$USERNAME --password=$PASSWORD stroom << EOQ INSERT INTO batstats ( batstat_timestamp, batstat_operstat, batstat_voltage, batstat_current, batstat_command, batstat_parameter, batstat_ahin, batstat_ahout ) VALUES ( $TIME, $SI_OPERSTATUS, $TOTALVOLT, $TOTALCURR, '$COMMAND', $SI_POWER_REQ, $AHIN, $AHOUT ) EOQ