houseenergy Annoyng bug: negative numbers

Talks about metering
jeanmarc
Posts: 1600
Joined: Thu Aug 29, 2013 7:16 am

Re: Annoyng bug: negative numbers

Post by jeanmarc » Thu Jan 07, 2016 2:34 pm

I believe the time check is useless. Let's try this one :

Code: Select all

#!/usr/bin/php
<?php
// A virtual meters example. This script will simulate a house consumption and selfconsumuption meter. You must own a total (import/export) and a production meter.
// ln -s /srv/http/comapps/houseenergy.php /usr/bin/houseenergy
// houseenergy [ power | energy | self ]
//
if (isset($_SERVER['REMOTE_ADDR'])) {
    die('Direct access not permitted');
}
$MEMORY = 624;

// Set the new virtual meters
// Consumption
$HOUSEID     = 'elect'; // ID
$HOUSEmetnum = 1; // meter number
// Selfconsumption
$SELFID      = 'self';
$SELFCmetnum = 7;

// Set up real meters
// Production
$PRODID       = 'solar'; // ID
$PRODcmd      = 'pool123s energy'; // Energy command
$POWERPRODcmd = 'pool123s power'; // Power
$PRODmetnum   = 4; // meter number
// TOT
$TPID         = '1_P';
//$TOTPOWERcmd  = 'reqsdm TOT'; // return the total power (eg if import = 45W, export -55W)
$TOTPOWERcmd  = 'sdm120cdrk -a1 -b9600 -2 -m -p /dev/sdm';
// Energy Imported
$IMPID        = '1_IE';
//$IMPcmd    = 'reqsdm EIMP';
$IMPcmd       = 'sdm120cdrk -a1 -b9600 -2 -m -i /dev/sdm ';
$IMPmetnum    = 5;
// Energy Exported
$EXPID        = '1_EE';
//$EXPcmd    = 'reqsdm EEXP';
$EXPcmd       = 'sdm120cdrk -a1 -b9600 -2 -m -e /dev/sdm ';
$EXPmetnum    = 6;

// Path to metern
$MNDIR = '/srv/http/metern';

// No edit should be needed bellow
function isvalid($id, $datareturn) //  IEC 62056 data set structure
{
    $regexp = "/^$id\(-?[0-9\.]+\*[A-z0-9³²%°]+\)$/i"; //ID(VALUE*UNIT)
    if (preg_match($regexp, $datareturn)) {
        $datareturn = preg_replace("/^$id\(/i", '', $datareturn, 1); // VALUE*UNIT)
        $datareturn = preg_replace("/\*[A-z0-9³²%°]+\)$/i", '', $datareturn, 1); // VALUE
        settype($datareturn, 'int');
    } else {
        $datareturn = null;
    }
    return $datareturn;
}

function retrievecsv($meternum, $csvarray, $passo, $datareturn) // Retrieve last know value in csv
{
    $datareturn = null;
    $contalines = count($csvarray);
    $j          = 0;
    while (!isset($datareturn)) {
        $j++;
        $array      = preg_split('/,/', $csvarray[$contalines - $j]);
        $datareturn = trim($array[$meternum]);
        if ($datareturn == '') {
            $datareturn = null;
        }
        if ($j == $contalines) {
            $datareturn = 0;
        }
    }
    if ($datareturn > $passo) {
        $datareturn -= $passo;
    }
    return $datareturn;
}

