JSON-Format für Anfragen zum Generieren von Messwertkonfigurationen

In diesem Leitfaden wird das JSON-Anfrageformat für den /api/v1/generate_metrics_config-Endpunkt des Tools „Metrics Configuration Generator“ (MCG) beschrieben. In diesem Format können Sie eine Telemetriekampagne definieren, indem Sie die Datenerhebung, die Verarbeitung auf dem Gerät und die Berichterstellung in einer für Menschen lesbaren Struktur angeben.

Das MCG-Tool validiert dieses JSON-Objekt und sucht nach Problemen wie Typkonflikten, Zirkelbezügen oder nicht definierten Referenzen. Anschließend wird es in eine MetricsConfig-Protokollzwischenspeichernachricht (protobuf) kompiliert. Diese MetricsConfig-Nachricht ist das binäre Format, das der Telemetriedienst auf dem Gerät ausführt, um die Kampagne auszuführen.

Voraussetzungen:Sie sollten sich mit JSON-Schemas, Protobuf und grundlegenden Datenstrukturen auskennen. Eine konzeptionelle Übersicht finden Sie unter Konzepte für die Messwertkonfiguration.

Konfigurationsbeschreibung verfassen

So erstellen Sie eine Kampagne zum Erfassen von Messwerten:

  1. Datenquellen angeben: Legen Sie fest, woher Ihre Daten stammen.
  2. Logik und Verarbeitung definieren: Richten Sie Regeln dafür ein, wann Daten erhoben und wie sie verarbeitet werden sollen.
  3. Ausgabe erstellen: Die verarbeiteten Daten werden in einer endgültigen Nachricht zusammengefasst.
  4. Felder der obersten Ebene: Fügen Sie Felder der obersten Ebene wie UUID, Signaldefinitionen und Lebenszyklussteuerung hinzu.

Beispiel: Bericht zur Durchschnittsgeschwindigkeit

In dieser Anleitung wird anhand eines Beispiels gezeigt, wie alle Komponenten zusammenarbeiten. Es wird ein Bericht erstellt, in dem die durchschnittliche Fahrzeuggeschwindigkeit pro Minute berechnet wird. Dazu werden eine Datenquelle (SpeedSource) zum Erfassen von Geschwindigkeitsdaten, Trigger (OnNewSpeed, EveryMinute) zum Steuern des Ausführungsablaufs, ein Aggregator (SpeedAggregator) zum Berechnen des Durchschnitts und eine Konfiguration für Messwertberichte (MinuteReport) zum Verpacken des Ergebnisses definiert. Die Beispiele in den aufklappbaren Abschnitten bauen auf diesem Szenario auf.

Datenquellen angeben

Telemetrie unterstützt das Erheben von Daten von SDV-Diensten (über die SDV-Middleware) und von Verlagen und Webpublishern, die auf der Configurable Publisher Registry basieren.

Wenn Sie Daten in SDV verwenden möchten, definieren Sie eine Datenquelle (Konzept) und fügen Sie sie dem Array data_sources hinzu.

Felder eines Datenquellenobjekts (Element in der Liste data_sources)
name Ein benutzerdefinierter String, der diese Datenquelle in der Messwertkonfiguration identifiziert.
source_identifier Die Kennung, die zum Erkennen des Dienstes verwendet wird. Weitere Informationen finden Sie unter source_identifier-Format.
connection_type SUBSCRIPTION für einen kontinuierlichen Datenstream (erforderlich für Datentrigger) oder ON_DEMAND für das On-Demand-Abrufen (weitere Informationen finden Sie unter Datenquellen konfigurieren).
optional
configuration

Nur RPC und konfigurierbares Publisher-Register. Ein Objekt zum Konfigurieren der Datenquelle mit den folgenden Feldern:

type_url Der FQN der Protobuf-Nachricht der Konfiguration.
value_json,
value_textproto,
oder value
Die Nutzlast im JSON-, Textproto- oder Base64-Format.
Felder für den Verbindungstyp SUBSCRIPTION
optional
sub_sampling_interval_ms
Nur Pub/Sub: Eine nicht negative Ganzzahl (Millisekunden), um die Häufigkeit von Nachrichten zu drosseln, indem das Mindestintervall zwischen Nachrichten angegeben wird.
optional
fetch_last_message
(Standard: false)
Nur Pub/Sub. Boolescher Wert. Bei true wird beim Herstellen der Verbindung die letzte Nachricht abgerufen.

Nicht alle Optionen sind für alle Arten von Datenquellen verfügbar. Weitere Informationen

Format von „source_identifier“

Der Telemetriedienst akzeptiert mehrere Quell-ID-Formate. Eine Übersicht finden Sie unter Datenquellendefinition in Messwertkonfigurationen.

