Condividi tramite


Compilare moduli WASM per i flussi di dati

La funzionalità di elaborazione dati WEBAssembly (WASM) personalizzata in Azure IoT Operations consente l'elaborazione dei dati di telemetria in tempo reale all'interno del cluster Azure IoT Operations. Distribuendo moduli WASM personalizzati, è possibile definire ed eseguire trasformazioni dei dati come parte del grafico del flusso di dati, del connettore HTTP/REST o del connettore MQTT.

Questo articolo descrive come usare l'estensione Azure IoT Operations Data Flow VS Code, l'interfaccia della riga di comando di aio-dataflow o gli strumenti standard installati nell'ambiente per sviluppare e testare i moduli WASM in locale prima di distribuirli nel cluster Azure IoT Operations. Si apprenderà come:

  • Eseguire un'applicazione a grafo in locale eseguendo un grafo predefinito con dati di esempio per comprendere il flusso di lavoro di base.
  • Creare moduli WASM personalizzati creando nuovi operatori in Python e Rust con funzionalità di mapping e filtro.

Usare l'estensione VS Code per un ciclo di sviluppo interno quando si creano attivamente operatori e grafici, ad esempio: scrivere codice, compilare, esaminare gli errori, eseguire il debug, apportare modifiche, aggiornare il grafico e pubblicare.

Usare l'interfaccia a riga di comando (CLI) per flussi di lavoro per la qualità del grafo incentrati su CI/CD, ad esempio compilare codice esistente, eseguire il grafico, verificare l'output confrontandolo con risultati di riferimento noti e monitorare la qualità nel tempo.

Usare gli strumenti standard installati nell'ambiente per scenari in cui si vuole un maggiore controllo sul processo di compilazione e test o quando è necessario integrarsi con altri strumenti e flussi di lavoro di sviluppo.

Questo articolo descrive come compilare e testare i moduli WASM in locale. Per utilizzare i flussi di dati e i connettori di Azure IoT Operations, è necessario distribuirli nel cluster di Azure IoT Operations e farvi riferimento nella configurazione del tuo grafo o connettore.

Per scenari più avanzati, vedere Creare grafici WASM di stato con l'archivio stati, Utilizzare lo Schema Registry con i moduli WASM, Eseguire il debug dei moduli WASM e Testare i moduli WASM.

Lo strumento di estensione e interfaccia della riga di comando è supportato nelle piattaforme seguenti:

  • Linux
  • Sottosistema di Windows per Linux (WSL)
  • Windows (assicurarsi di usare una shell Windows, ad esempio PowerShell o prompt dei comandi quando si eseguono i comandi di estensione in Windows)

Per altre informazioni sui grafici e su WASM in Azure IoT Operations, vedere:

Prerequisiti

Ambiente di sviluppo:

Immagini Docker:

docker pull mcr.microsoft.com/azureiotoperations/processor-app:1.1.5
docker tag mcr.microsoft.com/azureiotoperations/processor-app:1.1.5 host-app

docker pull mcr.microsoft.com/azureiotoperations/devx-runtime:0.1.8
docker tag mcr.microsoft.com/azureiotoperations/devx-runtime:0.1.8 devx

docker pull mcr.microsoft.com/azureiotoperations/statestore-cli:0.0.2
docker tag mcr.microsoft.com/azureiotoperations/statestore-cli:0.0.2 statestore-cli

docker pull eclipse-mosquitto

Eseguire un'applicazione graph in locale

Questo esempio usa un'area di lavoro di esempio che contiene tutte le risorse necessarie per compilare ed eseguire un'applicazione graph in locale usando l'estensione VS Code.

Aprire l'area di lavoro di esempio in VS Code

Clonare il repository Explore IoT Operations se non è già stato fatto.

Aprire la cartella samples/wasm in Visual Studio Code selezionando File > Apri cartella e passando alla cartella samples/wasm.

Costruire gli operatori

Premere Ctrl+Shift+P per aprire il riquadro comandi e cercare Azure IoT Operations: Compila tutti gli operatori. Selezionare Release (Versione ) come modalità di compilazione.