if (isset($argv[1])) {
    if ($argv[1] == 'power') {
        $datareturn = exec($TOTPOWERcmd);
        $datareturn = trim($datareturn);
        $totpower   = isvalid($TPID, $datareturn);
        
        $datareturn = exec($POWERPRODcmd);
        $datareturn = trim($datareturn);
        $prodpower  = isvalid($PRODID, $datareturn);
        
        if (isset($totpower) && isset($prodpower)) {
            $power = $prodpower + $totpower;
        } else {
            $power = 0;
        }
        $outstr = utf8_decode("$HOUSEID($power*W)\n");
        echo "$outstr";
    } elseif ($argv[1] == 'energy' || $argv[1] == 'self') {
        define('checkaccess', TRUE);
        include("$MNDIR/config/config_main.php");
        
        include("$MNDIR/config/config_met$HOUSEmetnum.php");
        include("$MNDIR/config/config_met$SELFCmetnum.php");
        include("$MNDIR/config/config_met$IMPmetnum.php");
        include("$MNDIR/config/config_met$EXPmetnum.php");
        include("$MNDIR/config/config_met$PRODmetnum.php");
        
        ///// open shm memory
        @$shmid = shmop_open($MEMORY, 'a', 0, 0);
        if (!empty($shmid)) {
            $size = shmop_size($shmid);
            shmop_close($shmid);
            
            $shmid        = shmop_open($MEMORY, 'c', 0666, $size);
            $memarraydata = shmop_read($shmid, 0, $size);
            shmop_close($shmid);
            $memarray = json_decode($memarraydata, true);
        }
        
        if (!isset($memarray['prevHOUSE']) || !isset($memarray['prevSELF'])) { // At boot retrieve values in last csv
            $output = array();
            $output = glob($MNDIR . '/data/csv/*.csv');
            sort($output);
            $cnt = count($output);
            
            $lines = file($output[$cnt - 1]); // should be today
            if ($cnt > 0) {
                $contalines = count($lines);
                $lastarray  = preg_split("/,/", $lines[$contalines - 1]);
                
                $datareturn                = null;
                $memarray['prevIMPhouse']  = retrievecsv($IMPmetnum, $lines, ${'PASSO' . $IMPmetnum}, $datareturn);
                $datareturn                = null;
                $memarray['prevEXPhouse']  = retrievecsv($EXPmetnum, $lines, ${'PASSO' . $EXPmetnum}, $datareturn);
                $memarray['prevEXPself']   = $memarray['prevEXPhouse'];
                $datareturn                = null;
                $memarray['prevHOUSE']     = retrievecsv($HOUSEmetnum, $lines, ${'PASSO' . $HOUSEmetnum}, $datareturn);
                $datareturn                = null;
                $memarray['prevSELF']      = retrievecsv($SELFCmetnum, $lines, ${'PASSO' . $SELFCmetnum}, $datareturn);
                $datareturn                = null;
                $memarray['prevPRODhouse'] = retrievecsv($PRODmetnum, $lines, ${'PASSO' . $PRODmetnum}, $datareturn);
                $memarray['prevPRODself']  = $memarray['prevPRODhouse'];
            } else { // no csv
                $memarray['prevIMPhouse']  = 0;
                $memarray['prevEXPhouse']  = 0;
                $memarray['prevEXPself']   = 0;
                $memarray['prevHOUSE']     = 0;
                $memarray['prevSELF']      = 0;
                $memarray['prevPRODhouse'] = 0;
                $memarray['prevPRODself']  = 0;
            }
        }
        
        // Now retrieve latest values
        $datareturn = null;
        $import     = null;
        $export     = null;
        $production = null;
        $outstr     = null;
        // latest import
        if ($argv[1] == 'energy') {
            exec($IMPcmd, $datareturn);
            $datareturn = trim(implode($datareturn));
            $import     = isvalid($IMPID, $datareturn);
        }
        // latest export
        $datareturn = null;
        exec($EXPcmd, $datareturn);
        $datareturn = trim(implode($datareturn));
        $export     = isvalid($EXPID, $datareturn);
        
        // latest production
        $datareturn = null;
        exec($PRODcmd, $datareturn);
        $datareturn = trim(implode($datareturn));
        $production = isvalid($PRODID, $datareturn);
        
        // energy
        if ($argv[1] == 'energy') {
            if (isset($import) && isset($export)) {
                // Some passover checks
                if ($export >= $memarray['prevEXPhouse']) {
                    $diffEXP = $export - $memarray['prevEXPhouse'];
                } else {
                    $diffEXP = $export + ${'PASSO' . $EXPmetnum} - $memarray['prevEXPhouse'];
                }
                if (isset($production)) {
                    if ($production >= $memarray['prevPRODhouse']) {
                        $diffPROD = $production - $memarray['prevPRODhouse'];
                    } else {
                        $diffPROD = $production + ${'PASSO' . $PRODmetnum} - $memarray['prevPRODhouse'];
                    }
                    settype($memarray['prevPRODhouse'], 'int');
                    $memarray['prevPRODhouse'] = $production;
                } else { // no production case
                    $diffPROD = 0;
                    $diffEXP  = 0;
                }
                if ($import >= $memarray['prevIMPhouse']) {
                    $diffIMP = $import - $memarray['prevIMPhouse'];
                } else {
                    $diffIMP = $import + ${'PASSO' . $IMPmetnum} - $memarray['prevIMPhouse'];
                }
                $difference = $diffIMP + $diffPROD - $diffEXP;
            } else { // no import/export values
                $difference = 0;
            }
            
            //  bug
            if ($difference < 0) {
	        date_default_timezone_set($DTZ);
                $a   = $memarray['prevHOUSE'];
                $b   = $memarray['prevEXPhouse'];
                $c   = $memarray['prevPRODhouse'];
                $d   = $memarray['prevIMPhouse'];
                $dt  = date('Ymd H:i:s');
                $tut = "$dt \t diff $difference \n prevHOUSE $a\n export: $export $b\n prod: $production $c\n import: $import $d\n";
                exec("echo '$tut' >> /srv/http/comapps/housebug.txt");
                
                $difference = 0; // correction
            }
            
            $memarray['prevHOUSE'] += $difference;
            
            if ($memarray['prevHOUSE'] >= ${'PASSO' . $HOUSEmetnum}) { // passed over
                $memarray['prevHOUSE'] -= ${'PASSO' . $HOUSEmetnum};
            }
            $val    = $memarray['prevHOUSE'];
            $outstr = utf8_decode("$HOUSEID($val*Wh)\n");
            
            settype($memarray['prevIMPhouse'], 'int');
            $memarray['prevIMPhouse'] = $import;
            settype($memarray['prevEXPhouse'], 'int');
            $memarray['prevEXPhouse'] = $export;
            settype($memarray['prevHOUSE'], 'int');
        } else { // Self 
            if (isset($export)) {
                // Some passover checks
                if ($export >= $memarray['prevEXPself']) {
                    $diffEXP = $export - $memarray['prevEXPself'];
                } else {
                    $diffEXP = $export + ${'PASSO' . $EXPmetnum} - $memarray['prevEXPself'];
                }
                if (isset($production)) {
                    if ($production >= $memarray['prevPRODself']) {
                        $diffPROD = $production - $memarray['prevPRODself'];
                    } else {
                        $diffPROD = $production + ${'PASSO' . $PRODmetnum} - $memarray['prevPRODself'];
                    }
                    settype($memarray['prevPRODself'], 'int');
                    $memarray['prevPRODself'] = $production;
                } else { // no production case
                    $diffPROD = 0;
                    $diffEXP  = 0;
                }
                $difference = $diffPROD - $diffEXP;
            } else { // no export values
                $difference = 0;
            }
            
            $memarray['prevSELF'] += $difference;
            if ($memarray['prevSELF'] >= ${'PASSO' . $SELFCmetnum}) {
                $memarray['prevSELF'] -= ${'PASSO' . $SELFCmetnum};
            }
            $val    = $memarray['prevSELF'];
            $outstr = utf8_decode("$SELFID($val*Wh)\n");
            
            settype($memarray['prevEXPself'], 'int');
            $memarray['prevEXPself'] = $export;
            settype($memarray['prevSELF'], 'int');
        }
        
        ///// save shm memory
        $data = json_encode($memarray);
        $size = mb_strlen($data, 'UTF-8');
        @$shmid = shmop_open($MEMORY, 'a', 0, 0);
        if (!empty($shmid)) {
            shmop_delete($shmid);
            shmop_close($shmid);
        }
        $shmid = shmop_open($MEMORY, 'c', 0666, $size);
        shmop_write($shmid, $data, 0);
        shmop_close($shmid);
        
        echo "$outstr";
    } elseif ($argv[1] == 'shm') {
        @$shmid = shmop_open($MEMORY, 'a', 0, 0);
        if (!empty($shmid)) {
            $size = shmop_size($shmid);
            shmop_close($shmid);
            
            $shmid        = shmop_open($MEMORY, 'c', 0666, $size);
            $memarraydata = shmop_read($shmid, 0, $size);
            shmop_close($shmid);
            $memarray = json_decode($memarraydata, true);
            print_r($memarray);
            echo "ps: clean the shm before using this script from meterN ! (ipcrm -M $MEMORY)\n";
        } else {
            echo "Empty shm ($MEMORY)\n";
        }
        
    } else {
        die("Abording: no valid argument given\n");
    }
} else {
    die("Usage: housepower { power | energy | self }\n");
}
?>