MCG leitet den Protobuf-Nachrichtentyp nur dann aus source_identifier ab, wenn das Format „Unit Type Name“ verwendet wird. Wenn Sie FQIN oder einen benutzerdefinierten Namen (aus der Configurable Publisher Registry) verwenden, kann MCG den Typ nicht ableiten. In diesen Fällen müssen Sie data_source_message_types angeben. Wenn der Typ nicht in Ihrem Katalog enthalten ist, müssen Sie auch seine Definition in descriptor_protos angeben.

Beispiel: Datenquelle definieren

In diesem Beispiel wird die Fahrzeuggeschwindigkeit gemeldet. Sehen Sie zuerst im VSIDL-Katalog nach, um den Dienst zu ermitteln, der diese Daten veröffentlicht.

Suchen Sie im Beispielkatalog in der SDV-Codebasis nach dem relevanten Dienst. Geben Sie entsprechend dem Format von source_identifier den Protobuf-Nachrichtentyp mcg.test.subpkg.speed_msg an. Da die Geschwindigkeit in der Regel häufig veröffentlicht wird, verwenden Sie sub_sampling_interval_ms, um die Aktualisierungen auf eine Nachricht pro Sekunde zu beschränken:

{
  "name": "SpeedSource",
  "source_identifier": "mcg.test.subpkg.speed_msg",
  "connection_type": "SUBSCRIPTION",
  "sub_sampling_interval_ms": 1000 // Limit updates to 1 per second
}

Logik und Verarbeitung definieren

Die Logik wird von zwei Komponenten übernommen, die zusammenarbeiten: Mit Triggern (Konzept) wird definiert, wann etwas passiert. Aggregatoren (Konzept) definieren, wie Daten basierend auf diesen Triggern verarbeitet werden. Da Ausdrücke (Konzept) für Triggerbedingungen und Aggregationslogik von entscheidender Bedeutung sind, wird in diesem Abschnitt zuerst beschrieben, wie sie geschrieben werden.

Ausdrücke

Mit Ausdrücken können Sie Berechnungen und Bedingungen in einer für Menschen lesbaren Syntax definieren. MCG kompiliert diese Strings in ein ausführbares Format, das für die On-Device-Auswertung optimiert ist.

Mit Ausdrücken lassen sich arithmetische Berechnungen, logische Bedingungen und Datenvergleiche darstellen. Die vollständige Syntax, einschließlich Operatoren und Funktionen, finden Sie unter Syntax für Ausdrücke.

Datenaktualität:Wenn in einem Ausdruck auf eine Datenquelle zugegriffen wird, hängt das Abrufverhalten vom Verbindungstyp ab:

  • SUBSCRIPTION: Verwendet die vom Telemetriedienst zwischengespeicherte Nachricht last received. Hinweis: Wenn sub_sampling_interval_ms festgelegt ist, kann dies von der absolut neuesten veröffentlichten Nachricht abweichen.
  • ON_DEMAND: Löst einen sofortigen Aufruf aus, um die aktuelle Nachricht vom Dienst abzurufen.

Typeinschränkungen

  • Arrays:Der direkte Zugriff auf Arrayindexe (z. B. my_data_source.my_array[0]) wird nicht unterstützt.
  • Typsicherheit:Achten Sie darauf, dass Sie kompatible Typen vergleichen. Vergleichen Sie beispielsweise kein String-Feld mit einer Liste von Ganzzahlen.

Beispiel: Ausdrücke

Im Beispiel muss der Geschwindigkeitswert extrahiert werden, um den Durchschnitt zu berechnen. Außerdem muss ermittelt werden, ob das Fahrzeug die Geschwindigkeitsbegrenzung (über 100 km/h) überschreitet, um den bedingten Trigger auszulösen. Die Feldnamen (in diesem Fall speed) finden Sie in der Protobuf-Nachrichtendefinition, die von der Datenquelle verwendet wird. Die folgenden Ausdrücke bewirken dies:

  • SpeedSource.speed: Ruft den Wert des Felds speed aus der Datenquelle SpeedSource ab.
  • SpeedSource.speed > 27.7: Ergibt true, wenn die Geschwindigkeit höher als 27,7 m/s (ca.100 km/h) ist.

Trigger: Definieren, wann Aktionen ausgeführt werden

Mit Triggern wird definiert, wann Aktionen ausgeführt werden, z. B. wenn ein Aggregator ausgewertet, ein Bericht generiert oder der Erfassungslebenszyklus gesteuert wird. Fügen Sie alle definierten Trigger dem triggers-Array der obersten Ebene hinzu.