Questo comando costruisce tutti gli operatori nell'area di lavoro e crea .wasm file nella operators cartella. Usi i file .wasm per eseguire l'applicazione grafica in locale.

Eseguire l'applicazione graph in locale

Per avviare l'ambiente di esecuzione locale, premere Ctrl+Shift+P per aprire il riquadro comandi e cercare Azure IoT Operations: Avvia ambiente di sviluppo. Selezionare release come modalità di esecuzione.

Quando l'ambiente di esecuzione locale è in esecuzione, premere Ctrl+Shift+P per aprire il riquadro comandi e cercare Azure IoT Operations: Esegui Application Graph. Selezionare release come modalità di esecuzione. Questo comando esegue l'applicazione graph in locale usando l'ambiente di esecuzione locale con il graph.dataflow.yaml file nell'area di lavoro.

Legge anche da hostapp.env.list per impostare la variabile di ambiente TK_CONFIGURATION_PARAMETERS per i parametri di configurazione dell'operatore di flusso di dati.

Quando viene richiesto di immettere i dati, selezionare la data-and-images cartella nell'area di lavoro. Questa cartella contiene i file di dati di input per l'applicazione graph, inclusi i dati relativi a temperatura e umidità e alcune immagini per il modulo snapshot.

Attendere che venga visualizzata una notifica di VS Code che indica che i log sono pronti: Log files for the run can be found at ...\wasm\data-and-images\output\logs.

L'output si trova nella cartella output sotto la cartella data-and-images. È possibile aprire la output cartella nell'area di lavoro per visualizzare i file di output. Il .txt file con la data e l'ora per il nome file contiene i dati elaborati ed è simile all'esempio seguente:

{"tst":"2025-09-19T04:19:13.530381+0000","topic":"sensors","qos":0,"retain":0,"payloadlen":312,"properties":{"payload-format-indicator":1,"message-expiry-interval":10,"correlation-data":"...","user-properties":{"__ts":"001758255553528:00000:...","__protVer":"1.0","__srcId":"mqtt-source"},"content-type":"application/json"},"payload":{"temperature":[{"count":2,"max":653.888888888889,"min":204.44444444444449,"average":429.16666666666669,"last":204.44444444444449,"unit":"C","overtemp":true}],"humidity":[{"count":3,"max":85,"min":45,"average":69.666666666666671,"last":79}],"object":[{"result":"notebook, notebook computer; sliding door"}]}}

L'output mostra che l'applicazione grafico ha elaborato i dati di input e generato l'output. L'output include i dati relativi a temperatura e umidità e gli oggetti rilevati nelle immagini.

Creare un nuovo grafico con moduli WASM personalizzati

Questo scenario illustra come creare una nuova applicazione a grafo con moduli WASM personalizzati. L'applicazione grafico è costituita da due operatori: un map operatore che converte i valori di temperatura da Fahrenheit a Celsius e un filter operatore che filtra i messaggi con valori di temperatura superiori a 500°C.

Attualmente, non usare trattini (-) o caratteri di sottolineatura (_) nei nomi degli operatori. L'estensione VS Code applica questo requisito, ma se si creano o si rinominano manualmente i moduli, si verificano problemi. Usare nomi alfanumerici semplici per moduli come filter, map, stateenricho schemafilter.

Anziché usare un'area di lavoro di esempio esistente, si crea una nuova area di lavoro da zero. Questo processo consente di apprendere come creare una nuova applicazione graph e programmare gli operatori in Python e Rust.

Creare un nuovo progetto di applicazione graph in Python

Premere Ctrl+Shift+P per aprire il riquadro comandi di VS Code e cercare Azure IoT Operations: Crea applicazione:

  1. Per la cartella, selezionare una cartella in cui si vuole creare il progetto. È possibile creare una nuova cartella per questo progetto.
  2. Immettere my-graph come nome.
  3. Selezionare Python come lingua.
  4. Selezionare Mappa come tipo.
  5. Immettere map come nome.