sovking
Posts: 80
Joined: Fri Feb 27, 2015 12:02 am

Re: Annoyng bug: negative numbers

Post by sovking » Thu Jan 07, 2016 8:07 pm

Ok, running from now.

Could you integrate in that script the live eimp and eexp and eself ? It should just 3 more tests with simple math...
The following is the code I'm using, but only just few lines of it are necessary:

Code: Select all

<?php
// This script will simulate a house consumption meter if you own a total meter (import/export) and a production meter.

require_once(dirname(__FILE__).'/meters-configuration.php'); 

// No edit should be needed bellow
function isvalid($id, $datareturn) //  IEC 62056 data set structure
{
    $regexp = "/^$id\(-?[0-9\.]+\*[A-z0-9<C2><B3><C2><B2>%<C2><B0>]+\)$/i"; //ID(VALUE*UNIT)
    if (preg_match($regexp, $datareturn)) {
        $datareturn = preg_replace("/^$id\(/i", '', $datareturn, 1); // VALUE*UNIT)
        $datareturn = preg_replace("/\*[A-z0-9<C2><B3><C2><B2>%<C2><B0>]+\)$/i", '', $datareturn, 1); // VALUE
        settype($datareturn, 'int');
    } else {
        $datareturn = null;
    }
    return $datareturn;
}