Felder eines Triggerobjekts (Element in der Liste triggers)
name Eine eindeutige Kennung für diesen Trigger in der Messkonfiguration.
periodic
data
conditional
Sie müssen genau eines dieser Felder angeben, um das Verhalten zu definieren.

Datentrigger

Wird ausgelöst, wenn eine SUBSCRIPTION-Datenquelle eine neue Nachricht (Konzept) bereitstellt.

Felder des data-Objekts (in einem Trigger)
source_name Die name des data_source, auf die dieser Trigger reagiert.

Beispiel: Datentrigger

Im Beispiel wird die Berechnung der Durchschnittsgeschwindigkeit jedes Mal aktualisiert, wenn SpeedSource eine neue Nachricht veröffentlicht. Dieser Datentrigger wird jedes Mal ausgelöst, wenn Folgendes passiert:

{
  "name": "OnNewSpeed",
  "data": {
    "source_name": "SpeedSource" // Reference to the defined data source
  }
}

Regelmäßiger Trigger

Wird in regelmäßigen Abständen ausgelöst (Konzept).

Felder des periodic-Objekts (in einem Trigger)
period_ms Eine nicht negative Zahl, die das Intervall in Millisekunden definiert.

Beispiel: Regelmäßiger Trigger

Im Beispiel ist ein Bericht pro Minute erforderlich. Dieser periodische Trigger wird alle 60.000 ms ausgelöst,um den Bericht zu generieren:

{
  "name": "EveryMinute",
  "periodic": {
    "period_ms": 60000 // 60,000 ms = 60 seconds
  }
}

Bedingungstrigger

Wird ausgelöst, wenn ein Ausdruck (Konzept) ausgewertet wird. Für die Auswertung sind ein oder mehrere übergeordnete Trigger erforderlich. Das ist oft ein Datentrigger für die Datenquellen oder Aggregatoren im Ausdruck oder ein periodischer Trigger zum Abrufen von Daten.

Felder des conditional-Objekts (in einem Trigger)
triggers Ein Array mit mindestens einem übergeordneten Triggernamen. Wenn ein übergeordneter Trigger ausgelöst wird, wertet der bedingte Trigger den Ausdruck aus.
expression Der auszuwertende Ausdruck. Weitere Informationen finden Sie unter Ausdrücke.
condition_type Gibt an, wann der Trigger ausgelöst werden soll, basierend auf der Auswertung des Ausdrucks.
Bedingungstypen

Das condition_type-Dictionary muss genau einen der verfügbaren Bedingungstypen als Schlüssel enthalten. Weitere Informationen finden Sie unter Bedingungstrigger.

Felder des condition_type-Objekts (schließen sich gegenseitig aus)
is_true

is_false
Wird ausgelöst, wenn ein boolescher Ausdruck zu true oder false ausgewertet wird.
rising_edge

Wenn der Wert numerisch ist, wird das Ereignis ausgelöst, wenn er steigt. Wenn der Ausdruck boolesch ist, wird das Ereignis ausgelöst, wenn sich der Wert von false in true ändert.

Kann ein rising_options-Objekt enthalten (siehe Edge-Optionen).

falling_edge

Wenn der Wert numerisch ist, wird das Ereignis ausgelöst, wenn der Wert sinkt. Wenn der Ausdruck boolesch ist, wird das Ereignis ausgelöst, wenn sich der Wert von true in false ändert.

Kann ein falling_options-Objekt enthalten (siehe Edge-Optionen).

all_changes

Wird ausgelöst, wenn sich das Ergebnis des Ausdrucks vom vorherigen Wert unterscheidet. Wenn Edge-Optionen festgelegt sind, werden nur numerische und boolesche Werte unterstützt.

Kann rising_options, falling_options oder beides enthalten (siehe Edge-Optionen).

Edge-Optionen

Die Objekte rising_options und falling_options haben die folgenden Felder. Falls angegeben, muss der entsprechende Übergang die Anforderung an die Dauer erfüllen. Übergänge ohne angegebene Optionen werden sofort ausgelöst.

Felder für Edge-Optionsobjekte
min_duration_ms Eine nicht negative Zahl (in Millisekunden), die angibt, wie lange die Bedingung im neuen Status erfüllt sein muss, bevor der Trigger ausgelöst wird.
optional
require_exact
Boolescher Wert. Wenn „true“, müssen alle während des Zeitraums veröffentlichten Werte gleich sein, damit der Trigger ausgelöst wird.

Beispiel: Bedingter Trigger

Im folgenden Trigger werden Edge-Optionen verwendet. Die Benachrichtigung wird ausgelöst, wenn die Geschwindigkeit 27,7 m/s überschreitet und mindestens 5 Sekunden lang hoch bleibt:

{
  "name": "SpeedingFor5Seconds",
  "conditional": {
    "triggers": ["OnNewSpeed"],
    "expression": "SpeedSource.speed > 27.7",
    "condition_type": {
      "rising_edge": {
        "rising_options": {
          "min_duration_ms": 5000 // Condition must hold for 5s in new state
        }
      }
    }
  }
}

Aggregatoren: Definieren, wie Daten verarbeitet werden

Verwenden Sie einen Aggregator für die zustandsbehaftete Zwischenverarbeitung von Daten (Konzept). Definieren Sie einen Aggregator und fügen Sie ihn dem Array aggregators hinzu.

Ein Aggregator transformiert Daten und stellt sie anderen Aggregatoren und Berichten zur Verfügung.

Felder eines Aggregators (Element in der Liste aggregators)
name Ein benutzerdefinierter String, der diesen Aggregator identifiziert. Ausdrücke können anhand des Namens auf diesen Aggregator verweisen, um auf seine Ergebnisse zuzugreifen.
trigger_names Ein Array mit einem oder mehreren Triggernamen, die dazu führen, dass diese Aggregation ausgewertet wird.
optional
reset_on_get
Boolesch, Standardwert: „false“. Wenn „true“, setzt das System den Aggregationsstatus zurück, nachdem sein Wert von einem anderen Aggregator, Messwertbericht oder bedingten Trigger abgerufen wurde.
message_builder Definiert die Daten, die gelesen, verarbeitet und zusammengefasst werden sollen. Die Felder der Ausgabenachricht werden dann zu einer Datenquelle für andere Aggregatoren und Berichte. Dabei wird field_assignments verwendet. Jede Zuweisung definiert ein Feld in der Ausgabenachricht.

Nachrichten-Builder

Ein message_builder-Objekt definiert die Struktur der Ausgabenachricht und die Aggregationslogik, die zum Berechnen der Felder verwendet wird. Sie wird sowohl in Aggregatoren als auch in Berichtskonfigurationen verwendet.

Felder eines message_builder-Objekts (im Aggregator oder Bericht)
message_type Der voll qualifizierte Name des Protobuf-Nachrichtentyps für die Ausgabe. Wenn dieser Parameter weggelassen wird, erstellt MCG einen benutzerdefinierten Nachrichtentyp basierend auf den abgeleiteten Ausgabetypen von field_assignments. Verwenden Sie diese Option nur, wenn der Message-Builder Teil eines Messwertberichts ist und Ihr Bericht einer bestimmten, vordefinierten Protobuf-Nachrichtendefinition entsprechen muss.
field_assignments Ein Array von Felddefinitionsobjekten. Jedes Objekt gibt ein Feld in der Ausgabenachricht und die Logik zum Berechnen seines Werts an.
Felder eines Feldzuweisungsobjekts (Element in der Liste field_assignments)
field_name Ein benutzerdefinierter Name für das Feld. Sie gibt den spezifischen Wert innerhalb des Objekts an, wenn in Ausdrücken die Punktnotation verwendet wird (aggregator_name.field_name).
aggregation

Ein Objekt, das definiert, wie der Wert des Felds berechnet wird. Es enthält die folgenden Felder:

@type Die Aggregationsfunktion.

  • avg, min, max, sum, stddev: Standardstatistiken.
  • count: Zählt, wie oft dieser Aggregator ausgelöst wurde.
  • delta: Differenz zwischen dem aktuellen und dem vorherigen Wert.
  • vector: Erstellt eine Liste von Werten (Ringpuffer).
  • none: Übergibt den Rohwert.
expression Der Eingabeausdruck für die Aggregation. Für alle Aggregationstypen außer count erforderlich.
max_length Nur für @type: "vector". Eine optionale Ganzzahl, die die Vektorgröße begrenzt und einen Ringpuffer erstellt.

Beispiel: Aggregator

Im Beispiel werden Statistiken zwischen den Minutenberichten berechnet. Dieser Aggregator wird durch OnNewSpeed ausgelöst, um die Durchschnittsgeschwindigkeit (avg) zu berechnen, Messwerte zu zählen (count) und die letzten fünf Geschwindigkeitswerte zu speichern (vector). Setzen Sie reset_on_get auf true. Dadurch werden die Statistiken jedes Mal zurückgesetzt, wenn MinuteReport sie liest. Für die nächste Minute wird ein neues Erfassungsfenster für den Aggregator gestartet:

