Compartilhar via


Converter dados usando conversões de fluxo de dados

Importante

Esta página inclui instruções para gerenciar componentes do Azure IoT Operations usando manifestos de implantação do Kubernetes, que estão em VERSÃO PRÉVIA. Esse recurso é fornecido com várias limitações e não deve ser usado para cargas de trabalho de produção.

Veja os Termos de Uso Complementares para Versões Prévias do Microsoft Azure para obter termos legais que se aplicam aos recursos do Azure que estão em versão beta, versão preliminar ou que, de outra forma, ainda não foram lançados em disponibilidade geral.

Você pode usar conversões de fluxo de dados para transformar dados em Operações do Azure IoT. O elemento de conversão em um fluxo de dados é usado para calcular valores para campos de saída. Você pode usar campos de entrada, operações disponíveis, tipos de dados e conversões de tipo em conversões de fluxo de dados.

O elemento de conversão de fluxo de dados é usado para calcular valores para campos de saída:

inputs: [
  '*.Max' // - $1
  '*.Min' // - $2
]
output: 'ColorProperties.*'
expression: '($1 + $2) / 2'

Há vários aspectos que precisam ser compreendidos sobre as conversões:

  • Referência a campos de entrada: como fazer referência a valores de campos de entrada na fórmula de conversão.
  • Operações disponíveis: as operações que podem ser usadas nas conversões. Por exemplo, adição, subtração, multiplicação e divisão.
  • Tipos de dados: os tipos de dados que uma fórmula pode processar e tratar. Por exemplo, valor inteiro, valor de ponto flutuante e cadeia de caracteres.
  • Conversões de tipo: como os tipos de dados são convertidos entre os valores de campo de entrada, a avaliação da fórmula e os campos de saída.

Campos de entrada

Em conversões, as fórmulas podem operar em valores estáticos, como um número como parâmetros ou 25 derivados de campos de entrada. Um mapeamento define esses campos de entrada que a fórmula pode acessar. Faz-se referência a cada campo de acordo com a ordem dele na lista de entrada:

inputs: [
  '*.Max'      // - $1
  '*.Min'      // - $2
  '*.Mid.Avg'  // - $3
  '*.Mid.Mean' // - $4
]
output: 'ColorProperties.*'
expression: '($1, $2, $3, $4)'