È ora disponibile una nuova area di lavoro di VS Code con la struttura di progetto di base e i file di avvio. I file di avvio includono il graph.dataflow.yaml file e il codice sorgente del modello di operatore map.

Importante

Per usare un modulo Python in un'istanza di Azure IoT Operations distribuita, è necessario distribuire l'istanza con il profilo di memoria broker impostato su Medium o High. Se si imposta il profilo di memoria su Low o Tiny, l'istanza non può eseguire il pull del modulo Python.

Aggiungere codice Python per il modulo operatore map

Aprire il operators/map/map.py file e sostituire il contenuto con il codice seguente per convertire un valore di temperatura in ingresso da Fahrenheit a Celsius:

import json
from map_impl import exports
from map_impl import imports
from map_impl.imports import types

class Map(exports.Map):
    def init(self, configuration) -> bool:
        imports.logger.log(imports.logger.Level.INFO, "module4/map", "Init invoked")
        return True

    def process(self, message: types.DataModel) -> types.DataModel:
        # TODO: implement custom logic for map operator
        imports.logger.log(imports.logger.Level.INFO, "module4/map", "processing from python")

        # Ensure the input is of the expected type
        if not isinstance(message, types.DataModel_Message):
            raise ValueError("Unexpected input type: Expected DataModel_Message")

        # Extract and decode the payload
        payload_variant = message.value.payload
        if isinstance(payload_variant, types.BufferOrBytes_Buffer):
            # It's a Buffer handle - read from host
            imports.logger.log(imports.logger.Level.INFO, "module4/map", "Reading payload from Buffer")
            payload = payload_variant.value.read()
        elif isinstance(payload_variant, types.BufferOrBytes_Bytes):
            # It's already bytes
            imports.logger.log(imports.logger.Level.INFO, "module4/map", "Reading payload from Bytes")
            payload = payload_variant.value
        else:
            raise ValueError("Unexpected payload type")

        decoded = payload.decode("utf-8")

        # Parse the JSON data
        json_data = json.loads(decoded)

        # Check and update the temperature value
        if "temperature" in json_data and "value" in json_data["temperature"]:
            temp_f = json_data["temperature"]["value"]
            if isinstance(temp_f, int):
                # Convert Fahrenheit to Celsius
                temp_c = round((temp_f - 32) * 5.0 / 9.0)

                # Update the JSON data
                json_data["temperature"]["value"] = temp_c
                json_data["temperature"]["unit"] = "C"

                # Serialize the updated JSON back to bytes
                updated_payload = json.dumps(json_data).encode("utf-8")

                # Update the message payload
                message.value.payload = types.BufferOrBytes_Bytes(value=updated_payload)

        return message

Assicurarsi che Docker sia in esecuzione. Premere quindi Ctrl+Shift+P per aprire il riquadro comandi e cercare Azure IoT Operations: Compila tutti gli operatori. Creare un modulo di versione .

Il processo di compilazione inserisce il map.wasm file per l'operatore map nella operators/map/bin/release cartella .

Aggiungere il codice Rust per il modulo dell'operatore di filtro

Creare un nuovo operatore premendo Ctrl+Shift+P per aprire il riquadro comandi e cercare Azure IoT Operations: Crea operatore:

  1. Selezionare Rust come lingua.
  2. Selezionare Filter come tipo di operatore.
  3. Immettere filter come nome.

Aprire il operators/filter/src/lib.rs file e sostituire il contenuto con il codice seguente per filtrare i valori in cui la temperatura è superiore a 500°C:

mod filter_operator {
    use wasm_graph_sdk::macros::filter_operator;
    use serde_json::Value;

    fn filter_init(_configuration: ModuleConfiguration) -> bool {
        // Add code here to process the module init properties and module schemas from the configuration

        true
    }