// Compute total power
$datareturn = exec($TOTPOWERcmd);
$datareturn = trim($datareturn);
$totpower   = isvalid($TPID, $datareturn);

// Compute production power
$datareturn = exec($POWERPRODcmd);
$datareturn = trim($datareturn);
$prodpower  = isvalid($PRODID, $datareturn);

// Compute consuption power
$consumi = $totpower + $prodpower;

// Compute Import, Export and SelfConsumption power
if ($totpower > 0) { // Import (Prelievi) 
        $imppower = $consumi - $prodpower;
        $exppower = 0;
        $slfpower = $prodpower;
} else { // Export (Immissioni)
        $imppower = 0;
        $exppower = $prodpower - $totpower;
        $slfpower = $consumi;
}

if ($argc > 1) {
        if (strncasecmp($argv[1],"i",1) == 0) {
                $str   = utf8_decode("$IMPID($imppower*W)\n");
        } else if (strncasecmp($argv[1], "e", 1) == 0) {
                $str   = utf8_decode("$EXPID($exppower*W)\n");
        } else if (strncasecmp($argv[1], "s", 1) == 0) {
                $str   = utf8_decode("$SELFID($slfpower*W)\n");
        }
        echo "$str";
} else {
        echo "DEBUG (missing argument: it can be i or e or s)\n";
        echo "Tot.: $totpower \n";
        echo "Pro.: $prodpower \n";
        echo "Con.: $consumi \n";
        echo "Exp.: $exppower \n";
        echo "Imp.: $imppower \n";
        echo "Aut.: $slfpower \n";
}
?>
Thanks!

jeanmarc
Posts: 1600
Joined: Thu Aug 29, 2013 7:16 am

Re: Annoyng bug: negative numbers

Post by jeanmarc » Fri Jan 08, 2016 11:46 am

Neat idea, i will repack the com app example with this.

Code: Select all

#!/usr/bin/php
<?php
// A virtual meters example for meterN. 
//					  ___
//					 /   \
//		- import ->	/     \
//					|  ?  | <- production
//		<- export -	|     |
//
//This script will simulate a house consumption and selfconsumuption meter. You must own a total (import/export) and a production meter.
//  
// ln -s /srv/http/comapps/houseenergy.php /usr/bin/houseenergy
// houseenergy [ power | energy | self ]
 
if (isset($_SERVER['REMOTE_ADDR'])) {
    die('Direct access not permitted');
}
$MEMORY = 624;

// Set the new virtual meters
// Consumption
$HOUSEID     = 'elect'; // ID
$HOUSEmetnum = 1; // meter number
// Selfconsumption
$SELFID      = 'self';
$SELFCmetnum = 7;

