feat(workflow): publish verified forecast controls and consolidated docs
Tests / test (push) Successful in 1m1s
Tests / test (push) Successful in 1m1s
Approved by Daniel Haefliger for develop and beta. Author dh_Agent, authenticated account dh. Preserve published battery, charging and overall Energy Pie changes. No deployment or plant control authorization.
This commit is contained in:
@@ -35,10 +35,11 @@ namespace Belevo\EnelixEMS {
|
||||
public array $op=[];
|
||||
public function __construct($id,$op) {
|
||||
$this->op=$op;
|
||||
$this->props=['NetzfahrplanV4EmpfangAktiv'=>false,'NetzfahrplanV4SchattenAktiv'=>true,
|
||||
$this->props=['PrognoseAktiv'=>false,'NetzfahrplanRegelungAktiv'=>false,'NetzfahrplanV4SchattenAktiv'=>true,
|
||||
'NetzfahrplanAktiv'=>false,'MesswertMaxAlter'=>60,
|
||||
'AnlagenBatterien'=>json_encode([['ID'=>'b','LeistungVariableID'=>100,'Leistungsfaktor'=>1]])];
|
||||
$this->attrs=['LizenzInstallationID'=>$id,'PrognoseInstallationsToken'=>str_repeat('x',43)];
|
||||
$this->attrs=['LizenzInstallationID'=>$id,'PrognoseInstallationsToken'=>str_repeat('x',43),
|
||||
'PrognoseV4Serverstatus'=>'{}'];
|
||||
$this->registriereNetzfahrplanV4Empfang();
|
||||
}
|
||||
public function receive() {$this->empfangeNetzfahrplanV4();}
|
||||
@@ -47,6 +48,7 @@ namespace Belevo\EnelixEMS {
|
||||
public function configure() {$this->konfiguriereNetzfahrplanV4Vorschau();}
|
||||
public function GetNetzfahrplanV4Diagnose() { return json_encode(['operation'=>$this->op]); }
|
||||
private function aktiveVerbraucherIDs() {return [];}
|
||||
private function prognoseLernenAktiv() {return $this->props['PrognoseAktiv'];}
|
||||
private function v4ManagerTestSession() {return $this->session;}
|
||||
private function berechtigungLizenziert($key) {return $this->licensed;}
|
||||
private function ReadPropertyBoolean($key) {return (bool)$this->props[$key];}
|
||||
@@ -55,7 +57,7 @@ namespace Belevo\EnelixEMS {
|
||||
private function ReadAttributeString($key) {return $this->attrs[$key]??'';}
|
||||
private function ReadAttributeInteger($key) {return (int)($this->attrs[$key]??0);}
|
||||
private function WriteAttributeString($key,$val) {
|
||||
if (!str_starts_with($key,'NetzfahrplanV4')) throw new \RuntimeException('Unexpected external attribute');
|
||||
if (!str_starts_with($key,'NetzfahrplanV4') && $key!=='PrognoseV4Serverstatus') throw new \RuntimeException('Unexpected external attribute');
|
||||
$this->attrs[$key]=$val;
|
||||
}
|
||||
private function WriteAttributeInteger($key,$val) { $this->attrs[$key]=$val; }
|
||||
@@ -86,8 +88,9 @@ namespace {
|
||||
$GLOBALS['clock']+=$seconds;$GLOBALS['response']['checkedAt']=gmdate('c',$GLOBALS['clock']);
|
||||
$h->op['observedAt']=gmdate('c',$GLOBALS['clock']);$h->op['batteries'][0]['measuredAt']=$h->op['observedAt'];
|
||||
}
|
||||
$h=fixture();$h->receive();check(count($requests)===0,'default disabled no network');
|
||||
$h->props['NetzfahrplanV4EmpfangAktiv']=true;$h->configure();check($h->timers['NetzfahrplanV4VorschauAktualisieren']===10000,'watchdog without network');
|
||||
$h=fixture();$h->receive();check(count($requests)===0,'learning disabled makes no network request');
|
||||
$h->props['NetzfahrplanV4EmpfangAktiv']=true;$h->receive();check(count($requests)===0,'retired receiver flag cannot enable learning or network');
|
||||
$h->props['PrognoseAktiv']=true;$h->configure();check($h->timers['NetzfahrplanV4VorschauAktualisieren']===10000,'watchdog without network');
|
||||
$h->receive();$v=json_decode($h->GetNetzfahrplanV4Vorschau(),true);
|
||||
check($v['status']==='preview_only' && $v['previewBatteryW']===3000 && $v['canDispatch']===false,'read and show only');
|
||||
check(count($requests)===2 && str_ends_with($requests[1]['url'],'/ack'),'one read and one acknowledgement');
|
||||
@@ -97,25 +100,25 @@ namespace {
|
||||
advance($h,91);$h->update();$v=json_decode($h->vars['NetzfahrplanV4VorschauJSON'],true);
|
||||
check($v['status']==='unavailable' && $v['previewBatteryW']===null,'expired cache clears numeric targets, not fake zero');
|
||||
check(!str_contains($h->vars['NetzfahrplanV4Vorschau'],'3000'),'expired HTML clears previous setpoint');
|
||||
$h=fixture();$h->props['NetzfahrplanV4EmpfangAktiv']=true;$h->receive();advance($h,61);$GLOBALS['getCode']=429;$h->receive();
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$h->receive();advance($h,61);$GLOBALS['getCode']=429;$h->receive();
|
||||
check($h->attrs['NetzfahrplanV4Empfang']==='{}' && json_decode($h->GetNetzfahrplanV4Vorschau(),true)['previewBatteryW']===null,'429 invalidates cache');
|
||||
check(!str_contains(json_encode($h->vars),str_repeat('x',43)),'no credentials in diagnosis');
|
||||
$h=fixture();$h->props['NetzfahrplanV4EmpfangAktiv']=true;$h->props['NetzfahrplanAktiv']=true;$h->receive();check(count($requests)===0,'legacy execution on blocks preview acquisition');
|
||||
$h=fixture();$h->props['NetzfahrplanV4EmpfangAktiv']=true;$GLOBALS['response']['installationId']='00000000-0000-4000-8000-000000000001';$h->receive();
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$h->props['NetzfahrplanAktiv']=true;$h->receive();check(count($requests)===2 && $h->props['NetzfahrplanRegelungAktiv']===false,'obsolete legacy flag neither blocks preview nor enables V4 control');
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$GLOBALS['response']['installationId']='00000000-0000-4000-8000-000000000001';$h->receive();
|
||||
check(count($requests)===1 && $h->attrs['NetzfahrplanV4Empfang']==='{}','foreign response not acknowledged');
|
||||
$h=fixture();$h->props['NetzfahrplanV4EmpfangAktiv']=true;$GLOBALS['ackCode']=503;$h->receive();$v=json_decode($h->GetNetzfahrplanV4Vorschau(),true);
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$GLOBALS['ackCode']=503;$h->receive();$v=json_decode($h->GetNetzfahrplanV4Vorschau(),true);
|
||||
check($v['status']==='preview_only' && !$v['reception']['acknowledged'] && isset($v['reception']['acknowledgementError']),'ack failure is visible, no false execution confirmation');
|
||||
$h=fixture();$h->props['NetzfahrplanV4EmpfangAktiv']=true;$h->receive();$h->op['batteries'][0]['minSocPercent']=30.;$h->update();
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$h->receive();$h->op['batteries'][0]['minSocPercent']=30.;$h->update();
|
||||
check(json_decode($h->vars['NetzfahrplanV4VorschauJSON'],true)['previewBatteryW']===null,'local policy change invalidates cache');
|
||||
$h=fixture();$h->props['NetzfahrplanV4EmpfangAktiv']=true;$h->receive();$h->stop();check($h->attrs['NetzfahrplanV4Empfang']==='{}' && $h->timers['NetzfahrplanV4VorschauAktualisieren']===0,'apply/restart invalidates cached plan');
|
||||
$h=fixture();$h->props['NetzfahrplanV4EmpfangAktiv']=true;$h->licensed=false;$h->receive();check(count($requests)===0,'no license no read');
|
||||
$h=fixture();$h->props['NetzfahrplanV4EmpfangAktiv']=true;$GLOBALS['lock']=true;$h->receive();check(count($requests)===0,'concurrent receiver does not send');
|
||||
$h=fixture();$h->props['NetzfahrplanV4EmpfangAktiv']=true;$h->receive();$h->props['NetzfahrplanV4EmpfangAktiv']=false;$h->update();check(json_decode($h->vars['NetzfahrplanV4VorschauJSON'],true)['previewBatteryW']===null,'disable clears displayed target');
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$h->receive();$h->stop();check($h->attrs['NetzfahrplanV4Empfang']==='{}' && $h->timers['NetzfahrplanV4VorschauAktualisieren']===0,'apply/restart invalidates cached plan');
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$h->licensed=false;$h->receive();check(count($requests)===0,'no license no read');
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$GLOBALS['lock']=true;$h->receive();check(count($requests)===0,'concurrent receiver does not send');
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$h->receive();$h->props['PrognoseAktiv']=false;$h->update();check(json_decode($h->vars['NetzfahrplanV4VorschauJSON'],true)['previewBatteryW']===null,'disable clears displayed target');
|
||||
$source=file_get_contents(__DIR__.'/../../libs/ManagerNetzfahrplanV4EmpfangTrait.php');
|
||||
check(!str_contains($source, 'netzfahrplanV4EmpfangFormular'), 'receiver no longer owns a separate form panel');
|
||||
check(!preg_match('/\b(?:SendDataToChildren|SendDataToParent|sendeManagerdaten|regeln|SetStatus|EnableAction|IPS_SetProperty|IPS_ApplyChanges)\s*\(/',$source),'no control or external configuration call in receiver');
|
||||
check(!str_contains($source,"'status' => 'applied'"),'never acknowledges applied');
|
||||
$h=fixture();$h->props['NetzfahrplanV4EmpfangAktiv']=true;$h->configure();
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$h->configure();
|
||||
check($h->timers['NetzfahrplanV4EmpfangAktualisieren']===10000,'refresh has an independent timer');
|
||||
$h->session=['kind'=>'local_active_test_consent'];$h->receive();$saved=$h->attrs['NetzfahrplanV4Empfang'];
|
||||
check($h->attrs['NetzfahrplanV4NaechsterAbruf']===$clock+45,'active refresh due after 45 seconds');
|
||||
@@ -125,16 +128,22 @@ namespace {
|
||||
advance($h,46);$h->receive();
|
||||
check($h->attrs['NetzfahrplanV4Empfang']==='{}','active envelope older than 90 seconds is discarded');
|
||||
$h->stop();check($h->timers['NetzfahrplanV4EmpfangAktualisieren']===0,'stop disables independent refresh timer');
|
||||
$h=fixture();$h->props['NetzfahrplanV4EmpfangAktiv']=true;$h->session=['kind'=>'local_active_test_consent'];$h->receive();
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$h->session=['kind'=>'local_active_test_consent'];$h->receive();
|
||||
$future=json_decode($h->attrs['NetzfahrplanV4Empfang'],true);$future['receivedAt']=$clock+120;
|
||||
$h->attrs['NetzfahrplanV4Empfang']=json_encode($future);advance($h,45);$GLOBALS['getCode']=503;$h->receive();
|
||||
check($h->attrs['NetzfahrplanV4Empfang']==='{}','future receipt cannot survive failed refresh');
|
||||
$h=fixture();$h->props['NetzfahrplanV4EmpfangAktiv']=true;$GLOBALS['response']['pending']=['sequence'=>1];$GLOBALS['response']['fresh']=false;$h->receive();
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$GLOBALS['response']['pending']=['sequence'=>1];$GLOBALS['response']['fresh']=false;$h->receive();
|
||||
check($h->attrs['NetzfahrplanV4NaechsterAbruf']===$clock+15 && $h->attrs['NetzfahrplanV4Empfang']==='{}',
|
||||
'pending startup retries after 15 seconds without creating a usable envelope');
|
||||
$v=json_decode($h->GetNetzfahrplanV4Vorschau(),true);
|
||||
check(($v['reception']['status']??null)==='rejected_or_unavailable','unavailable preview preserves receiver rejection detail');
|
||||
$h=fixture();$h->props['NetzfahrplanV4EmpfangAktiv']=true;$GLOBALS['getCode']=429;$h->receive();
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$GLOBALS['getCode']=429;$h->receive();
|
||||
check($h->attrs['NetzfahrplanV4NaechsterAbruf']===$clock+60,'startup rate-limit response retains ordinary backoff');
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;$h->props['NetzfahrplanRegelungAktiv']=true;$h->receive();
|
||||
check($h->attrs['NetzfahrplanV4NaechsterAbruf']===$clock+45,'normal control switch uses active refresh without a test session');
|
||||
$h=fixture();$h->props['PrognoseAktiv']=true;
|
||||
$GLOBALS['response']['workflow']=['state'=>'ready','planningReady'=>true,'controlActive'=>false];$h->receive();
|
||||
$workflow=json_decode($h->attrs['PrognoseV4Serverstatus'],true);
|
||||
check($workflow['receivedAt']===$clock && $workflow['workflow']===$GLOBALS['response']['workflow'],'server workflow cached separately without inferring control activity');
|
||||
echo "Total: $count checks. Mocked IPS and HTTP only.\n";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user