    #[filter_operator(init = "filter_init")]
    fn filter(input: DataModel) -> Result<bool, Error> {

        // Extract payload from input to process
        let payload = match input {
            DataModel::Message(Message {
                payload: BufferOrBytes::Buffer(buffer),
                ..
            }) => buffer.read(),
            DataModel::Message(Message {
                payload: BufferOrBytes::Bytes(bytes),
                ..
            }) => bytes,
            _ => return Err(Error { message: "Unexpected input type".to_string() }),
        };

        // ... perform filtering logic here and return boolean
        if let Ok(payload_str) = std::str::from_utf8(&payload) {
            if let Ok(json) = serde_json::from_str::<Value>(payload_str) {
                if let Some(temp_c) = json["temperature"]["value"].as_i64() {
                    // Return true if temperature is above 500°C
                    return Ok(temp_c > 500);
                }
            }
        }

        Ok(false)
   }
}

Aprire il operators/filter/Cargo.toml file e aggiungere le dipendenze seguenti:

[dependencies]
# ...
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

Assicurarsi che Docker sia in esecuzione. Premere quindi Ctrl+Shift+P per aprire il riquadro comandi e cercare Azure IoT Operations: Compila tutti gli operatori. Creare un modulo di versione .

Il processo di compilazione inserisce il filter.wasm file per l'operatore filter nella operators/filter/bin/release cartella .

Eseguire l'applicazione graph in locale con dati di esempio

Aprire il graph.dataflow.yaml file e sostituire il contenuto con il codice seguente:

metadata:
    $schema: "https://www.schemastore.org/aio-wasm-graph-config-1.0.0.json"
    name: "Temperature Monitoring"
    description: "A graph that converts temperature from Fahrenheit to Celsius, if temperature is above 500°C, then sends the processed data to the sink."
    version: "1.0.0"
    vendor: "Microsoft"
moduleRequirements:
    apiVersion: "1.1.0"
    runtimeVersion: "1.1.0"
operations:
  - operationType: source
    name: source
  - operationType: map
    name: map
    module: map
  - operationType: filter
    name: filter
    module: filter
  - operationType: sink
    name: sink
connections:
  - from:
      name: source
    to:
      name: map
  - from:
      name: map
    to:
      name: filter
  - from:
      name: filter
    to:
      name: sink

Copiare la data cartella contenente i dati di esempio dal repository explore-iot-operations\samples\wasm\data degli esempi clonati nell'area di lavoro corrente. La data cartella contiene tre file JSON con dati di temperatura di input di esempio.

Se in precedenza è stato arrestato l'ambiente di esecuzione locale, premere Ctrl+Shift+P per aprire il riquadro comandi e cercare Azure IoT Operations: Avvia ambiente di sviluppo. Selezionare release come modalità di esecuzione.

Premere Ctrl+Shift+P per aprire il riquadro comandi e cercare Azure IoT Operations: Esegui Application Graph:

  1. Selezionare il file del graph.dataflow.yaml grafico.
  2. Selezionare release come modalità di esecuzione.
  3. Selezionare la data cartella copiata nell'area di lavoro.

Il contenitore DevX viene avviato per eseguire il grafico. Il risultato elaborato viene salvato nella data/output cartella . Il file di testo nella output cartella contiene i dati elaborati con la temperatura convertita in Celsius e filtrati in base alla soglia.

Per informazioni su come distribuire moduli WASM personalizzati e grafici nell'istanza di Azure IoT Operations, vedere Deploy WASM modules and data flow graphs.

Dopo aver creato i moduli WASM e aver configurato l'applicazione graph, è possibile distribuirli nel cluster Azure IoT Operations e farvi riferimento nella configurazione del grafo o del connettore:

Troubleshoot

Errori di compilazione

Error Motivo Correzione
error[E0463]: can't find crate for std Destinazione WASM mancante Eseguire rustup target add wasm32-wasip2
error: no matching package found per wasm_graph_sdk Registro merci mancante Aggiungere il [registries] blocco a .cargo/config.toml come illustrato in Eseguire un'applicazione graph in locale
componentize-py non è possibile trovare file WIT Percorso dello schema errato Usare il flag -d con il percorso completo della directory dello schema. Tutti i .wit file devono essere presenti perché fanno riferimento l'uno all'altro.
componentize-py mancata corrispondenza della versione Collegamenti generati con una versione diversa Eliminare la directory dei binding generati e rigenerarla con la stessa componentize-py versione
wasm-tools controllo componente non riuscito Destinazione non valida o adattatore del componente mancante Assicurarsi di usare wasm32-wasip2 (non wasm32-wasi o wasm32-unknown-unknown)