{
  "name": "SpeedAggregator",
  "trigger_names": ["OnNewSpeed"], // Update aggregation on new speed data
  "reset_on_get": true, // Reset stats after they are read by the report configuration
  "message_builder": {
    "field_assignments": [
      {
        "field_name": "average_speed",
        "aggregation": {
          "@type": "avg",
          "expression": "SpeedSource.speed"
        }
      },
      {
        "field_name": "speed_reading_count",
        "aggregation": {
          "@type": "count" // Counts triggers (that is, processed speed readings) since last reset
        }
      },
      {
        "field_name": "speed_history_last5",
        "aggregation": {
          "@type": "vector",
          "expression": "SpeedSource.speed",
          "max_length": 5 // Keep last 5 readings
        }
      }
    ]
  }
}

Ausgabe erstellen

Um die endgültige Ausgabe Ihrer Telemetriekampagne zu definieren, fügen Sie dem report_configs-Array (Konzept) Objekte hinzu. Diese Konfigurationen legen fest, wie verarbeitete Daten verpackt und wann sie generiert werden. Sie können mehrere Berichtskonfigurationen in einer Messwertkonfiguration definieren, um Komponenten wiederzuverwenden.

Sie steuern die Berichterstellung mit dem Feld trigger_names. Außerdem können Sie mit report_initial einen Bericht sofort nach der Aktivierung der Konfiguration und mit report_incomplete einen endgültigen Bericht erstellen, wenn die Datenerhebung unterbrochen wird.

Hinweis:Wenn Sie die Verarbeitung mit der Ausgabe verbinden möchten, verwenden Sie den Aggregationstyp none (@type: "none"), um vorab berechnete Werte aus einem Aggregator zu lesen. Da Berichte in der Regel zustandslose Snapshots sind, wird so komplexe zustandsbehaftete Logik in Aggregatoren beibehalten und Berichte werden für die Formatierung reserviert.

Felder eines Berichtskonfigurationsobjekts (Element in der Liste report_configs)
name Ein eindeutiger Name für den Bericht. Dieser Name wird in den generierten Berichtsmetadaten angezeigt.
trigger_names Ein Array von Triggernamen, die dazu führen, dass der Bericht generiert und veröffentlicht wird.
message_builder Weitere Informationen finden Sie unter Message Builder. Dadurch wird der Inhalt des Berichts definiert. Aggregationen werden nur ausgewertet, wenn der Bericht ausgelöst wird. Bei einer Vektoraggregation wird beispielsweise ein Wert pro Bericht hinzugefügt und bei einer Zählaggregation wird die Berichtsnummer gespiegelt.
optional
report_incomplete
(Standard: „false“)
Boolescher Wert. Bei „true“ generiert das System beim Herunterfahren oder wenn die Datenerfassung endet einen Abschlussbericht, auch wenn Daten fehlen.
optional
report_initial
(Standard: „false“)
Boolescher Wert. Wenn „true“, generiert das System sofort einen Bericht, wenn die Messwertkonfiguration aktiviert wird.

Beispiel: Berichtskonfiguration

Definieren Sie schließlich die Berichtskonfiguration für das Beispiel. Sie wird durch EveryMinute ausgelöst. Die berechnete Durchschnittsgeschwindigkeit und die Anzahl der Messwerte werden aus SpeedAggregator mit einer none-Aggregation gelesen, die den vorab aggregierten Wert an den Bericht übergibt:

{
  "name": "MinuteReport",
  "trigger_names": ["EveryMinute"], // Generate report every minute
  "message_builder": {
    "field_assignments": [
      {
        "field_name": "average_speed",
        "aggregation": {
          "@type": "none", // Read the value directly from the aggregator
          "expression": "SpeedAggregator.average_speed"
        }
      },
      {
        "field_name": "reading_count",
        "aggregation": {
          "@type": "none",
          "expression": "SpeedAggregator.speed_reading_count"
        }
      }
    ]
  }
}

Felder der obersten Ebene

Zusätzlich zu den Arrays data_sources, aggregators, triggers und report_configs ist für die Beschreibung einer Messwertkonfiguration ein Verweis auf den Signalkatalog erforderlich. Sie können auch optionale Felder einfügen, um eine bestimmte UUID zuzuweisen und den Erfassungslebenszyklus zu verwalten.

Set-UUID

Jeder MetricsConfig erfordert einen Universally Unique Identifier (UUID). Wenn Sie einen existing_uuid angeben, wird dieser von MCG verwendet. Andernfalls wird ein zufälliger existing_uuid erstellt. Geben Sie einen existing_uuid an, um die Konsistenz über Bereitstellungen und Tools hinweg zu gewährleisten.

Der String muss eine gültige UUID mit Bindestrichen sein, die nur Kleinbuchstaben enthält.

"existing_uuid": "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",

Signaldefinitionen

