This commit is contained in:
@@ -33,16 +33,10 @@
|
||||
},
|
||||
{
|
||||
"type": "NumberSpinner",
|
||||
"name": "Interval",
|
||||
"caption": "Regelintervall",
|
||||
"name": "LastwechselSperrzeit",
|
||||
"caption": "Mindestzeit zwischen Lastwechseln",
|
||||
"suffix": " s",
|
||||
"minimum": 1
|
||||
},
|
||||
{
|
||||
"type": "NumberSpinner",
|
||||
"name": "IdleCounterMax",
|
||||
"caption": "Zyklen bis Idle",
|
||||
"minimum": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -56,8 +56,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
$this->RegisterPropertyBoolean('BoilertemperaturGlaetten', false);
|
||||
$this->RegisterPropertyInteger('Boilervolumen', 300);
|
||||
$this->RegisterPropertyString('Zeitplan', '[]');
|
||||
$this->RegisterPropertyInteger('Interval', 5);
|
||||
$this->RegisterPropertyInteger('IdleCounterMax', 2);
|
||||
$this->RegisterPropertyInteger('LastwechselSperrzeit', 5);
|
||||
$this->RegisterPropertyInteger('TemperaturMaxAlter', 30);
|
||||
$this->RegisterPropertyFloat('Hysterese', 5.0);
|
||||
$this->RegisterPropertyBoolean('LegionellenfunktionAktiv', true);
|
||||
@@ -74,7 +73,9 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
$this->RegisterAttributeBoolean('InitialwerteGesetzt', false);
|
||||
$this->RegisterAttributeInteger('RegistrierteFuehlerID', 0);
|
||||
$this->RegisterAttributeInteger('LetzteBerechnung', 0);
|
||||
$this->RegisterAttributeInteger('LetzteTemperaturberechnung', 0);
|
||||
$this->RegisterAttributeInteger('LetzteVorgabeZeit', 0);
|
||||
$this->RegisterAttributeInteger('LetzterLastwechsel', 0);
|
||||
$this->RegisterAttributeInteger('LetzteManagerID', 0);
|
||||
$this->RegisterAttributeInteger('LetzterLegionellenabschluss', 0);
|
||||
$this->RegisterAttributeFloat('Glaettungswert', 0.0);
|
||||
@@ -99,9 +100,9 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
$this->RegisterAttributeInteger('ZustandIdleCounter', 0);
|
||||
|
||||
$this->RegisterTimer(
|
||||
'Regelzyklus',
|
||||
'LastwechselFreigabe',
|
||||
0,
|
||||
"IPS_RequestAction(\$_IPS['TARGET'], 'Regelzyklus', false);"
|
||||
"IPS_RequestAction(\$_IPS['TARGET'], 'LastwechselFreigabe', false);"
|
||||
);
|
||||
$this->RegisterTimer(
|
||||
'Meldezyklus',
|
||||
@@ -125,7 +126,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
try {
|
||||
$this->pruefeKonfiguration();
|
||||
} catch (Throwable $fehler) {
|
||||
$this->SetTimerInterval('Regelzyklus', 0);
|
||||
$this->SetTimerInterval('LastwechselFreigabe', 0);
|
||||
$this->SetTimerInterval('Meldezyklus', 0);
|
||||
$this->SetTimerInterval('RueckmeldungVerzoegert', 0);
|
||||
$this->setzeZustand('Verfuegbar', false);
|
||||
@@ -136,7 +137,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
}
|
||||
|
||||
$this->registriereFuehlermeldung();
|
||||
$this->SetTimerInterval('Regelzyklus', $this->ReadPropertyInteger('Interval') * 1000);
|
||||
$this->SetTimerInterval('LastwechselFreigabe', 0);
|
||||
$this->SetTimerInterval('Meldezyklus', $this->ReadPropertyInteger('Meldeintervall') * 1000);
|
||||
if ($this->ReadAttributeInteger('LetzterLegionellenabschluss') <= 0) {
|
||||
$this->WriteAttributeInteger('LetzterLegionellenabschluss', time());
|
||||
@@ -168,7 +169,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
$this->setzeTemperaturSollwert((string) $ident, $wert);
|
||||
return;
|
||||
|
||||
case 'Regelzyklus':
|
||||
case 'LastwechselFreigabe':
|
||||
$this->SetTimerInterval('LastwechselFreigabe', 0);
|
||||
$this->regelzyklus(true);
|
||||
return;
|
||||
|
||||
@@ -176,6 +178,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
if ((bool) $wert) {
|
||||
$this->SetTimerInterval('RueckmeldungVerzoegert', 0);
|
||||
}
|
||||
$this->regelzyklus(false);
|
||||
$this->sendeVerbraucherdaten();
|
||||
return;
|
||||
|
||||
@@ -233,8 +236,15 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
$temperaturGueltig = $this->aktualisiereTemperatur();
|
||||
$this->aktualisiereLegionellenstatus($temperaturGueltig, $jetzt);
|
||||
|
||||
$restzeit = $this->aktualisiereLastwechselstatus($jetzt);
|
||||
[$angebot, $aenderungMoeglich, $verfuegbar, $zwangsleistung] =
|
||||
$this->bestimmeLeistungsangebot($temperaturGueltig, $jetzt);
|
||||
$aktuelleLeistung = (int) round((float) $this->leseZustand('Istleistung'));
|
||||
$lastwechselGesperrt = $restzeit > 0 && $verfuegbar && $zwangsleistung !== 0;
|
||||
if ($lastwechselGesperrt) {
|
||||
$angebot = [$aktuelleLeistung];
|
||||
$aenderungMoeglich = false;
|
||||
}
|
||||
$this->WriteAttributeString('Leistungsangebot', json_encode($angebot, JSON_THROW_ON_ERROR));
|
||||
$this->setzeZustand('Verfuegbar', $verfuegbar);
|
||||
$this->setzeZustand('AenderungMoeglich', $aenderungMoeglich);
|
||||
@@ -247,7 +257,9 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
}
|
||||
|
||||
$ziel = 0;
|
||||
if ($verfuegbar) {
|
||||
if ($lastwechselGesperrt) {
|
||||
$ziel = $aktuelleLeistung;
|
||||
} elseif ($verfuegbar) {
|
||||
if ($zwangsleistung !== null) {
|
||||
$ziel = $zwangsleistung;
|
||||
} elseif ((bool) $this->leseZustand('SollwertGueltig')) {
|
||||
@@ -259,7 +271,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
}
|
||||
}
|
||||
|
||||
$this->schalteLeistung($ziel);
|
||||
$this->schalteLeistung($ziel, $jetzt);
|
||||
$this->setzeZustand('Sollleistung', $ziel);
|
||||
$this->aktualisiereStoerungen($temperaturGueltig);
|
||||
if ($meldungPlanen) {
|
||||
@@ -296,18 +308,23 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
}
|
||||
|
||||
$temperatur = (float) $rohwert;
|
||||
$jetzt = time();
|
||||
$letzteTemperaturberechnung = $this->ReadAttributeInteger('LetzteTemperaturberechnung');
|
||||
$this->WriteAttributeInteger('LetzteTemperaturberechnung', $jetzt);
|
||||
if ($this->ReadPropertyBoolean('BoilertemperaturGlaetten')) {
|
||||
if (!$this->ReadAttributeBoolean('GlaettungInitialisiert')) {
|
||||
$this->WriteAttributeFloat('Glaettungswert', $temperatur);
|
||||
$this->WriteAttributeBoolean('GlaettungInitialisiert', true);
|
||||
} else {
|
||||
} elseif ($letzteTemperaturberechnung > 0 && $jetzt > $letzteTemperaturberechnung) {
|
||||
$temperatur = WarmwasserRegler::pt1(
|
||||
$this->ReadAttributeFloat('Glaettungswert'),
|
||||
$temperatur,
|
||||
$this->ReadPropertyInteger('Interval'),
|
||||
$jetzt - $letzteTemperaturberechnung,
|
||||
$this->ReadPropertyInteger('ZeitKonstante')
|
||||
);
|
||||
$this->WriteAttributeFloat('Glaettungswert', $temperatur);
|
||||
} else {
|
||||
$temperatur = $this->ReadAttributeFloat('Glaettungswert');
|
||||
}
|
||||
} else {
|
||||
$this->WriteAttributeBoolean('GlaettungInitialisiert', false);
|
||||
@@ -403,14 +420,13 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
$this->setzeZustand('LegionellenbetriebAktiv', $fruehestensFaellig);
|
||||
}
|
||||
|
||||
private function schalteLeistung(int $zielLeistung): void
|
||||
private function schalteLeistung(int $zielLeistung, int $jetzt): void
|
||||
{
|
||||
$stufen = WarmwasserRegler::dekodiereLeistungsstufen($this->ReadPropertyString('LeistungsStufen'));
|
||||
$zielStufe = WarmwasserRegler::stufeFuerLeistung($stufen, $zielLeistung);
|
||||
$bisherigeLeistung = (int) round((float) $this->leseZustand('Istleistung'));
|
||||
if ($zielLeistung === $bisherigeLeistung && $this->kontakteEntsprechenZiel($stufen, $zielLeistung)) {
|
||||
$this->WriteAttributeString('Schaltfehler', '');
|
||||
$this->verarbeiteIdle(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -436,6 +452,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
}
|
||||
$this->setzeZustand('Istleistung', 0.0);
|
||||
$this->setzeZustand('AktiveStufe', 0);
|
||||
$this->WriteAttributeInteger('LetzterLastwechsel', $jetzt);
|
||||
$this->aktualisiereLastwechselstatus($jetzt);
|
||||
throw new RuntimeException('Leistungsstufe konnte nicht sicher geschaltet werden: ' . $fehler->getMessage());
|
||||
}
|
||||
|
||||
@@ -443,7 +461,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
$this->setzeZustand('Istleistung', (float) $zielLeistung);
|
||||
$this->setzeZustand('Leistungsquelle', Nachrichtenvertrag::LEISTUNGSQUELLE_BERECHNET);
|
||||
$this->setzeZustand('AktiveStufe', $zielStufe);
|
||||
$this->verarbeiteIdle(true);
|
||||
$this->WriteAttributeInteger('LetzterLastwechsel', $jetzt);
|
||||
$this->aktualisiereLastwechselstatus($jetzt);
|
||||
$this->protokolliere('Leistungsstufe', ['Leistung_W' => $zielLeistung, 'Stufe' => $zielStufe]);
|
||||
}
|
||||
|
||||
@@ -465,16 +484,18 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
return true;
|
||||
}
|
||||
|
||||
private function verarbeiteIdle(bool $geaendert): void
|
||||
private function aktualisiereLastwechselstatus(int $jetzt): int
|
||||
{
|
||||
$counter = (int) $this->leseZustand('IdleCounter');
|
||||
if ($geaendert) {
|
||||
$counter = $this->ReadPropertyInteger('IdleCounterMax');
|
||||
} elseif ($counter > 0) {
|
||||
--$counter;
|
||||
}
|
||||
$this->setzeZustand('IdleCounter', $counter);
|
||||
$this->setzeZustand('Idle', $counter === 0);
|
||||
$restzeit = WarmwasserRegler::restzeitBisLastwechsel(
|
||||
$this->ReadAttributeInteger('LetzterLastwechsel'),
|
||||
$jetzt,
|
||||
$this->ReadPropertyInteger('LastwechselSperrzeit')
|
||||
);
|
||||
$this->setzeZustand('IdleCounter', $restzeit);
|
||||
$this->setzeZustand('Idle', $restzeit === 0);
|
||||
$this->SetTimerInterval('LastwechselFreigabe', $restzeit > 0 ? $restzeit * 1000 : 0);
|
||||
|
||||
return $restzeit;
|
||||
}
|
||||
|
||||
private function aktualisiereEnergie(int $jetzt): void
|
||||
@@ -674,7 +695,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
}
|
||||
}
|
||||
foreach ([
|
||||
'Meldeintervall', 'VorgabeTimeout', 'Interval', 'IdleCounterMax', 'TemperaturMaxAlter',
|
||||
'Meldeintervall', 'VorgabeTimeout', 'LastwechselSperrzeit', 'TemperaturMaxAlter',
|
||||
'ZeitKonstante', 'Boilervolumen', 'LegionellenMinimalintervallTage',
|
||||
'LegionellenMaximalintervallTage',
|
||||
] as $property) {
|
||||
@@ -825,8 +846,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
||||
220
|
||||
);
|
||||
$this->RegisterVariableInteger('LegioCounter', 'Zeit seit Legionellenabschluss', '', 230);
|
||||
$this->RegisterVariableBoolean('Idle', 'Idle', '~Switch', 240);
|
||||
$this->RegisterVariableInteger('IdleCounter', 'Idle Counter', '', 250);
|
||||
$this->RegisterVariableBoolean('Idle', 'Lastwechsel freigegeben', '~Switch', 240);
|
||||
$this->RegisterVariableInteger('IdleCounter', 'Restzeit bis Lastwechsel', '', 250);
|
||||
|
||||
foreach (self::DIAGNOSE_VARIABLEN as $ident) {
|
||||
$wert = $ident === 'Leistungsquelle'
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
| Enelix 1 | Enelix 2 | Hinweis |
|
||||
| --- | --- | --- |
|
||||
| `LeistungsStufen` | `LeistungsStufen` | Felder `Stufe`, `Leistung`, `Schaltkontakt_Stufe` bleiben erhalten. |
|
||||
| `ZeitKonstante` | `ZeitKonstante` | PT1-Berechnung verwendet das reale Regelintervall. |
|
||||
| `ZeitKonstante` | `ZeitKonstante` | PT1-Berechnung verwendet die tatsaechlich verstrichene Zeit. |
|
||||
| `Boilerfuehler_PT1` | `Boilerfuehler_PT1` | Alter und Datentyp werden geprueft. |
|
||||
| `Boilertemperatur_glätten` | `BoilertemperaturGlaetten` | ASCII-sicherer Ident. |
|
||||
| `Boilervolumen` | `Boilervolumen` | Wird fuer die Zeitplanprognose verwendet. |
|
||||
| `Zeitplan` | `Zeitplan` | JSON-Liste mit `Uhrzeit` und `Solltemperatur`. |
|
||||
| `Interval` | `Interval` | Regelintervall in Sekunden. |
|
||||
| `IdleCounterMax` | `IdleCounterMax` | Verhalten bleibt erhalten. |
|
||||
| `Interval` | entfaellt | Die Regelung wird ereignisbasiert ausgeloest. |
|
||||
| `IdleCounterMax` | `LastwechselSperrzeit` | Zykluszaehler wird durch eine Sperrzeit in Sekunden ersetzt; Standard `5`. |
|
||||
|
||||
Die neuen Properties `TemperaturMaxAlter`, `Hysterese`, die Parameter der
|
||||
Legionellenfunktion und `DiagnosevariablenAnzeigen` ersetzen feste Werte und
|
||||
|
||||
@@ -19,13 +19,16 @@ Legionellenprogramm koennen die lokale Warmwassersicherheit priorisieren.
|
||||
- Mindesttemperatur, vorausberechneter Zeitplan und Legionellenprogramm koennen
|
||||
die maximale Stufe lokal erzwingen. Diese Phase wird mit
|
||||
`AenderungMoeglich=false` gemeldet.
|
||||
- Lastwechsel werden fuer `LastwechselSperrzeit` Sekunden gesperrt. Danach
|
||||
erfolgt genau eine ereignisgesteuerte Neuberechnung; sicherheitsbedingtes
|
||||
Ausschalten bleibt sofort moeglich.
|
||||
- `BoilertemperaturGlaetten` aktiviert eine PT1-Glaettung mit konfigurierbarer
|
||||
Zeitkonstante.
|
||||
Zeitkonstante und der tatsaechlich verstrichenen Zeit.
|
||||
|
||||
## Properties
|
||||
|
||||
Zu den sechs gemeinsamen Verbraucher-Properties aus
|
||||
[`Schnittstelle.md`](../../Schnittstelle.md) kommen 14 Modul-Properties hinzu.
|
||||
[`Schnittstelle.md`](../../Schnittstelle.md) kommen 13 Modul-Properties hinzu.
|
||||
|
||||
| Ident | Typ | Standard | Beschreibung |
|
||||
| --- | --- | ---: | --- |
|
||||
@@ -35,8 +38,7 @@ Zu den sechs gemeinsamen Verbraucher-Properties aus
|
||||
| `BoilertemperaturGlaetten` | Boolean | `false` | PT1-Glaettung aktiv. |
|
||||
| `Boilervolumen` | Integer | `300` | Volumen in Litern fuer die Zeitplanprognose. |
|
||||
| `Zeitplan` | JSON-Liste | `[]` | Uhrzeit und Solltemperatur. |
|
||||
| `Interval` | Integer | `5` | Regelintervall in Sekunden. |
|
||||
| `IdleCounterMax` | Integer | `2` | Zyklen bis zum Idle-Status. |
|
||||
| `LastwechselSperrzeit` | Integer | `5` | Mindestzeit zwischen zwei Lastwechseln in Sekunden. |
|
||||
| `TemperaturMaxAlter` | Integer | `30` | Maximal zulaessiges Messwertalter in Sekunden. |
|
||||
| `Hysterese` | Float | `5.0` | Temperaturhysterese in K. |
|
||||
| `LegionellenfunktionAktiv` | Boolean | `true` | Zweistufige periodische Aufheizung aktiv. |
|
||||
@@ -74,8 +76,8 @@ Mit `DiagnosevariablenAnzeigen` werden diese 16 Variablen angelegt:
|
||||
- `NachladenAktiv`
|
||||
- `LegionellenbetriebAktiv`
|
||||
- `LegioCounter`
|
||||
- `Idle`
|
||||
- `IdleCounter`
|
||||
- `Idle` (Lastwechsel freigegeben)
|
||||
- `IdleCounter` (verbleibende Sperrzeit in Sekunden)
|
||||
|
||||
Die Regelung und Managerkommunikation verwenden fuer diese Werte eine interne
|
||||
Zustandsablage und funktionieren auch ohne angelegte Diagnosevariablen weiter.
|
||||
@@ -96,7 +98,7 @@ verzoegert, damit keine synchrone Manager-Verbraucher-Endlosschleife entsteht.
|
||||
`WarmwasserReglerTest.php` prueft Leistungsstufen, PT1, Energieberechnung,
|
||||
Zeitplan, thermische Prognose und die zweistufigen Legionellengrenzen.
|
||||
`WarmwassererwaermerModulstrukturTest.php` prueft Metadaten, Formular,
|
||||
20 Properties, bedarfsgesteuerte Diagnosevariablen, Schnittstellenvertrag und
|
||||
19 Properties, bedarfsgesteuerte Diagnosevariablen, Schnittstellenvertrag und
|
||||
Break-before-make-Schaltung.
|
||||
|
||||
## Migration
|
||||
|
||||
@@ -109,6 +109,23 @@ final class WarmwasserRegler
|
||||
return $bisher + $alpha * ($eingang - $bisher);
|
||||
}
|
||||
|
||||
public static function restzeitBisLastwechsel(
|
||||
int $letzterLastwechsel,
|
||||
int $jetzt,
|
||||
int $sperrzeitSekunden
|
||||
): int {
|
||||
if ($sperrzeitSekunden < 0) {
|
||||
throw new InvalidArgumentException('Die Lastwechsel-Sperrzeit darf nicht negativ sein.');
|
||||
}
|
||||
if ($letzterLastwechsel <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$verstrichen = max(0, $jetzt - $letzterLastwechsel);
|
||||
|
||||
return max(0, $sperrzeitSekunden - $verstrichen);
|
||||
}
|
||||
|
||||
public static function energieKWh(float $leistungW, int $dauerSekunden): float
|
||||
{
|
||||
if ($dauerSekunden < 0) {
|
||||
|
||||
@@ -53,6 +53,14 @@ final class WarmwasserReglerTest extends TestCase
|
||||
self::assertEqualsWithDelta(20.4, WarmwasserRegler::pt1(20.0, 30.0, 5, 120), 0.001);
|
||||
}
|
||||
|
||||
public function testLastwechselRestzeitWirdInSekundenBerechnet(): void
|
||||
{
|
||||
self::assertSame(0, WarmwasserRegler::restzeitBisLastwechsel(0, 100, 5));
|
||||
self::assertSame(5, WarmwasserRegler::restzeitBisLastwechsel(100, 100, 5));
|
||||
self::assertSame(2, WarmwasserRegler::restzeitBisLastwechsel(100, 103, 5));
|
||||
self::assertSame(0, WarmwasserRegler::restzeitBisLastwechsel(100, 105, 5));
|
||||
}
|
||||
|
||||
public function testEnergieWirdInKWhBerechnet(): void
|
||||
{
|
||||
self::assertEqualsWithDelta(3.0, WarmwasserRegler::energieKWh(3000.0, 3600), 0.000001);
|
||||
|
||||
@@ -29,14 +29,14 @@ final class WarmwassererwaermerModulstrukturTest extends TestCase
|
||||
self::assertMatchesRegularExpression('/^\{[0-9A-F-]{36}\}$/', $metadaten['id']);
|
||||
}
|
||||
|
||||
public function testAlle20PropertiesSindRegistriertUndImFormularDokumentiert(): void
|
||||
public function testAlle19PropertiesSindRegistriertUndImFormularDokumentiert(): void
|
||||
{
|
||||
$basis = (string) file_get_contents(__DIR__ . '/../libs/VerbraucherBasisTrait.php');
|
||||
$modul = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||
preg_match_all('/RegisterProperty(?:Integer|Float|Boolean|String)\(\'([^\']+)\'/', $basis . $modul, $treffer);
|
||||
$properties = array_values(array_unique($treffer[1]));
|
||||
|
||||
self::assertCount(20, $properties);
|
||||
self::assertCount(19, $properties);
|
||||
|
||||
$formular = (string) file_get_contents(self::MODULPFAD . 'form.json');
|
||||
foreach ($properties as $property) {
|
||||
@@ -44,6 +44,18 @@ final class WarmwassererwaermerModulstrukturTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testRegelungIstEreignisbasiertUndSperrtLastwechselFuenfSekunden(): void
|
||||
{
|
||||
$inhalt = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||
|
||||
self::assertStringContainsString("RegisterPropertyInteger('LastwechselSperrzeit', 5)", $inhalt);
|
||||
self::assertStringNotContainsString("RegisterPropertyInteger('Interval'", $inhalt);
|
||||
self::assertStringNotContainsString("RegisterPropertyInteger('IdleCounterMax'", $inhalt);
|
||||
self::assertStringNotContainsString("ReadPropertyInteger('Interval')", $inhalt);
|
||||
self::assertStringContainsString("'LastwechselFreigabe'", $inhalt);
|
||||
self::assertStringContainsString('LetzteTemperaturberechnung', $inhalt);
|
||||
}
|
||||
|
||||
public function testModulVerwendetAusschliesslichDenVertrag30(): void
|
||||
{
|
||||
$inhalt = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||
|
||||
Reference in New Issue
Block a user