// Set up real meters
// Production
$PRODID       = 'solar'; // ID
$PRODcmd      = 'pool123s energy'; // Energy command
$POWERPRODcmd = 'pool123s power'; // Power
$PRODmetnum   = 4; // meter number
// TOT
$TPID         = '1_P';
//$TOTPOWERcmd  = 'reqsdm TOT'; // return the total power (eg if import = 45W, export -55W)
$TOTPOWERcmd  = 'sdm120cdrk -a1 -b9600 -2 -m -p /dev/sdm';
// Energy Imported
$IMPID        = '1_IE';
//$IMPcmd    = 'reqsdm EIMP';
$IMPcmd       = 'sdm120cdrk -a1 -b9600 -2 -m -i /dev/sdm';
$IMPmetnum    = 5;
// Energy Exported
$EXPID        = '1_EE';
//$EXPcmd    = 'reqsdm EEXP';
$EXPcmd       = 'sdm120cdrk -a1 -b9600 -2 -m -e /dev/sdm';
$EXPmetnum    = 6;

// Path to metern
$MNDIR = '/srv/http/metern';

// No edit should be needed bellow
function isvalid($id, $datareturn) //  IEC 62056 data set structure
{
    $regexp = "/^$id\(-?[0-9\.]+\*[A-z0-9³²%°]+\)$/i"; //ID(VALUE*UNIT)
    if (preg_match($regexp, $datareturn)) {
        $datareturn = preg_replace("/^$id\(/i", '', $datareturn, 1); // VALUE*UNIT)
        $datareturn = preg_replace("/\*[A-z0-9³²%°]+\)$/i", '', $datareturn, 1); // VALUE
        settype($datareturn, 'int');
    } else {
        $datareturn = null;
    }
    return $datareturn;
}

function retrievecsv($meternum, $csvarray, $passo, $datareturn) // Retrieve last know value in csv
{
    $datareturn = null;
    $contalines = count($csvarray);
    $j          = 0;
    while (!isset($datareturn)) {
        $j++;
        $array      = preg_split('/,/', $csvarray[$contalines - $j]);
        $datareturn = trim($array[$meternum]);
        if ($datareturn == '') {
            $datareturn = null;
        }
        if ($j == $contalines) {
            $datareturn = 0;
        }
    }
    if ($datareturn > $passo) {
        $datareturn -= $passo;
    }
    return $datareturn;
}