Zur Validierung von Signalnamen und ‑typen benötigt MCG Zugriff auf einen Fahrzeugsignalkatalog. Dies ist ein Protobuf FileDescriptorSet, der Ihre VSIDL-Definitionen .proto enthält (verpackt und in das MCG hochgeladen). Weitere Informationen zum Erstellen und Hochladen eines Katalogs finden Sie unter Fahrzeugsignalkataloge.

Geben Sie die Katalogversion im Feld vs_version des JSON-Objekts an:

"vs_version": "v1.0",

Lebenszyklus-Trigger definieren

Im Rahmen einer Telemetriekampagne bestimmt der Lebenszyklus eines MetricsConfig, wann Daten tatsächlich erfasst werden. Während das Kampagnenverwaltungssystem die Konfiguration auf dem Gerät bereitstellt und aktiviert, können Sie mit Lebenszyklus-Triggern genau steuern, wann Daten im Rahmen dieser Bereitstellung erfasst werden.

So können Sie die Datenerhebung an die Nutzungsmuster des Fahrzeugs anpassen, z. B. an eine „Fahrt“ (IgnitionOn bis IgnitionOff) oder eine „Ladesitzung“, ohne die Konfiguration deaktivieren zu müssen.

  • Sitzungssteuerung (Start/Pause): Mit start_trigger_name und stop_trigger_name können Sie steuern, wann die Erfassung erfolgt. Wenn Sie beispielsweise Daten nur während der Fahrt des Fahrzeugs erfassen möchten, verwenden Sie IgnitionOn als Start- und IgnitionOff als Stopp-Trigger. Die Konfiguration bleibt auf dem Gerät aktiv, wird aber effektiv „pausiert“ (es werden keine Daten mehr erhoben und verarbeitet), wenn der Stopp-Trigger ausgelöst wird. Die Erhebung und Verarbeitung wird erst fortgesetzt, wenn der Start-Trigger wieder ausgelöst wird.

    Wichtig:Dadurch wird die Erhebung lediglich pausiert. Es werden keine logischen Zeiträume oder separaten Datasets definiert und es gibt auch keine anderen Nebenwirkungen. Aggregatorwerte werden nicht zurückgesetzt, wenn die Erhebung pausiert oder fortgesetzt wird.

  • Einmalige Erkennung (Abschluss): Verwenden Sie deactivate_trigger_name, wenn die Konfiguration nur einmal ausgeführt werden soll (z. B. um das erste Auftreten eines bestimmten Fehlercodes zu erkennen) und sich dann auf diesem Gerät dauerhaft deaktivieren soll, auch wenn die Kampagne technisch noch aktiv ist.

Wenn Sie keine Triggers für den Lebenszyklus angeben, beginnt die Datenerhebung sofort, wenn die Konfiguration durch die Kampagne aktiviert wird, und wird bis zum Ende der Kampagne fortgesetzt.

Lebenszyklusfelder der obersten Ebene (Stammobjekt)
optional
start_trigger_name
Der Name eines Triggers, der die Erfassungssitzung startet. Kann ohne stop_trigger_name festgelegt werden.
optional
stop_trigger_name
Der Name eines Triggers, der die Erfassungssitzung pausiert, z. B. wenn das Fahrzeug steht. Wenn dieser Wert festgelegt ist, muss auch start_trigger_name festgelegt werden.
optional
deactivate_trigger_name
Der Name eines Triggers, der die `MetricsConfig` abschließt und vollständig deaktiviert.

Erweitert: Benutzerdefinierte Proto-Definitionen

In zwei Hauptfällen reicht vs_version allein nicht aus, damit MCG alle Nachrichtentypen in der Beschreibung einer Messwertkonfiguration versteht:

  1. Fehler beim Ableiten des Typs:Wie im source_identifier-Format beschrieben, kann der Typ nicht abgeleitet werden, wenn für source_identifier ein FQIN oder ein benutzerdefinierter Name verwendet wird.
  2. Benutzerdefinierte Nachrichten:In der Beschreibung der Messwertkonfiguration werden Protobuf-Nachrichten verwendet, die nicht im VSIDL-Katalog in vs_version enthalten sind. Das passiert, wenn Sie message_type in einem message_builder für ein benutzerdefiniertes Berichtsformat festlegen.

Verwenden Sie in diesen Fällen data_source_message_types, damit MCG Typen ableiten kann, und descriptor_protos, um Nachrichtendefinitionen bereitzustellen.

data_source_message_types

Ordnen Sie den String source_identifier dem vollständig qualifizierten Protobuf-Nachrichtentyp zu. Der Schlüssel in data_source_message_types muss mit dem source_identifier-Wert aus dem data_sources-Eintrag übereinstimmen:

"data_source_message_types": {
  "MyCustomSpeedService": "com.sdv.example.SampleMessage"
}