Nesse exemplo, a conversão resulta em uma matriz que contém os valores [Max, Min, Mid.Avg, Mid.Mean]. Os comentários no arquivo YAML (# - $1, # - $2) são opcionais, mas ajudam a esclarecer a conexão entre cada propriedade do campo e a função desse campo na fórmula de conversão.

Tipos de dados

Os diversos formatos de serialização fornecem suporte a vários tipos de dados. Por exemplo, o JSON oferece alguns tipos primitivos: cadeia de caracteres, número, booliano e nulo. Também inclui matrizes desses tipos primitivos.

Quando o mapeador lê uma propriedade de entrada, ele a converte em um tipo interno. Essa conversão é necessária para manter os dados na memória até que sejam gravados em um campo de saída. A conversão em um tipo interno ocorre independentemente de os formatos de serialização de entrada e saída serem os mesmos.

A representação interna utiliza os seguintes tipos de dados:

Tipo Descrição
bool Verdadeiro/falso lógico.
integer Armazenado como um valor inteiro assinado de 128 bits.
float Armazenado como número de ponto flutuante de 64 bits.
string Uma cadeia de caracteres UTF-8.
bytes Os dados binários, uma cadeia de caracteres de valores não assinados de 8 bits.
datetime A hora local ou UTC com resolução de nanossegundos.
time A hora do dia com resolução de nanossegundos.
duration Uma duração com resolução de nanossegundos.
array Uma matriz de todos os tipos listados anteriormente.
map Um vetor de pares (chave, valor) de todos os tipos listados anteriormente.

Campos de registro de entrada

Quando se lê um campo de registro de entrada, o tipo subjacente dele é convertido em uma dessas variantes de tipo interno. A representação interna é versátil o suficiente para tratar a maioria dos tipos de entrada com conversão mínima ou nenhuma.

Os tipos alternativos são usados para alguns formatos. Por exemplo, o JSON não tem um tipo datetime e armazena valores datetime como cadeias de caracteres formatadas de acordo com ISO8601. Quando o mapeador lê esse campo, a representação interna permanece como uma cadeia de caracteres.

Campos de registro de saída

O mapeador é destinado a ser flexível, pois converte os tipos internos em tipos de saída a fim de acomodar os cenários em que os dados vêm de um formato de serialização com um sistema de tipo limitado. Os seguintes exemplos mostram como as conversões são tratadas:

  • Tipos numéricos: esses tipos podem ser convertidos em outras representações, mesmo que isso prejudique a precisão. Por exemplo, um número de ponto flutuante de 64 bits (f64) pode ser convertido em um número inteiro de 32 bits (i32).
  • De cadeia de caracteres para números: caso o registro de entrada contenha uma cadeia de caracteres como 123 e o campo de saída for um número inteiro de 32 bits, o mapeador converterá e gravará o valor como um número.
  • De cadeias de caracteres para outros tipos:
    • Caso o campo de saída seja datetime, o mapeador tentará analisar a cadeia de caracteres como um datetime com o formato ISO8601.
    • Caso o campo de saída seja binary/bytes, o mapeador tentará desserializar a cadeia de caracteres de uma cadeia de caracteres codificada em Base64.
  • Valores boolianos:
    • Caso o campo de saída seja numérico, eles serão convertidos para 0/1.
    • Caso o campo de saída seja uma cadeia de caracteres, eles serão convertidos para true/false.

Usar uma fórmula de conversão com tipos

Nos mapeamentos, uma fórmula opcional pode especificar a forma como os dados da entrada são processados antes de serem gravados no campo de saída. Caso não se especifique nenhuma fórmula, o mapeador copiará o campo de entrada para a saída usando o tipo interno e as regras de conversão.

Caso se especifique uma fórmula, os tipos de dados disponíveis para uso em fórmulas serão limitados a:

  • Inteiros
  • Números de ponto flutuante
  • Cadeias de caracteres
  • Boolianos
  • Matrizes dos tipos anteriores
  • Valor ausente

Map e byte não participam de fórmulas.

Os tipos que são relacionados ao tempo (datetime, time e duration) são convertidos em valores inteiros que representam o tempo em segundos. Depois da avaliação da fórmula, os resultados são armazenados na representação interna e não são convertidos novamente. Por exemplo, datetime convertido em segundos permanece um valor inteiro. Caso o valor seja usado em campos datetime, um método de conversão explícito deverá ser aplicado. Um exemplo é converter o valor em uma cadeia de caracteres ISO8601 que é automaticamente convertida para o tipo datetime de formato de serialização de saída.

Usar tipos irregulares

Aplicam-se considerações especiais a tipos como matrizes e valor ausente.

Matrizes

As matrizes podem ser processadas usando-se as funções de agregação para calcular um único valor direto de vários elementos. Por exemplo, usando-se o registro de entrada:

{
  "Measurements": [2.34, 12.3, 32.4]
}

Com o mapeamento:

inputs: [
  'Measurements' // - $1
]
output: 'Measurement'
expression: 'min($1)'

Essa configuração seleciona o menor valor da matriz de Measurements para o campo de saída.

As matrizes também podem ser criadas de acordo com vários valores únicos:

inputs: [
  'minimum' // - - $1
  'maximum' // - - $2
  'average' // - - $3
  'mean'    // - - $4
]
output: 'stats'
expression: '($1, $2, $3, $4)'

Esse mapeamento cria uma matriz que contém o mínimo, o máximo e a média.

Valor ausente

O valor ausente é um tipo especial usado em cenários, como nos casos de:

  • Tratamento de campos ausentes na entrada fornecendo um valor alternativo.
  • Remoção condicional de um campo com base na presença dele.

Exemplo de mapeamento que usa um valor ausente:

{
  "Employment": {      
    "Position": "Analyst",
    "BaseSalary": 75000,
    "WorkingHours": "Regular"
  }
}

O registro de entrada contém o campo BaseSalary, mas é possível que isso seja opcional. Digamos que, se o campo estiver ausente, um valor deverá ser adicionado direto de um conjunto de dados de contextualização:

{
  "Position": "Analyst",
  "BaseSalary": 70000,
  "WorkingHours": "Regular"
}

Um mapeamento pode verificar se o campo está presente no registro de entrada. Caso o campo seja encontrado, a saída receberá esse valor existente. Caso contrário, a saída receberá o valor com base no conjunto de dados de contexto. Por exemplo:

inputs: [
  'BaseSalary' // - - - - - - - - - - - $1
  '$context(position).BaseSalary' //  - $2
]
output: 'BaseSalary'
expression: 'if($1 == (), $2, $1)'

conversion usa a função if que apresenta três parâmetros:

  • O primeiro parâmetro é uma condição. No exemplo, ele verifica se o valor ausente é o campo BaseSalary do campo de entrada (com alias de $1).
  • O segundo parâmetro será o resultado da função caso a condição no primeiro parâmetro seja verdadeira. Nesse exemplo, isso é o campo BaseSalary do conjunto de dados de contextualização (com alias $2).
  • O terceiro parâmetro é o valor da condição caso o primeiro parâmetro seja falso.

Funções disponíveis

Os fluxos de dados fornecem um conjunto de funções internas que podem ser usadas em fórmulas de conversão. Essas funções podem ser usadas para executar operações comuns, como aritmética, comparação e manipulação de cadeia de caracteres. As funções disponíveis são:

Função Descrição Exemplos
min Retorna o valor mínimo direto de uma matriz. min(2, 3, 1) retorna 1, min($1) retorna o valor mínimo direto de uma matriz $1
max Retorna o valor máximo direto de uma matriz. max(2, 3, 1) retorna 3, max($1) retorna o valor máximo direto de uma matriz $1
if Retorna um valor entre valores de acordo com uma condição. if($1 > 10, 'High', 'Low') retorna 'High' se $1 for maior que 10; caso contrário, 'Low'
len Retorna o número de elementos ou o comprimento do caractere de uma cadeia de caracteres em uma tupla. len("Azure") retorna 5, len(1, 2, 3) retorna 3, len($1) retorna o número de elementos na matriz $1
floor Retorna o maior número inteiro menor ou igual a um número. floor(2.9) retorna 2
round Retorna o número inteiro mais próximo a um número, arredondando os casos de metade do caminho para além de 0,0. round(2.5) retorna 3
ceil Retorna o menor número inteiro maior ou igual ao número. ceil(2.1) retorna 3
scale Escala um valor direto de um intervalo para outro. scale($1, 0, 10, 0, 100) escala o valor de entrada direto do intervalo de 0 a 10 para o intervalo de 0 a 100

Funções de conversão

Os fluxos de dados fornecem várias funções de conversão internas para conversões de unidade comuns, como temperatura, pressão, comprimento, peso e volume. Estes são alguns exemplos:

Conversão Fórmula Nome da função
Celsius para Fahrenheit F = (C * 9/5) + 32 cToF
PSI para bar Bar = PSI * 0,0689476 psiToBar
Polegada para cm Cm = polegada * 2,54 inToCm
Pé para metro Metro = pé * 0,3048 ftToM
Lbs para kg Kg = lbs * 0,453592 lbToKg
Galões para litros Litros = galões * 3,78541 galToL

Também existe suporte para as conversões inversas:

Conversão Fórmula Nome da função
Fahrenheit para Celsius C = (F - 32) * 5/9 fToC
Bar para PSI PSI = bar/0,0689476 barToPsi
Cm para polegada Polegada para cm/2,54 cmToIn
Metro para pé Pé = metro/0,3048 mToFt
Kg para lbs Lbs = kg/0,453592 kgToLb
Litros para galões Galões = litros/3,78541 lToGal

Além disso, você pode definir suas próprias funções de conversão usando as fórmulas matemáticas básicas. O sistema fornece suporte a operadores como adição (+), subtração (-), multiplicação (*) e divisão (/). Esses operadores seguem as regras padrão de precedência, que podem ser ajustadas com parênteses a fim de garantir a ordem correta das operações. Isso permite que você personalize as conversões de unidade para atender às necessidades específicas.

Operadores disponíveis por precedência

Operador Descrição
^ Exponenciação: $1 ^ 3

Como Exponentiation tem a maior precedência, ele é executado primeiro, exceto se os parênteses substituírem essa ordem:

  • $1 * 2 ^ 3 é interpretado como $1 * 8 porque executa-se a parte 2 ^ 3 primeiro, antes da multiplicação.
  • ($1 * 2) ^ 3 processa a multiplicação antes da exponenciação.
Operador Descrição
- Negação
! Não lógico

Negation e Logical not têm precedência alta; portanto, eles sempre se apoiam no vizinho imediato, exceto quando há o envolvimento da exponenciação:

  • -$1 * 2 nega $1 primeiro e depois multiplica.
  • -($1 * 2) multiplica e depois nega o resultado.
Operador Descrição
* Multiplicação: $1 * 10
/ Divisão: $1/25 (o resultado é um número inteiro se os dois argumentos forem valores inteiros, caso contrário, será um número de ponto flutuante)
% Módulo: $1 % 25

Multiplication, Division e Modulo, com a mesma precedência, são executados da esquerda para a direita, exceto se a ordem for alterada por parênteses.

Operador Descrição
+ Adição de valores numéricos, concatenação das cadeias de caracteres
- Subtração

Addition e Subtraction são consideradas operações mais fracas se comparadas às operações do grupo anterior:

  • $1 + 2 * 3 resulta em $1 + 6 porque executa-se primeiro 2 * 3 devido à precedência mais alta de multiplication.
  • ($1 + 2) * 3 prioriza Addition antes de Multiplication.
Operador Descrição
< Menor que
> Maior que
<= Menor ou igual a
>= Maior ou igual a
== Igual a
!= É diferente de

Comparisons opera em valores numéricos, boolianos e de cadeia de caracteres. Como têm menor precedência do que os operadores aritméticos, não é necessário o uso de parênteses para comparar os resultados de forma eficaz:

  • $1 * 2 <= $2 é equivalente a ($1 * 2) <= $2.
Operador Descrição
|| OR lógico
&& AND lógico

Os operadores lógicos são usados para encadear condições:

  • $1 > 100 && $2 > 200