diff --git a/schemas/oefacade.graphql b/schemas/oefacade.graphql new file mode 100644 index 0000000..f4a02ad --- /dev/null +++ b/schemas/oefacade.graphql @@ -0,0 +1,557 @@ +# Scalar-Typen für die GraphQL-Schnittstelle - siehe DateTimeScalarConfig.class +scalar DateTime +scalar Date + +type Query { + allWaehrungen: [Waehrung!]! + waehrungByCurrencyCode(currencyCode: String!): [Waehrung!] + waehrungByCurrencyType(currencyType: String!): [Waehrung!] + sensors: [Sensor] + sensor(id: ID!): Sensor + measureConceptList(measurementConceptId: ID!, namePattern: String) : [MeasureConcept] + findObservation( measurementConceptId: ID!, sensorName: String, observationVariableNamePattern:String, startTime:String, endTime:String) : [Observation] + findGapsInObservations (measurementConceptId: ID!,sensorId: ID, startTime: String, endTime: String, gapDurationMinutes: Int, turnOfMonth: Boolean): [ObservationGap] + findNearestObservations(measurementConceptId: ID!,sensorName: String, observationVariableName: String, variableUnitIdList: [ID], timeUTC: String,timeOrder: String): [ObservationDetails] + findObservationSummaryList(measurementConceptId: ID!): [ObservationSummary] + findObservationVariableSummaryList(measurementConceptId: ID!): [ObservationVariableSummary] + getObservationVariableUnitData(observationUnitList: [ID], observationVariableName: String, unitName: String ): [ObservationVariableUnitData]! + getIndexes(indexFamilyId: Int, id: Int, name: String): [Index] + getIndexValues(indexId: Int, periodFrom: String, periodTo: String): [IndexValue] + reportMC(siteId: Int!, tenant: String!, dateTimeFromIsoUtc: String, dateTimeToIsoUtc: String): [MesskonzeptRow] + reportEichfristen(MKA_ANLAGENR: String, MKA_NAME: String, EICHJAHR: Int): [EichfristenRow] + getMBusConfiguration(m2mId: Int!): M2MConfiguration! + getMKAList: [MKA] + getCustomerAccountHistory(ecNumber: String!, monatYYYYMM: String, anzMonateRetour: Int): [CustomerAccountHistory] + getMKAByAnlagenr(mkaAnlagenr: String!): [MKA] + getMKAByName(mkaName: String!): [MKA] + getOpenSolarReport(queryName: String!, params: [ReportParam]): ReportResponse + isAnlagenabrechnungRunning(anlagenNr: String!): Boolean! + getAllRunningInstances(processDefinitionKey: String!): [String] + # -------------------------------------------------------------- + # Abfragen für das "LLM Meter Reading Recording" OERedshift - Beginn + # -------------------------------------------------------------- + # Sucht Sensoren, deren Name mit * beginnt. Liefert Sensor-ID, Name, zugehöriges MeasureConcept (id, name, descr). Das LLM braucht das, um bei mehreren Treffern dem User die MeasureConcept-Auswahl anzubieten. + sensorsForMeterNumber(meterNumber: String!): [SensorInfo!]! + # Liefert den letzten existierenden Messwert (Zählerstand + Zeitpunkt) für einen Sensor. Default-Variable: ENERGY_INST_VAL. Das LLM braucht das, um festzustellen, ob überhaupt ein Anfangsstand existiert. + lastObservation(sensorId: ID!, variableName: String): Observation + # Prüft, ob am angegebenen Tag bereits ein Zählerstand vorhanden ist. Kernregel: Doppelerfassung am selben Tag verhindern. + observationsForDay(sensorId: ID!, date: Date!, variableName: String): [Observation!]! + # Prüft für den Zeitraum from-to, ob für jeden Monatswechsel jeweils ein Wert kurz vor und kurz nach 00:00 UTC existiert. Liefert eine Liste der fehlenden Monate/Seiten (before/after midnight).Das ist die zentrale Validierung für die Ultimo-Regel. + monthlyGapCheck(sensorId: ID!, from: DateTime!, to: DateTime!, variableName: String): [MonthGap!]! + # Listet die verfügbaren ObservationVariables und zur Variable gehörige Unit für einen Sensor. Alphabetisch sortiert nach Variable-Name. Das LLM braucht das, um dem User die Auswahl der Variable zu ermöglichen (z.B. ENERGY_INST_VAL, ENERGY_DAY_VAL, POWER_VAL, etc.) + availableVariableUnits(sensorId: ID!): [VariableUnitInfo!]! + # -------------------------------------------------------------- + # Abfragen für das "LLM Meter Reading Recording" - Ende + # -------------------------------------------------------------- + +} + +# Eingabetyp für die Parameter des Reports +input ReportParam { + key: String! + value: String! +} +# ReportResponse is a generic response for reports with: title, headers and data (OpenSolar Reports +type ReportResponse { + title: String + headers: [String] + data: [ReportData] +} +# das Ergebnis des Reports sind 0-n Zeilen (ReportData) mit Werten (values) +type ReportData { + values: [String] +} + +type MKA { + id: ID! + dbkUid: String! + updateKey: String! + updateCount: Int! + updateUid: String! + firstApprovalUid: String! + finalApprovalUid: String! + lockUid: String + firstApprovalStamp: String! + finalApprovalStamp: String! + lockStamp: String + status: Int! + rekey01: String! + rekey02: String! + mkaAnlagenr: String! + mkaGiltab: String! + mkaStatus: String! + mkaMonatVon: Int! + mkaName: String! + mkaDatumIbn: String + mkaStichtag: String! + mkaZession: Int + mkaAnmerkVm: String + mkaAnmerkNo: String + mkaAnmerkFl: String + mkaAdresse: String + mkaPlz: String + mkaVerantwort: String + mkaGenehmMail: String +} + +type CustomerAccountHistory { + building: String + teilnehmer: String + meteringpoint: String + mandatreferenz: String + monat: String + akontoEUR: Float + istVerbrauch: Float + unitVerbrauch: String + preisUnit: Float + unitPreis: String + preisVerbrauchEUR: Float + saldoEUR: Float + fehler: String +} + +type Mutation { + createWaehrung(waehrung: WaehrungInput!): Waehrung! + updateWaehrung(id: ID!, waehrung: WaehrungInput!): Waehrung! + deleteWaehrung(id: ID!): Boolean! + createSensor(name: String!, nameExtern: String, description: String, measureConceptId: ID!): Sensor + updateSensor(id: ID!, name: String!, nameExtern: String, description: String, measureConceptId: ID!): Sensor + deleteSensor(id: ID!): String + createObservation ( measureConceptId: ID! ,sensorNameLike:String, observationVariableNameLike: String, observationVariableUnitId: ID, observationTimeString: String, userName:String, meterValue:Float, imageFileName: String): Observation + # -------------------------------------------------------------- + # Abfragen für das "LLM Meter Reading Recording" OERedshift - Beginn + # -------------------------------------------------------------- + # Die Haupt-Mutation für einen einzelnen Zählerstand. Input: sensorId, moment, value (metervalue), variableUnit (optional, default ENERGY_INST_VAL). Serverseitig erzwingt sie die Regel "kein zweiter Wert am selben Tag" und gibt einen klaren Fehler zurück, falls verletzt. Sonst wird Observation erzeugt. + recordMeterReading(input: MeterReadingInput!): MeterReadingResult! + # Batch-Mutation für eine Serie von Ultimo-Ständen. Input: sensorId, variableUnit, eine zeitlich sortierte Liste von {month: YearMonth, meterValue: Float}. Es sollen Observations erzeugt werden. + recordUltimoReadings(input: UltimoReadingsInput!): UltimoResult! + # Setzt den Anfangszählerstand. Input: sensorId, startDate, startValue (default 0), variableUnit. Wird gebraucht, wenn lastObservation keinen Treffer liefert. Getrennt von recordMeterReading, damit das LLM den Initialfall explizit steuern kann. + # es wird auch erlaubt einen Erststand VOR den aktuell ersten Stand zu setzen. Oft gebraucht wenn Zählereinbau bei 0, der erste Wert in der DB aber schon Zäherstand > 0 hat + initializeMeterReading(input: InitMeterInput!): MeterReadingResult! + # -------------------------------------------------------------- + # Abfragen für das "LLM Meter Reading Recording" OERedshift - Ende + # -------------------------------------------------------------- + +} + +input MeterReadingInput { + sensorId: ID! + moment: DateTime! + value: Float! + variableName: String + variableUnit: String +} + +input InitMeterInput { + sensorId: ID! + startDate: Date! + startValue: Float = 0 + variableName: String + variableUnit: String +} + +input UltimoReadingsInput { + sensorId: ID! + variableName: String + variableUnit: String + readings: [UltimoReadingEntry!]! +} + +input UltimoReadingEntry { + month: String! # YearMonth im Format "YYYY-MM" + meterValue: Float! +} + +input WaehrungInput { + dbkUid: String! + updateKey: String! + updateName: String! + updateCount: Int! + firstApprovalUid: String! + finalApprovalUid: String! + lockUid: String + firstApprovalStamp: String! + finalApprovalStamp: String! + lockStamp: String + status: Int! + currencyCode: String! + currencyType: String! + isEuroCurrency: String! + decimalPlaces: Int! +} + +type Index { + id: Int + indexFamilyId: Int + isInactive: Boolean + name: String + isCombined: Boolean + isCapitalPreservationModel: Boolean + minValue: Float + maxValue: Float + maxDeltaIncrease: Float + maxDeltaDecrease: Float + publicationPeriodDuration: Int + publicationPeriodDurationUnit: Int + publicationReferenceDate: String + publicationSchedulingReferenceDate: String + schedulingPeriodDuration: Int + schedulingPeriodDurationUnit: Int + schedulingReferenceDate: String + decimals: Int + hasUnreliablePublicationSchedule: Boolean + tentativeValuePeriodRange: Int + tentativeValuePeriodJumping: Int + created: String + modified: String +} + + +type IndexValue { + id: Int + name: String + periodBegin: String + value: Float +} + +type EichfristenRow { + MKA_ANLAGENR: String + MKA_NAME: String + BSTAETTE: Int + MANDANT: String + MK_EICHUNG: String + EICHJAHR: Int + MK_ZAEHLER: String + MK_HAUPTKATEGORIE: String + MK_KATEGORIE: String + MK_ZAEHLER_GUI: String + MK_SERIALNR: String + MK_MBUS_PRIM: String + MK_MBUS_SEC: String + MK_OBSERVATION_VARIABLE: String + HERSTELLER: String + EINHEIT_KBEZ: String + EINHEIT_BEZ: String + E_20074_DBK: String + ZAEHLER_NEU: String + MK_GILT_AB: String + MK_GILT_BIS: String +} + +type MesskonzeptRow { + zaehler: String + einheit: String + zaehlerArt: String + zaehlerTyp: String + observationVariable: String + rollVor: Int + rollNach: Int + m2m: String + interf: String + serial: String + mbusPrim: String + mbusSec: String + plz: String + strasse: String + objektNr: Int + herstellerBezeich: String + bemerk1: String + bemerk2: String + inputWert: Int + kategorie: String + messwTyp: String + intpolArt: String + intpolIntval: Float + extpolIntval: Float + formel: String + raster: String + rasterStart: String + hauptkategorie: String + zaehlerGui: String + sichtbarNurOE: String + wertKonstant: Float + datumIbn: String + initialStand: Float + verrechnung: String + eichung: String + giltAb: String + giltBis: String +} + +type Observation { + id: ID! + sensor: Sensor! + observationVariableUnit: ObservationVariableUnit! + measureType: MeasureType! + observationRaster: ObservationRaster! + contextHashValue: String + moment: String! + quality: String! + status: Int! + value: Float! + meterValue: Float! +} + +type ObservationGap { + resultRow: Int! + observation: Observation! + prevMoment: String! + gapDurationFormated: String! + gapDuration: Int! +} + + +type ObservationDetails { + resultRow: Int! + observation: Observation! + observationVariableName: String! + unitName : String! +} + +type ObservationVariableUnit { + id: ID! + observationVariable: ObservationVariable! + unit: Unit! +} + + +type ObservationVariableUnitData { + observationVariableUnitId: ID! + observationVariableName: String! + unitName: String! +} + + +type ObservationVariable { + id: ID! + name: String! + description: String +} + +type ObservationRaster { + id: ID! + unit: Unit! + anzahl: Float! + name: String! + description: String +} + +type ObservationContext { + hashValue: ID! + measureConcept: MeasureConcept! + sensor: Sensor + m2m: String + moment: String! + binaryMessage: String + decodedMessage: String +} + +type Sensor { + id: ID! + measureConcept: MeasureConcept! + name: String! + nameExtern: String + description: String +} + +type MeasureConcept { + id: ID! + name: String! + description: String + sensors: [Sensor] +} + +type MeasureType { + id: ID! + name: String! + description: String +} + +type Unit { + id: ID! + name: String! + description: String +} + +type ObservationSummary { + mcId: ID! + mcName: String! + sensorId: ID! + sensorName: String! + firstObservation: String! + lastObservation: String! + countObservation: Int + measurementDays: Int + integration: String! + timeliness: String! +} + +type ObservationVariableSummary { + mcId: ID! + mcName: String! + sensorId: ID! + sensorName: String! + variableId: ID! + variableName: String! + firstObservation: String! + lastObservation: String! + countObservation: Int! + minMeterValue: Float + maxMeterValue: Float + distinctMeterValueCount: Int +} + + + +type M2MConfiguration { + name: String + alias: String + m2m: String + type: String + infoText: String + notificationInterval: Int + notificationQueueName: String + observationQueueName: String + readingFrequencySeconds: Int + queuingIntervalSeconds: Int + iterations: Int + calibrations: [Calibration] + scalings: [Scaling] + communicationParameters: CommunicationParameters + serialCommunicationParameters: SerialCommunicationParameters + winsockCommunicationParameters: WinsockCommunicationParameters + sqs: String + activeMQ: String + activeMQParameters: ActiveMQParameters + awsMQTT: String + paho: String + pahoLocal: String + awsMqttParameters: AwsMqttParameters + pahoParameters: PahoParameters + searchIntervalSeconds: Int + meterDefinitions: [MeterDefinition] +} + +type Calibration { + observationVariable: String + calibrationValue: Float +} + +type Scaling { + unitOld: String + unitNew: String + scaleFactor: Float +} + +type CommunicationParameters { + communicationType: String + timeOutInMillis: Int + retryCount: Int + continueIfError: String + testCommunication: String +} + +type SerialCommunicationParameters { + portName: String + baudRate: Int + dataBits: Int + stopBits: Int + parity: Int + flowControl: Int +} + +type WinsockCommunicationParameters { + inetHost: String + inetPort: Int +} + +type ActiveMQParameters { + activeMQAddr: String +} + +type AwsMqttParameters { + reportingIntervalMillisec: Int + awsKeyLocation: String + awsKeyPrefix: String +} + +type PahoParameters { + reportingIntervalMillisec: Int + pahoAddress: String + pahoUser: String + pahoPassword: String + pahoTopicId: String +} + +type MeterDefinition { + primaryAddress: String + addressString: String + meterType: String + readIntervalSeconds: Int +} + +type Waehrung { + id: ID! + dbkUid: String! + updateKey: String! + updateName: String! + updateCount: Int! + firstApprovalUid: String! + finalApprovalUid: String! + lockUid: String + firstApprovalStamp: String! + finalApprovalStamp: String! + lockStamp: String + status: Int! + currencyCode: String! + currencyType: String! + isEuroCurrency: String! + decimalPlaces: Int! +} + +# --------------------------------------------------- +# Hilfstypen für das "LLM Meter Reading Recording" OERedshift - Begin +# --------------------------------------------------- +type VariableUnitInfo { + variableUnitId: ID! + variableName: String! + unitName: String! +} + +type SensorInfo { + sensorId: ID! + sensorName: String! + sensorNameExtern: String + descr: String + measureConcept: MeasureConceptInfo! +} + +type MeasureConceptInfo { + id: ID! + name: String! + descr: String +} + +type MonthGap { + yearMonth: String! # z.B. "2025-10" + missingBeforeMidnight: Boolean! + missingAfterMidnight: Boolean! +} +type ValidationError { + code: String! # z.B. DUPLICATE_DAY, MISSING_GAP, NO_INITIAL_READING + message: String! + details: String # JSON-String mit weiteren Informationen, z.B. die betroffenen Tage bei DUPLICATE_DAY oder MISSING_GAP +} +type UltimoResult { + success: Boolean! + created: [Observation!]! + errors: [ValidationError!] +} +type MeterReadingResult { + success: Boolean! + observation: Observation + errors: [ValidationError!] +} +# --------------------------------------------------- +# Hilfstypen für das "LLM Meter Reading Recording" - Ende +# ---------------------------------------------------