descriptor_protos

Geben Sie Definitionen für alle Nachrichtentypen an, die in data_source_message_types oder message_builder verwendet werden und nicht in der konfigurierten vs_version enthalten sind.

Übergeben Sie einen base64-codierten descriptorpb.FileDescriptorSet im Array descriptor_protos. Generieren Sie diese aus .proto-Dateien mit dem Protobuf-Compiler protoc.

"descriptor_protos": [
  "Cu8BCiZtY2cvdGVzdGRhdGEvbWF4YXZnY3..." // Base64 string
]

Beispiel: Vollständige Konfigurationsbeschreibung

In den vorherigen Abschnitten werden alle Komponenten für das Beispiel definiert: Es wird jede Minute ein Bericht mit der durchschnittlichen Fahrzeuggeschwindigkeit in dieser Minute erstellt.

Die Komponenten sind:

  • Eine Datenquelle (SpeedSource) zum Abrufen von Geschwindigkeitsdaten bis zu einmal pro Sekunde.
  • Ein Datentrigger (OnNewSpeed), der ausgelöst wird, wenn SpeedSource Daten sendet.
  • Ein periodischer Trigger (EveryMinute), der alle 60 Sekunden ausgelöst wird.
  • Ein Aggregator (SpeedAggregator), der OnNewSpeed verwendet, um die Durchschnittsgeschwindigkeit zu berechnen, Messwerte zu zählen und aktuelle Werte zu speichern. Er wird zurückgesetzt, wenn er gelesen wird.
  • Eine Berichtskonfiguration (MinuteReport), mit der mithilfe von EveryMinute ein Bericht mit der Durchschnittsgeschwindigkeit und der Anzahl aus SpeedAggregator ausgelöst wird.
  • Felder der obersten Ebene (existing_uuid, vs_version) zur Identifizierung der Messwertkonfiguration und zur Angabe, welcher VSIDL-Katalog für Signaldaten verwendet werden soll.

Zusammen bilden diese Elemente die vollständige Beschreibung einer Messwertkonfiguration:

{
  "existing_uuid": "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8", // Unique identifier for the configuration
  "vs_version": "example_version", // Version of the VSIDL catalog to use
  "data_sources": [
    {
      "name": "SpeedSource",
      "source_identifier": "mcg.test.subpkg.speed_msg",
      "connection_type": "SUBSCRIPTION",
      "sub_sampling_interval_ms": 1000
    }
  ],
  "aggregators": [
    {
      "name": "SpeedAggregator",
      "trigger_names": ["OnNewSpeed"],
      "reset_on_get": true,
      "message_builder": {
        "field_assignments": [
          {
            "field_name": "average_speed",
            "aggregation": {
              "@type": "avg",
              "expression": "SpeedSource.speed"
            }
          },
          {
            "field_name": "speed_reading_count",
            "aggregation": { "@type": "count" }
          },
          {
            "field_name": "speed_history_last5",
            "aggregation": {
              "@type": "vector",
              "expression": "SpeedSource.speed",
              "max_length": 5
            }
          }
        ]
      }
    }
  ],
  "triggers": [
    {
      "name": "OnNewSpeed",
      "data": { "source_name": "SpeedSource" }
    },
    {
      "name": "EveryMinute",
      "periodic": { "period_ms": 60000 }
    }
  ],
  "report_configs": [
    {
      "name": "MinuteReport",
      "trigger_names": ["EveryMinute"],
      "message_builder": {
        "field_assignments": [
          {
            "field_name": "average_speed",
            "aggregation": {
              "@type": "none",
              "expression": "SpeedAggregator.average_speed"
            }
          },
          {
            "field_name": "reading_count",
            "aggregation": {
              "@type": "none",
              "expression": "SpeedAggregator.speed_reading_count"
            }
          }
        ]
      }
    }
  ]
}

Referenzvorlage

Die API-Definition finden Sie in der MCG API-Referenz.

In den folgenden Abschnitten finden Sie eine vollständige Referenz für die Beschreibung einer Messwertkonfiguration. Sie können sie als Leitfaden für die Erstellung einer eigenen Beschreibung einer Messwertkonfiguration verwenden.

Felder der obersten Ebene

{
  "existing_uuid": "00000000-0000-0000-0000-000000000000", // Optional
  "vs_version": "example_version", // Optional
  "descriptor_protos": ["..."], // Optional. Base64 encoded FileDescriptorSet
  "data_source_message_types": {
    "ExampleServiceName": "com.example.ProtoMessage"
  }, // Optional
  "start_trigger_name": "DataTriggerExample", // Optional
  "stop_trigger_name": "ConditionalTriggerExample", // Optional
  "deactivate_trigger_name": "PeriodicTriggerExample" // Optional
}