if (isset($argv[1])) {
    if ($argv[1] == 'power' || $argv[1] == 'powerimp' || $argv[1] == 'powerexp' || $argv[1] == 'powerself') {
        $datareturn = exec($TOTPOWERcmd);
        $datareturn = trim($datareturn);
        $totpower   = isvalid($TPID, $datareturn);
        
        $datareturn = exec($POWERPRODcmd);
        $datareturn = trim($datareturn);
        $prodpower  = isvalid($PRODID, $datareturn);
        
        $power = $prodpower + $totpower;
        
        if ($argv[1] == 'power') {
            $outstr = utf8_decode("$HOUSEID($power*W)\n");
        } else {
            if ($totpower > 0) { // Import
                $imppower = $power - $prodpower;
                $exppower = 0;
                $slfpower = $prodpower;
            } else { // Export
                $imppower = 0;
                $exppower = $prodpower - $power;
                $slfpower = $power;
            }
        }
        if ($argv[1] == 'powerimp') {
            $outstr = utf8_decode("$IMPID($imppower*W)\n");
        } elseif ($argv[1] == 'powerexp') {
            $outstr = utf8_decode("$EXPID($exppower*W)\n");
        } elseif ($argv[1] == 'powerself') {
            $outstr = utf8_decode("$SELFID($slfpower*W)\n");
        }
        echo "$outstr";
    } elseif ($argv[1] == 'energy' || $argv[1] == 'self') {
        define('checkaccess', TRUE);
        include("$MNDIR/config/config_main.php");
        
        include("$MNDIR/config/config_met$HOUSEmetnum.php");
        include("$MNDIR/config/config_met$SELFCmetnum.php");
        include("$MNDIR/config/config_met$IMPmetnum.php");
        include("$MNDIR/config/config_met$EXPmetnum.php");
        include("$MNDIR/config/config_met$PRODmetnum.php");
        
        ///// open shm memory
        @$shmid = shmop_open($MEMORY, 'a', 0, 0);
        if (!empty($shmid)) {
            $size = shmop_size($shmid);
            shmop_close($shmid);
            
            $shmid        = shmop_open($MEMORY, 'c', 0666, $size);
            $memarraydata = shmop_read($shmid, 0, $size);
            shmop_close($shmid);
            $memarray = json_decode($memarraydata, true);
        }
        
        if (!isset($memarray['prevHOUSE']) || !isset($memarray['prevSELF'])) { // At boot retrieve values in last csv
            $output = array();
            $output = glob($MNDIR . '/data/csv/*.csv');
            sort($output);
            $cnt = count($output);
            
            $lines = file($output[$cnt - 1]); // should be today
            if ($cnt > 0) {
                $contalines = count($lines);
                $lastarray  = preg_split("/,/", $lines[$contalines - 1]);
                
                $datareturn                = null;
                $memarray['prevIMPhouse']  = retrievecsv($IMPmetnum, $lines, ${'PASSO' . $IMPmetnum}, $datareturn);
                $datareturn                = null;
                $memarray['prevEXPhouse']  = retrievecsv($EXPmetnum, $lines, ${'PASSO' . $EXPmetnum}, $datareturn);
                $memarray['prevEXPself']   = $memarray['prevEXPhouse'];
                $datareturn                = null;
                $memarray['prevHOUSE']     = retrievecsv($HOUSEmetnum, $lines, ${'PASSO' . $HOUSEmetnum}, $datareturn);
                $datareturn                = null;
                $memarray['prevSELF']      = retrievecsv($SELFCmetnum, $lines, ${'PASSO' . $SELFCmetnum}, $datareturn);
                $datareturn                = null;
                $memarray['prevPRODhouse'] = retrievecsv($PRODmetnum, $lines, ${'PASSO' . $PRODmetnum}, $datareturn);
                $memarray['prevPRODself']  = $memarray['prevPRODhouse'];
            } else { // no csv
                $memarray['prevIMPhouse']  = 0;
                $memarray['prevEXPhouse']  = 0;
                $memarray['prevEXPself']   = 0;
                $memarray['prevHOUSE']     = 0;
                $memarray['prevSELF']      = 0;
                $memarray['prevPRODhouse'] = 0;
                $memarray['prevPRODself']  = 0;
            }
        }
        
        // Now retrieve latest values
        $datareturn = null;
        $import     = null;
        $export     = null;
        $production = null;
        $outstr     = null;
        // latest import
        if ($argv[1] == 'energy') {
            exec($IMPcmd, $datareturn);
            $datareturn = trim(implode($datareturn));
            $import     = isvalid($IMPID, $datareturn);
        }
        // latest export
        $datareturn = null;
        exec($EXPcmd, $datareturn);
        $datareturn = trim(implode($datareturn));
        $export     = isvalid($EXPID, $datareturn);
        
        // latest production
        $datareturn = null;
        exec($PRODcmd, $datareturn);
        $datareturn = trim(implode($datareturn));
        $production = isvalid($PRODID, $datareturn);
        
        // energy
        if ($argv[1] == 'energy') {
            if (isset($import) && isset($export)) {
                // Some passover checks
                if ($export >= $memarray['prevEXPhouse']) {
                    $diffEXP = $export - $memarray['prevEXPhouse'];
                } else {
                    $diffEXP = $export + ${'PASSO' . $EXPmetnum} - $memarray['prevEXPhouse'];
                }
                if (isset($production)) {
                    if ($production >= $memarray['prevPRODhouse']) {
                        $diffPROD = $production - $memarray['prevPRODhouse'];
                    } else {
                        $diffPROD = $production + ${'PASSO' . $PRODmetnum} - $memarray['prevPRODhouse'];
                    }
                    settype($memarray['prevPRODhouse'], 'int');
                    $memarray['prevPRODhouse'] = $production;
                } else { // no production case
                    $diffPROD = 0;
                    $diffEXP  = 0;
                }
                if ($import >= $memarray['prevIMPhouse']) {
                    $diffIMP = $import - $memarray['prevIMPhouse'];
                } else {
                    $diffIMP = $import + ${'PASSO' . $IMPmetnum} - $memarray['prevIMPhouse'];
                }
                $difference = $diffIMP + $diffPROD - $diffEXP;
            } else { // no import/export values
                $difference = 0;
            }
            
            //  bug
            if ($difference < 0) {
                date_default_timezone_set($DTZ);
                $a   = $memarray['prevHOUSE'];
                $b   = $memarray['prevEXPhouse'];
                $c   = $memarray['prevPRODhouse'];
                $d   = $memarray['prevIMPhouse'];
                $dt  = date('Ymd H:i:s');
                $tut = "$dt \t diff $difference \n prevHOUSE $a\n export: $export $b\n prod: $production $c\n import: $import $d\n";
                exec("echo '$tut' >> /srv/http/comapps/housebug.txt");
                
                $difference = 0; // correction
            }
            
            $memarray['prevHOUSE'] += $difference;
            
            if ($memarray['prevHOUSE'] >= ${'PASSO' . $HOUSEmetnum}) { // passed over
                $memarray['prevHOUSE'] -= ${'PASSO' . $HOUSEmetnum};
            }
            $val    = $memarray['prevHOUSE'];
            $outstr = utf8_decode("$HOUSEID($val*Wh)\n");
            
            settype($memarray['prevIMPhouse'], 'int');
            $memarray['prevIMPhouse'] = $import;
            settype($memarray['prevEXPhouse'], 'int');
            $memarray['prevEXPhouse'] = $export;
            settype($memarray['prevHOUSE'], 'int');
        } else { // Self 
            if (isset($export)) {
                // Some passover checks
                if ($export >= $memarray['prevEXPself']) {
                    $diffEXP = $export - $memarray['prevEXPself'];
                } else {
                    $diffEXP = $export + ${'PASSO' . $EXPmetnum} - $memarray['prevEXPself'];
                }
                if (isset($production)) {
                    if ($production >= $memarray['prevPRODself']) {
                        $diffPROD = $production - $memarray['prevPRODself'];
                    } else {
                        $diffPROD = $production + ${'PASSO' . $PRODmetnum} - $memarray['prevPRODself'];
                    }
                    settype($memarray['prevPRODself'], 'int');
                    $memarray['prevPRODself'] = $production;
                } else { // no production case
                    $diffPROD = 0;
                    $diffEXP  = 0;
                }
                $difference = $diffPROD - $diffEXP;
            } else { // no export values
                $difference = 0;
            }
            
            $memarray['prevSELF'] += $difference;
            if ($memarray['prevSELF'] >= ${'PASSO' . $SELFCmetnum}) {
                $memarray['prevSELF'] -= ${'PASSO' . $SELFCmetnum};
            }
            $val    = $memarray['prevSELF'];
            $outstr = utf8_decode("$SELFID($val*Wh)\n");
            
            settype($memarray['prevEXPself'], 'int');
            $memarray['prevEXPself'] = $export;
            settype($memarray['prevSELF'], 'int');
        }
        
        ///// save shm memory
        $data = json_encode($memarray);
        $size = mb_strlen($data, 'UTF-8');
        @$shmid = shmop_open($MEMORY, 'a', 0, 0);
        if (!empty($shmid)) {
            shmop_delete($shmid);
            shmop_close($shmid);
        }
        $shmid = shmop_open($MEMORY, 'c', 0666, $size);
        shmop_write($shmid, $data, 0);
        shmop_close($shmid);
        
        echo "$outstr";
    } elseif ($argv[1] == 'shm') {
        @$shmid = shmop_open($MEMORY, 'a', 0, 0);
        if (!empty($shmid)) {
            $size = shmop_size($shmid);
            shmop_close($shmid);
            
            $shmid        = shmop_open($MEMORY, 'c', 0666, $size);
            $memarraydata = shmop_read($shmid, 0, $size);
            shmop_close($shmid);
            $memarray = json_decode($memarraydata, true);
            print_r($memarray);
            echo "ps: Always clean the shm before using this script from meterN ! (ipcrm -M $MEMORY)\n";
        } else {
            echo "Empty shm ($MEMORY)\n";
        }
        
    } else {
        die("Abording: no valid argument given\n");
    }
} else {
    die("Usage: housepower { power | powerimp | powerexp | powerself | energy | self }\n");
}
?>