Errori di esecuzione

Sintomo Motivo Correzione
Arresto anomalo dell'operatore con backtrace WASM Parametri di configurazione mancanti o non validi Aggiungere l'analisi difensiva in init con le impostazioni predefinite. Vedere Parametri di configurazione del modulo.
init restituisce false, il flusso di dati non verrà avviato Convalida della configurazione non riuscita Controllare i log del flusso di dati per i messaggi di errore. Verificare che i nomi moduleConfigurations corrispondano al codice.
Il modulo viene caricato ma non produce alcun output process restituzione di errori o filtro che esclude tutti gli elementi Aggiungere la registrazione in process per tracciare il flusso di dati.
Unexpected input type Il modulo ha ricevuto una variante errata data-model Aggiungere un controllo del tipo all'inizio di process e gestire varianti impreviste.
Il modulo funziona da solo ma si arresta in modo anomalo in un grafico complesso Configurazione mancante quando viene riutilizzata tra i nodi Ogni nodo del grafo necessita di una propria moduleConfigurations voce.

Inconvenienti comuni

  • Dimenticando --artifact-type ORAS push. Senza di esso, l'interfaccia utente dell'esperienza operativa non visualizzerà correttamente il modulo.
  • Non corrispondente name in moduleConfigurations. Il nome deve essere <module>/<operator> (ad esempio, module-temperature/filter), corrispondente alla definizione della sezione operations del grafo.
  • Uso wasm32-wasi di anziché di wasm32-wasip2. Azure IoT Operations richiede l'obiettivo WASI Preview 2.
  • Python: lavorare all'esterno del repository dei campioni senza copiare la cartella dello schema. Tutti i .wit file devono essere posizionati in modo condiviso perché fanno riferimento tra loro.

Problemi noti

  • Valori booleani in YAML: i valori booleani devono essere racchiusi tra virgolette come stringhe per evitare errori di convalida. Ad esempio, usare "True" e "False" anziché true e false.

    Errore di esempio quando si usano valori booleani non racchiusi tra virgolette:

    * spec.connections[2].from.arm: Invalid value: "boolean": spec.connections[2].from.arm in body must be of type string: "boolean"
    * spec.connections[2].from.arm: Unsupported value: false: supported values: "False", "True"
    
  • : per usare i moduli Python, Azure IoT Operations deve essere distribuito con il broker MQTT configurato per l'uso del profilo di memoria Medium o High. non è possibile eseguire il pull dei moduli Python quando il profilo di memoria è impostato su Low o Tiny.

  • Tempi di distribuzione dei moduli: il pull e l'applicazione di moduli WASM potrebbero richiedere tempo, in genere circa un minuto, a seconda delle condizioni di rete e delle dimensioni del modulo.

  • Dettagli errore di compilazione: quando una compilazione ha esito negativo, il messaggio di errore nella notifica popup potrebbe non fornire dettagli sufficienti. Controllare l'output del terminale per informazioni più specifiche sull'errore.

  • Windows compatibilità: in Windows, la prima volta che si esegue un'applicazione graph, è possibile che venga visualizzato un errore "comando non riuscito con codice di uscita 1". Se si verifica questo errore, ripetere l'operazione e dovrebbe funzionare correttamente.

  • Stabilità dell'app host: l'ambiente di esecuzione locale potrebbe occasionalmente smettere di funzionare e richiedere il riavvio per il ripristino.

  • Limitazioni di debug remoto: Attualmente non è possibile effettuare il debugging remoto dei moduli WASM in esecuzione su Azure Linux 3.0 a causa di versioni LLDB incompatibili.

Procedure di ripristino

Reimpostazione dell'estensione VS Code: se l'estensione VS Code si comporta in modo imprevisto, provare a disinstallarla e reinstallarla, quindi riavviare VS Code.