Eingabe: Datenquellen und Aggregatoren

{
  "data_sources": [
    {
      "name": "SubscriptionExample",
      "source_identifier": "com.example.sdv.ExampleMessage|example-unit",
      "connection_type": "SUBSCRIPTION", // Options: SUBSCRIPTION (default), ON_DEMAND
      "sub_sampling_interval_ms": 100, // Optional
      "fetch_last_message": false // Optional. Default: false
    },
    {
      "name": "RegistryExample",
      // Configurable Publisher Registry-based publisher (matches data_source_message_types)
      "source_identifier": "ExampleServiceName",
      "connection_type": "SUBSCRIPTION"
    },
    {
      "name": "GetterExample",
      "source_identifier": "com.example.sdv.ExampleConfig|example-unit",
      "connection_type": "ON_DEMAND",
      "configuration": {
        "type_url": "type.googleapis.com/example.Config",
        "value_json": {} // Or value_textproto, value (base64)
      }
    }
  ],
  "aggregators": [
    {
      "name": "AggregatorExample",
      "trigger_names": ["DataTriggerExample"],
      "reset_on_get": false, // Optional. Default: false. If true, resets state after it's read
      "message_builder": {
        "message_type": "com.example.AggregatedMessage", // Optional
        "field_assignments": [
          {
            "field_name": "avg_example",
            "aggregation": {
              // Options: avg, count, min, max, sum, stddev, delta, vector, none
              "@type": "avg",
              "expression": "SubscriptionExample.value"
            }
          },
          {
            "field_name": "count_example",
            "aggregation": {
              "@type": "count" // Counts number of evaluations. No expression needed
            }
          },
          {
            "field_name": "vector_example",
            "aggregation": {
              "@type": "vector",
              "expression": "SubscriptionExample.value",
              "max_length": 10 // Optional. If set, creates a ring buffer
            }
          }
        ]
      }
    }
  ]
}

Logik und Verarbeitung: Trigger

{
  "triggers": [
    {
      "name": "PeriodicTriggerExample",
      "periodic": { "period_ms": 1000 }
    },
    {
      "name": "DataTriggerExample",
      "data": { "source_name": "SubscriptionExample" }
    },
    {
      "name": "ConditionalTriggerExample",
      "conditional": {
        "triggers": ["PeriodicTriggerExample"],
        "expression": "SubscriptionExample.value > 0",
        "condition_type": {
          // Options: is_true, is_false, rising_edge, falling_edge, all_changes
          "rising_edge": {
            "rising_options": { "min_duration_ms": 0, "require_exact": false }
          }
        }
      }
    }
  ]
}

Ausgabe: Berichtskonfigurationen

{
  "report_configs": [
    {
      "name": "ReportExample",
      "trigger_names": ["PeriodicTriggerExample"],
      "report_incomplete": false, // Optional. Default: false
      "report_initial": false, // Optional. Default: false
      "message_builder": {
        "message_type": "com.example.ReportMessage", // Optional. Must be defined in VSIDL catalog or descriptor_protos. Message type will be inferred if not provided
        "field_assignments": [
          {
            "field_name": "avg_example",
            "aggregation": {
              "@type": "none", // Passthrough since aggregation is done in AggregatorExample
              "expression": "AggregatorExample.avg_example"
            }
          }
        ]
      }
    }
  ]
}

Syntax für Ausdrücke

Kategorie Syntax Beschreibung
Datenzugriff source_name
source_name.field
source_name.field.subfield
Auf die vollständige Nachricht aus einer Datenquelle oder einem Aggregator zugreifen
Auf ein bestimmtes Feld in der Nachricht zugreifen (einschließlich verschachtelter Felder)
Arithmetik +, -, *, /, %, ** Standardmathematik ** ist die Exponentiation.
Logisch &&, ||, !, ^ AND, OR, NOT, XOR.
Beziehungsbezogen ==, !=, <, <=, >, >= == und != funktionieren für alle Typen. Für andere sind Zahlen erforderlich.
Liste contains(list, item)
doesnotcontain(list, item)
alleq(list, value)
Wird für Vektoren (Arrays) verwendet. alleq(list, value) gibt true zurück, wenn alle Elemente in list gleich value sind.
Funktionen timestamp(clock_type) Aktuelle Zeit in Nanosekunden.
clock_type: REALTIME_CLOCK oder
MONOTONIC_TIME_SINCE_BOOT_OR_RESUME
abs(n) Absolutwert
floor(n), round(n), ceil(n) Rundungsfunktionen
Operatorrangfolge () Standardgruppierung für Vorrang