sovking
Posts: 80
Joined: Fri Feb 27, 2015 12:02 am

Re: Annoyng bug: negative numbers

Post by sovking » Fri Jan 08, 2016 6:44 pm

Great work!

Two glitches:
- in the initial comments, the usage example should contain the new arguments:

Code: Select all

// ln -s /srv/http/comapps/houseenergy.php /usr/bin/houseenergy
// houseenergy [ power | powerimp | powerexp | powerself | energy | self ]
- at the end in the usage "echo", should be written houseenergy or houseenergy.php instead of housepower...
or to forget about the name you chould use

Code: Select all

die("Usage: ". basename(__FILE__, ".php") ." { power | powerimp | powerexp | powerself | energy | self }\n");
I don't know if you prefer with or without extension... (just use __FILE__ if you wish).

And finally I suggest the following ASCII art at the beginning of the script

Code: Select all

#!/usr/bin/php
<?php
// A virtual meters example for meterN.
// __
// \ \     +--------+
//  \_\ -->|Inverter|-- Production -->|
//         +--------+   (meter)       |
//                                    |
//     _____                         \|/
//    /     \                     +-------+               +---------+
//   /       \                    | Total |<-- Import --- | Utility |
//   | House |<--- Consumption ---| Meter |--- Export --> | meter   |
//   |_______|                    +-------+               +---------+
//
// This script will simulate a house consumption and selfconsumuption meter.
// You must own a total (import/export) and a production meter.
//
// ln -s /srv/http/comapps/houseenergy.php /usr/bin/houseenergy
// houseenergy [ power | powerimp | powerexp | powerself | energy | self ]
That's should be quite clear, at least for Italian audience :D

