#!/bin/sh
# Look for evidence of the DHW cylinder being at pasteurisation temperature.
# Provide Eddi 'all status' log on stdin, live or historic, one per line.
#
# Usage:
#      sh $0 < data/eddi/log/live/20??????.log
#
# or, for self test:
#      sh $0 -test
# 
# Pasteurised is implied by by a (single) log line where:
#   * eddi is on divert or boost ("sta" 3 or 4, eg not state 'stopped')
#   * to heater 1 ("hno" 1)
#   * and the DHW cylinder stops accepting energy ("div" 0).
# Also 1 has filled up and now diverting to 2:
#   * eddi is on divert or boost or stopped ("sta" 3 or 4 or 6)
#   * priority 1 but actually going to 2 ("hpri":1 and "hno":2)
# Also:
#   * 'everything is full' ("sta" 5) as backstop for a few successive polls.
#
# Can also check for a pending pasteurisation cycle ("hpri" 1).
#
# Returns non-empty output if DHW has likely hit pasteurisation temperature.
# 
# NOTE: MAY REQUIRE MORE THAN ONE LOG LINE / TIME SAMPLE
#
# Sample Eddi log lines at end.

if [ "-test" != "$1" ]; then
    # LOOK FOR SIGNS OF DHW CYLINDER UP TO TEMPERATURE
    # Yes, I am picking out JSON values with regexes.  Sue me.
    # Print out whole log line that indicated DHW hot.
    exec awk '
        /"sta":[34]/ && /"hno":1/ && /"div":0/ {print $0;exit}
        /"sta":[346]/ && /"hpri":1/ && /"hno":2/ {print $0;exit}
        /"sta":5/ {if(sta5count++>2){print $0;exit}next}
	{sta5count=0} # Reset count on non-full indication.
        '
else
    # SELF TEST
    #
    # Test cases:
    #  1) Does NOT detect full hot DHW for data/eddi/log/live/20241217.log
    #  2) Does detect full hot DHW for data/eddi/log/live/20250113.log
    #  3) Does detect full hot DHW for data/eddi/log/live/20250123.log
    #
    # Test data for relevant days is preserved here:
    TESTDATADIR=script/checkForDHWHot.testdata
    #
    # Days where the tank does NOT get hot enough to turn off the immersion.
    NOTHOT="20241217 20250224"
    # Days where the tank DOES get hot.
    HOT="20250113 20250123 20250303 20250319 20250330 20250331-part 20250401-part"

    for d in $NOTHOT;
        do
            f="$TESTDATADIR/$d.log"
            if [ ! -s "$f" ]; then echo "ERROR: missing $f" 1>&2; exit 1; fi
            OUT="$(sh "$0" < "$f")"
            if [ "" != "$OUT" ]; then
                echo "ERROR: wrongly said HOT on $d: $OUT" 1>&2
                exit 1
            fi
        done

    for d in $HOT;
        do
            f="$TESTDATADIR/$d.log"
            if [ ! -s "$f" ]; then echo "ERROR: missing $f" 1>&2; exit 1; fi
            if [ "" = "$(sh "$0" < "$f")" ]; then
                echo "ERROR: wrongly said NOT hot on $d" 1>&2
                exit 1
            fi
        done

    echo "INFO: self tests OK" 1>&2
    exit 0
fi


# Should not get here...
exit 1


# Sample Eddi log lines ('all status'):
#{"eddi":[{"deviceClass":"EDDI","sno":0,"dat":"23-01-2025","tim":"01:27:55","ectp1":1774,"ectp2":2014,"ectp3":31,"ectt1":"Internal Load","ectt2":"Grid","ectt3":"Monitor","bsm":1,"bst":0,"div":1774,"frq":50.06,"gen":0,"grd":2014,"pha":1,"pri":1,"sta":4,"tz":0,"vol":2415,"che":0,"isVHubEnabled":false,"hpri":1,"hno":1,"ht1":"Tank 1","ht2":"Tank 2","r1a":0,"r2a":0,"rbc":0,"rbt":550,"tp1":127,"tp2":127,"batteryDischargeEnabled":false,"g100LockoutState":"NONE","cmt":254,"fwv":"3200S3.048","newAppAvailable":false,"newBootloaderAvailable":false,"productCode":"3200"}]}
#{"eddi":[{"deviceClass":"EDDI","sno":0,"dat":"23-01-2025","tim":"01:37:55","ectp1":1784,"ectp2":2021,"ectp3":16,"ectt1":"Internal Load","ectt2":"Grid","ectt3":"Monitor","bsm":1,"bst":0,"div":1784,"frq":50.02,"gen":0,"grd":2025,"pha":1,"pri":1,"sta":4,"tz":0,"vol":2415,"che":0,"isVHubEnabled":false,"hpri":1,"hno":1,"ht1":"Tank 1","ht2":"Tank 2","r1a":0,"r2a":0,"rbc":0,"rbt":423,"tp1":127,"tp2":127,"batteryDischargeEnabled":false,"g100LockoutState":"NONE","cmt":254,"fwv":"3200S3.048","newAppAvailable":false,"newBootloaderAvailable":false,"productCode":"3200"}]}
#{"eddi":[{"deviceClass":"EDDI","sno":0,"dat":"23-01-2025","tim":"01:47:55","ectp1":0,"ectp2":119,"ectp3":16,"ectt1":"Internal Load","ectt2":"Grid","ectt3":"Monitor","bsm":1,"bst":0,"div":0,"frq":50.02,"gen":0,"grd":118,"pha":1,"pri":1,"sta":4,"tz":0,"vol":2415,"che":0,"isVHubEnabled":false,"hpri":1,"hno":1,"ht1":"Tank 1","ht2":"Tank 2","r1a":0,"r2a":0,"rbc":0,"rbt":551,"tp1":127,"tp2":127,"batteryDischargeEnabled":false,"g100LockoutState":"NONE","cmt":254,"fwv":"3200S3.048","newAppAvailable":false,"newBootloaderAvailable":false,"productCode":"3200"}]}
#{"eddi":[{"deviceClass":"EDDI","sno":0,"dat":"23-01-2025","tim":"01:57:56","ectp1":0,"ectp2":126,"ectp3":29,"ectt1":"Internal Load","ectt2":"Grid","ectt3":"Monitor","bsm":1,"bst":0,"div":0,"frq":49.98,"gen":0,"grd":142,"pha":1,"pri":1,"sta":4,"tz":0,"vol":2415,"che":0,"isVHubEnabled":false,"hpri":1,"hno":1,"ht1":"Tank 1","ht2":"Tank 2","r1a":0,"r2a":0,"rbc":0,"rbt":419,"tp1":127,"tp2":127,"batteryDischargeEnabled":false,"g100LockoutState":"NONE","cmt":253,"fwv":"3200S3.048","newAppAvailable":false,"newBootloaderAvailable":false,"productCode":"3200"}]}




##########
# May be used / adapted / etc without any promise of fitness for purpose
# under the terms of the Apache License Version 2.0, January 2004
#     http://www.apache.org/licenses/LICENSE-2.0
##########
