$daten */ public static function pruefeManagerdaten(array $daten): void { self::pruefeSchluessel($daten, ['Kopf', 'Betriebsart', 'Sollleistung_W'], 'Managerdaten'); self::pruefeKopf($daten['Kopf']); self::pruefeBetriebsart($daten['Betriebsart']); if ($daten['Sollleistung_W'] !== null && !is_int($daten['Sollleistung_W'])) { throw new InvalidArgumentException('Sollleistung_W muss eine Ganzzahl oder null sein.'); } } /** * @param array $daten */ public static function pruefeVerbraucherdaten(array $daten): void { self::pruefeSchluessel( $daten, [ 'Kopf', 'Betriebsart', 'PrioritaetPV', 'PrioritaetPeak', 'Leistungswerte_W', 'AenderungMoeglich', 'Verfuegbar', 'Istleistung_W', 'Leistungsquelle', 'Zustand', ], 'Verbraucherdaten' ); self::pruefeKopf($daten['Kopf']); self::pruefeBetriebsart($daten['Betriebsart']); self::pruefePrioritaet($daten['PrioritaetPV'], 'PrioritaetPV'); self::pruefePrioritaet($daten['PrioritaetPeak'], 'PrioritaetPeak'); self::pruefeLeistungswerte($daten['Leistungswerte_W']); if (!is_bool($daten['AenderungMoeglich'])) { throw new InvalidArgumentException('AenderungMoeglich muss ein Wahrheitswert sein.'); } if (!is_bool($daten['Verfuegbar'])) { throw new InvalidArgumentException('Verfuegbar muss ein Wahrheitswert sein.'); } self::pruefeIstleistung($daten['Istleistung_W'], $daten['Leistungsquelle']); self::pruefeZustand($daten['Zustand']); } /** * @param mixed $kopf */ private static function pruefeKopf($kopf): void { if (!is_array($kopf)) { throw new InvalidArgumentException('Kopf muss ein Objekt sein.'); } self::pruefeSchluessel( $kopf, ['Version', 'AbsenderID', 'EmpfaengerID', 'Zeitpunkt'], 'Kopf' ); if ($kopf['Version'] !== self::VERSION) { throw new InvalidArgumentException('Die Vertragsversion wird nicht unterstuetzt.'); } if (!is_int($kopf['AbsenderID']) || $kopf['AbsenderID'] <= 0) { throw new InvalidArgumentException('AbsenderID muss eine positive Ganzzahl sein.'); } if (!is_int($kopf['EmpfaengerID']) || $kopf['EmpfaengerID'] <= 0) { throw new InvalidArgumentException('EmpfaengerID muss eine positive Ganzzahl sein.'); } if (!is_int($kopf['Zeitpunkt']) || $kopf['Zeitpunkt'] < 0) { throw new InvalidArgumentException('Zeitpunkt muss eine nicht negative Unixzeit sein.'); } } /** @param mixed $betriebsart */ private static function pruefeBetriebsart($betriebsart): void { if (!is_string($betriebsart) || !in_array( $betriebsart, [self::BETRIEBSART_PV, self::BETRIEBSART_PEAK], true )) { throw new InvalidArgumentException('Betriebsart muss PV oder Peak sein.'); } } /** * @param mixed $prioritaet */ private static function pruefePrioritaet($prioritaet, string $name): void { if (!is_int($prioritaet) || $prioritaet < 0) { throw new InvalidArgumentException($name . ' muss eine Ganzzahl ab 0 sein.'); } } /** * @param mixed $leistungswerte */ private static function pruefeLeistungswerte($leistungswerte): void { if (!is_array($leistungswerte) || !self::istListe($leistungswerte)) { throw new InvalidArgumentException('Leistungswerte_W muss eine Liste sein.'); } $letztesMaximum = null; foreach ($leistungswerte as $index => $eintrag) { if (is_int($eintrag)) { $minimum = $eintrag; $maximum = $eintrag; } elseif (is_array($eintrag)) { self::pruefeSchluessel($eintrag, ['Von_W', 'Bis_W'], 'Leistungsbereich'); if (!is_int($eintrag['Von_W']) || !is_int($eintrag['Bis_W'])) { throw new InvalidArgumentException('Bereichsgrenzen muessen Ganzzahlen sein.'); } if ($eintrag['Von_W'] > $eintrag['Bis_W']) { throw new InvalidArgumentException('Von_W darf nicht groesser als Bis_W sein.'); } $minimum = $eintrag['Von_W']; $maximum = $eintrag['Bis_W']; } else { throw new InvalidArgumentException( 'Leistungswert an Position ' . $index . ' ist weder Ganzzahl noch Bereich.' ); } if ($letztesMaximum !== null && $minimum <= $letztesMaximum) { throw new InvalidArgumentException( 'Leistungswerte_W muss aufsteigend und ohne Ueberschneidungen sein.' ); } $letztesMaximum = $maximum; } } /** * @param mixed $istleistung * @param mixed $leistungsquelle */ private static function pruefeIstleistung($istleistung, $leistungsquelle): void { if (!is_int($leistungsquelle) || !in_array( $leistungsquelle, [ self::LEISTUNGSQUELLE_NICHT_VORHANDEN, self::LEISTUNGSQUELLE_BERECHNET, self::LEISTUNGSQUELLE_GEMESSEN, ], true )) { throw new InvalidArgumentException('Leistungsquelle muss 0, 1 oder 2 sein.'); } if ($leistungsquelle === self::LEISTUNGSQUELLE_NICHT_VORHANDEN) { if ($istleistung !== null) { throw new InvalidArgumentException('Ohne Leistungsquelle muss Istleistung_W null sein.'); } return; } if (!is_int($istleistung) && !is_float($istleistung)) { throw new InvalidArgumentException('Bei berechneter oder gemessener Leistung ist ein Zahlenwert erforderlich.'); } if (is_float($istleistung) && !is_finite($istleistung)) { throw new InvalidArgumentException('Istleistung_W muss endlich sein.'); } } /** * @param mixed $zustand */ private static function pruefeZustand($zustand): void { if (!is_array($zustand) || !self::istListe($zustand)) { throw new InvalidArgumentException('Zustand muss eine Liste sein.'); } $kennungen = []; $sollleistungVorhanden = false; foreach ($zustand as $eintrag) { if (!is_array($eintrag)) { throw new InvalidArgumentException('Jeder Zustandseintrag muss ein Objekt sein.'); } self::pruefeSchluessel( $eintrag, ['Kennung', 'Art', 'Wert', 'Einheit'], 'Zustandseintrag', ['Text'] ); if (!is_string($eintrag['Kennung']) || trim($eintrag['Kennung']) === '') { throw new InvalidArgumentException('Kennung muss ein nicht leerer Text sein.'); } if (isset($kennungen[$eintrag['Kennung']])) { throw new InvalidArgumentException('Kennungen im Zustand muessen eindeutig sein.'); } $kennungen[$eintrag['Kennung']] = true; if (!is_string($eintrag['Art']) || !in_array( $eintrag['Art'], ['Istwert', 'Sollwert', 'Status', 'Stoerung'], true )) { throw new InvalidArgumentException('Art des Zustandseintrags ist ungueltig.'); } if (!is_string($eintrag['Einheit'])) { throw new InvalidArgumentException('Einheit muss ein Text sein.'); } if (array_key_exists('Text', $eintrag) && !is_string($eintrag['Text'])) { throw new InvalidArgumentException('Text im Zustandseintrag muss ein Text sein.'); } if (!self::istZustandswert($eintrag['Wert'])) { throw new InvalidArgumentException('Wert im Zustandseintrag hat einen ungueltigen Typ.'); } if ($eintrag['Art'] === 'Stoerung' && !is_bool($eintrag['Wert'])) { throw new InvalidArgumentException('Eine Stoerung muss true oder false melden.'); } if ($eintrag['Kennung'] === 'Sollleistung_W') { if ($eintrag['Art'] !== 'Sollwert' || $eintrag['Einheit'] !== 'W') { throw new InvalidArgumentException('Sollleistung_W muss als Sollwert in W gemeldet werden.'); } if ($eintrag['Wert'] !== null && !is_int($eintrag['Wert'])) { throw new InvalidArgumentException('Sollleistung_W im Zustand muss Ganzzahl oder null sein.'); } $sollleistungVorhanden = true; } } if (!$sollleistungVorhanden) { throw new InvalidArgumentException('Der gemeinsame Zustandseintrag Sollleistung_W fehlt.'); } } /** * @param mixed $wert */ private static function istZustandswert($wert): bool { if ($wert === null || is_string($wert) || is_bool($wert) || is_int($wert)) { return true; } return is_float($wert) && is_finite($wert); } /** * @param array $wert */ private static function istListe(array $wert): bool { return $wert === [] || array_keys($wert) === range(0, count($wert) - 1); } /** * @param array $daten * @param list $pflicht * @param list $optional */ private static function pruefeSchluessel( array $daten, array $pflicht, string $bezeichnung, array $optional = [] ): void { $vorhanden = array_keys($daten); $erlaubt = array_merge($pflicht, $optional); $fehlend = array_diff($pflicht, $vorhanden); $unbekannt = array_diff($vorhanden, $erlaubt); if ($fehlend !== [] || $unbekannt !== []) { throw new InvalidArgumentException($bezeichnung . ' enthaelt fehlende oder unbekannte Felder.'); } } }