sovking
Posts: 80
Joined: Fri Feb 27, 2015 12:02 am

Re: Annoyng bug: negative numbers

Post by sovking » Fri Jan 15, 2016 4:19 pm

Today another problem, with selfconsumption.
I'm housing the latest verson of housenergy (v.2.3 of 8 January)

Around 14:30 we suddendly needed a lot of electricity and the power grown up from around 1 Kw to over 6 kw for over 10 or 20 minutes (I don't remember exactly).
That's is what meterN registered:
Image
These are the recoreded readings:
Image
As you can see until 14:30 everything was fine, but at 14:35 ESELF get a negative value.
Any idee why it's happened ?

jeanmarc
Posts: 1600
Joined: Thu Aug 29, 2013 7:16 am

Re: Annoyng bug: negative numbers

Post by jeanmarc » Fri Jan 15, 2016 6:32 pm

I don't have the idea, i don't know what goes wrong. Could you add the same debug as consumption into self part :

Code: Select all

            if ($difference < 0) {
                date_default_timezone_set($DTZ);
                $a   = $memarray['prevEXPself'];
                $c   = $memarray['prevPRODself'];
                $dt  = date('Ymd H:i:s');
                $tut = "$dt \t diff $difference \n prevEXPself $a\n prevPRODself: $c export: \n $export prod: $production\n";
                exec("echo '$tut' >> /srv/http/comapps/selfbug.txt");
                
                $difference = 0; // correction
            }
Also, what are your passover values ?

sovking
Posts: 80
Joined: Fri Feb 27, 2015 12:02 am

Re: Annoyng bug: negative numbers

Post by sovking » Sat Jan 16, 2016 12:13 am

My passover values are 0.
Debug code added. Thank you!

thedrake
Posts: 52
Joined: Fri Aug 21, 2015 12:43 pm

Re: Annoyng bug: negative numbers

Post by thedrake » Sat Jan 16, 2016 3:26 pm

sovking wrote:My passover values are 0.
Debug code added. Thank you!
Hi sowking,
I suggest you to add -j10 -w10 to sdm120c commands if not already in your houseenergy script.

/drk

jeanmarc
Posts: 1600
Joined: Thu Aug 29, 2013 7:16 am

Re: Annoyng bug: negative numbers

Post by jeanmarc » Sat Jan 16, 2016 3:59 pm

Well, that shouldn't be the problem. If the value is not retrieved or is wrong there is isset($export) test that return a null difference.
I wonder where that negative values come. So far, i haven't the problem on my system.

jeanmarc
Posts: 1600
Joined: Thu Aug 29, 2013 7:16 am

Re: Annoyng bug: negative numbers

Post by jeanmarc » Thu Feb 18, 2016 5:46 pm

Hi,
Please use the latest 'housenergy', there was previously a bug with the self : if the production don't return a latest value (eg 123s is stop), while the export did.

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests