Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O armazenamento de estado do MQ é um sistema de armazenamento distribuído dentro do cluster das Operações do Azure IoT. O armazenamento de estado oferece as mesmas garantias de alta disponibilidade que as mensagens MQTT no Agente MQTT. De acordo com as diretrizes de protocolo MQTT5/RPC, os clientes devem usar o MQTT v5 para interagir com o repositório de estado. Este artigo fornece diretrizes de protocolo para desenvolvedores que precisam implementar seus próprios clientes de armazenamento de estado para Agente MQTT.
Visão geral
O armazenamento de estado do MQ dá suporte aos seguintes comandos:
-
SET<keyName><keyValue><setOptions> -
GET<keyName> -
DEL<keyName> -
VDEL<keyName><keyValue> ## Exclui um determinado <keyName> se e somente se seu valor for <keyValue>
O protocolo usa o seguinte modelo de solicitação-resposta:
- Solicitação. Os clientes publicam uma solicitação em um tópico do sistema de armazenamento de estado bem definido. Para publicar a solicitação, os clientes usam as propriedades e a carga necessárias descritas nas seções a seguir.
- Resposta. O armazenamento de estado processa de maneira assíncrona a solicitação e responde no tópico de resposta que o cliente forneceu inicialmente.
O diagrama a seguir mostra a exibição básica da solicitação e da resposta:
Tópico do sistema de repositório de estado, QoS e propriedades MQTT v5 necessárias
Para se comunicar com o armazenamento de estado, os clientes devem atender aos seguintes requisitos:
- Use MQTT v5. Para obter mais informações, consulte a especificação MQTT v5.
- Use QoS 1 (Qualidade de Serviço de nível 1). O QoS 1 é descrito na especificação MQTT v5.
- Tenha um relógio que esteja dentro de um minuto do relógio do Agente MQTT.
Para se comunicar com o armazenamento de estado, os clientes devem PUBLISH solicitações para o tópico do sistema statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke. Como o armazenamento de estado faz parte das Operações do Azure IoT, ele faz uma SUBSCRIBE implícita a este tópico sobre a inicialização.
Para criar uma solicitação, as seguintes propriedades MQTT5 são necessárias. Se essas propriedades não estiverem presentes ou a solicitação não for do tipo QoS 1, a solicitação falhará.
-
Tópico de Resposta. O armazenamento de estado responde à solicitação inicial usando esse valor. Como prática recomendada, formate o tópico de resposta como
clients/{clientId}/services/statestore/_any_/command/invoke/response. Definir o tópico de resposta comostatestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invokeou como um que começa comclients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8não é permitido em uma solicitação de repositório de estado. O repositório de estado desconecta clientes MQTT que usam um tópico de resposta inválido. - Dados de Correlação. Quando o armazenamento de estado envia uma resposta, ele inclui os dados de correlação da solicitação inicial.
O diagrama a seguir mostra uma exibição expandida da solicitação e da resposta:
Comandos suportados
Os comandos SET, GET e DEL se comportam conforme o esperado.
Os valores que o comando SET define e o comando GET recupera são dados binários arbitrários. O tamanho dos valores é limitado apenas pelo tamanho máximo do conteúdo MQTT e limitações de recursos do MQ e do cliente.
SET opções
O comando SET fornece mais sinalizadores opcionais além dos básicos keyValue e keyName:
-
NX. Permite que a chave seja definida somente se ela ainda não existir. -
NEX <value>. Permite que a chave seja definida somente se a chave não existir ou se o valor da chave já estiver definido como <valor>. O sinalizadorNEXnormalmente é usado para um cliente renovar a expiração (PX) em uma chave. -
PX. Por quanto tempo a chave deve persistir antes de expirar, em milissegundos.
VDEL opções
O comando VDEL é um caso especial do comando DEL.
DEL exclui incondicionalmente o keyNamedeterminado.
VDEL requer outro argumento chamado keyValue.
VDEL só excluirá o keyName determinado se tiver o mesmo keyValue.
Formato de conteúdo
O formato de conteúdo PUBLISH do armazenamento de estado é inspirado em RESP3, que é o protocolo subjacente que o Redis usa. O RESP3 codifica o verbo, como SET ou GET, e os parâmetros, como keyName e keyValue.
Diferenciação de maiúsculas e minúsculas
O cliente deve enviar os verbos e as opções em maiúsculas.
Formato de solicitação
As solicitações são formatadas como no exemplo a seguir. Após RESP3, o * representa o número de itens em uma matriz. O caractere $ é o número de caracteres na linha a seguir, excluindo o CRLF à direita.
Os comandos com suporte no formato RESP3 são GET, SET, DEL e VDEL.
*{NUMBER-OF-ARGUMENTS}<CR><LF>
${LENGTH-OF-NEXT-LINE}<CR><LF>
{COMMAND-NAME}<CR><LF>
${LENGTH-OF-NEXT-LINE}<CR><LF> // This is always the keyName with the current supported verbs.
{KEY-NAME}<CR><LF>
// Next lines included only if command has additional arguments
${LENGTH-OF-NEXT-LINE}<CR><LF> // This is always the keyValue for set
{KEY-VALUE}<CR><LF>
A saída de exemplo a seguir mostra o conteúdo RESP3 do armazenamento de estado:
*3<CR><LF>$3<CR><LF>set<CR><LF>$7<CR><LF>SETKEY2<CR><LF>$6<CR><LF>VALUE5<CR><LF>
*2<CR><LF>$3<CR><LF>get<CR><LF>$7<CR><LF>SETKEY2<CR><LF>
*2<CR><LF>$3<CR><LF>del<CR><LF>$7<CR><LF>SETKEY2<CR><LF>
*3<CR><LF>$4<CR><LF>vdel<CR><LF>$7<CR><LF>SETKEY2<CR><LF>$3<CR><LF>ABC<CR><LF>
Observação
SET requer propriedades MQTT5 adicionais, conforme explicado na seção Controle de versão e relógios lógicos híbridos.
Formato da resposta
Quando o repositório de estado detecta uma carga RESP3 inválida, ele ainda retorna uma resposta para o solicitante Response Topic. Exemplos de conteúdo inválido incluem um comando inválido, um RESP3 ilegal ou um estouro inteiro. Um conteúdo inválido começa com a cadeia de caracteres -ERR e contém mais detalhes.
Observação
Uma solicitação GET, DEL ou VDEL em uma chave inexistente não é considerada um erro.
Se um cliente enviar um conteúdo inválido, o armazenamento de estado enviará uma carga semelhante ao seguinte exemplo:
-ERR syntax error
Resposta SET
Quando uma solicitação de SET for bem-sucedida, o armazenamento de estado retornará o seguinte conteúdo:
+OK<CR><LF>
Se uma solicitação SET falhar devido a uma verificação de condição especificada nas opções de conjunto NX ou NEX que significa que a chave não pode ser definida, o armazenamento de estado retornará a seguinte carga útil:
-1<CR><LF>
Resposta GET
Quando uma solicitação de GET é feita em uma chave inexistente, o armazenamento de estado retorna o seguinte conteúdo:
$-1<CR><LF>
Quando a chave é encontrada, o armazenamento de estado retorna o valor no seguinte formato:
${NumberOfBytes}<CR><LF>
{KEY-VALUE}
A saída do armazenamento de estado que retorna o valor 1234 se parece com o seguinte exemplo:
$4<CR><LF>1234<CR><LF>
Resposta DEL e VDEL
O armazenamento de estado retorna o número de valores excluídos em uma solicitação de exclusão. Atualmente, o armazenamento de estado só pode excluir um valor por vez.
:{NumberOfDeletes}<CR><LF> // Will be 1 on successful delete or 0 if the keyName is not present
A saída a seguir é um exemplo de um comando DEL bem-sucedido:
:1<CR><LF>
Se uma solicitação VDEL falhar porque o valor especificado não corresponde ao valor associado à chave, o armazenamento de estado retornará a seguinte carga útil:
-1<CR><LF>
-ERR respostas
A seguir está a lista atual de sequências de erros. Seu aplicativo cliente deve manipular cadeias de caracteres de erro desconhecido para dar suporte a atualizações no armazenamento de estado.
| Cadeia de caracteres de erro retornada do armazenamento de estado | Explicação |
|---|---|
| o registro de data e horade solicitação está muito distante no futuro; certifique-se de que os relógios do sistema do cliente e do corretor estejam sincronizados | Carimbo de data/hora de solicitação inesperado causado pelo armazenamento de estado e os relógios do cliente não estão sincronizados. |
| um token de esgrima é necessário para essa solicitação | Ocorre um erro se uma chave estiver marcada com um token de cerca, mas o cliente não especificar o token de cerca. |
| o carimbo de data/hora do token de esgrima de solicitação está muito distante no futuro; certifique-se de que os relógios do sistema do cliente e do corretor estejam sincronizados | Carimbo de data/hora inesperado do token de cerca causado pela falta de sincronização dos relógios do cliente e do armazenamento de estado. |
| o token de cerca de solicitação é uma versão inferior ao token de cerca que protege o recurso | Versão incorreta do token de esgrima de solicitação. Para obter mais informações, veja [Versionamento e relógios lógicos híbridos].(#versioning-and-hybrid-logical-clocks) |
| a cota foi excedida | O armazenamento de estado tem uma cota de quantas chaves ele pode armazenar, que é baseada no perfil de memória do broker MQTT especificado. |
| erro de sintaxe | A carga enviada não está de acordo com a definição do armazenamento de estado. |
| não autorizado | Erro de autorização |
| comando desconhecido | O comando não é reconhecido. |
| número errado de argumentos | Número incorreto de argumentos esperados. |
| carimbo de data/hora ausente | Quando os clientes fazem um SET, eles devem definir a propriedade de usuário MQTT5 __ts como um HLC representando seu registro de data e hora. |
| carimbo de data/hora malformado | O registro de data e hora no __ts ou no token de esgrima não é legal. |
| o comprimento da chave é zero | As chaves não podem ter comprimento zero no armazenamento de estado. |
Controle de versão e relógios lógicos híbridos
Esta seção descreve como o armazenamento de estado lida com o controle de versão.
Versões como relógios lógicos híbridos
O armazenamento de estado mantém uma versão para cada valor armazenado. O armazenamento de estado poderia usar um contador de aumento de forma monotônica para manter versões. Em vez disso, o armazenamento de estado usa um HLC (Relógio Lógico Híbrido) para representar versões. Para obter mais informações, consulte os artigos sobre o design original de HLCs e a intenção por trás de HLCs.
O armazenamento de estado usa o seguinte formato para definir HLCs:
{wallClock}:{counter}:{node-Id}
O wallClock é o número de milissegundos desde a época do Unix.
counter e node-Id funcionam como HLCs em geral.
Quando os clientes fazem um SET, eles devem definir a propriedade de usuário MQTT5 __ts como um HLC, representando seu carimbo de data/hora, com base no relógio atual do cliente. O armazenamento de estado retorna a versão do valor em sua mensagem de resposta. A resposta também é especificada como um HLC e também usa a propriedade de usuário MQTT5 __ts. O HLC retornado é sempre maior que o HLC da solicitação inicial.
Exemplo de configuração e recuperação da versão de um valor
Esta seção mostra um exemplo de configuração e obtenção da versão para um valor.
Um cliente define keyName=value. O relógio do cliente é 3 de outubro, 23:07:05 GMT. O valor do relógio é 1696374425000 milissegundos desde a época do Unix. Suponha que o relógio do sistema do armazenamento de estado seja idêntico ao relógio do sistema cliente. O cliente faz o comando SET conforme descrito anteriormente.
O diagrama a seguir ilustra o comando SET:
A propriedade __ts (carimbo de data/hora) no conjunto inicial contém 1696374425000 como o relógio de parede do cliente, o contador como 0 e sua ID de nó como CLIENT. Na resposta, a propriedade __ts retornada pelo armazenamento de estado contém o wallClock, o contador incrementado por um e a ID do nó como StateStore. O repositório de estado poderia retornar um valor de wallClock mais alto se o relógio estivesse adiantado, com base na maneira como as atualizações do HLC funcionam.
Essa versão também é retornada em solicitações de GET, DEL e VDEL bem-sucedidas. Nessas solicitações, o cliente não especifica um __ts.
O diagrama a seguir ilustra o comando GET:
Observação
O carimbo de data/hora __ts que o armazenamento de estado retorna é o mesmo que retornou na solicitação de SET inicial.
Se uma determinada chave for atualizada posteriormente com um novo SET, o processo será semelhante. O cliente deve definir sua solicitação __ts com base no relógio atual. O armazenamento de estado atualiza a versão do valor e retorna o __ts seguindo as regras de atualização do HLC.
Distorção de relógio
O armazenamento de estado rejeita um __ts (e também um __ft) que está mais de um minuto à frente do relógio local do armazenamento de estado.
O armazenamento de estado aceita um __ts que está atrás do relógio local do armazenamento de estado. Conforme especificado no algoritmo HLC, o armazenamento de estado define a versão da chave como seu relógio local porque ela é maior.
Tokens de bloqueio e isolamento
Esta seção descreve a finalidade e o uso de tokens de bloqueio e isolamento.
Contexto
Suponha que haja dois ou mais clientes MQTT usando o armazenamento de estado. Ambos os clientes querem gravar em uma determinada chave. Os clientes do armazenamento de estado precisam de um mecanismo para bloquear a chave de forma que apenas um cliente por vez possa modificar uma determinada chave.
Um exemplo desse cenário ocorre em sistemas ativos e em espera. Pode haver dois clientes que executam a mesma operação e a operação pode incluir o mesmo conjunto de chaves do armazenamento de estado. Em um determinado momento, um dos clientes está ativo e o outro está pronto para assumir imediatamente se o sistema ativo trava ou falha. Idealmente, apenas um cliente deve gravar no armazenamento de estado em um determinado momento. No entanto, em sistemas distribuídos, é possível que ambos os clientes se comportem como se estivessem ativos e, simultaneamente, tentem gravar nas mesmas chaves. Esse cenário cria uma condição de corrida.
O armazenamento de estado fornece mecanismos para impedir essa condição de corrida usando tokens de isolamento. Para obter mais informações sobre tokens de isolamento e a classe de condições de corrida contra as quais eles foram projetados para se proteger, consulte este artigo.
Obter um token de isolamento
Este exemplo pressupõe que temos os seguintes elementos:
-
Client1eClient2. Esses clientes são clientes de armazenamento de estado que atuam como um par ativo e em espera. -
LockName. O nome de uma chave no armazenamento de estado que atua como o bloqueio. -
ProtectedKey. A chave que precisa ser protegida contra vários gravadores.
Os clientes tentam obter um bloqueio como a primeira etapa. Eles recebem um bloqueio fazendo um SET LockName {CLIENT-NAME} NEX PX {TIMEOUT-IN-MILLISECONDS}. Lembre-se de Definir Opções que o sinalizador NEX significa que o SET só terá êxito se uma das seguintes condições for atendida:
- A chave estava vazia
- O valor da chave já está definido como <valor> e
PXespecifica o tempo limite em milissegundos.
Suponha que Client1 vá primeiro com uma solicitação de SET LockName Client1 NEX PX 10000. Essa solicitação lhe dá a propriedade de LockName para 10.000 milissegundos. Se Client2 tentar um SET LockName Client2 NEX ... enquanto Client1 tiver o bloqueio, o sinalizador NEX significará que a solicitação Client2 falhará.
Client1 precisa renovar esse bloqueio enviando o mesmo comando SET usado para adquirir o bloqueio, se Client1 quiser continuar a propriedade.
Observação
Um SET NX é conceitualmente equivalente a AcquireLock().
Usar os tokens de isolamento em solicitações SET
Quando Client1 faz SET com êxito ("AcquireLock") no LockName, o armazenamento de estado retorna a versão de LockName como um HLC (Relógio Lógico Híbrido) na propriedade __ts do usuário MQTT5.
Quando um cliente executa uma solicitação de SET, ele pode incluir opcionalmente a propriedade de usuário MQTT5 __ft para representar um "token de isolamento". O __ft é representado como um HLC. O token de isolamento associado a um determinado par chave-valor fornece verificação de propriedade de bloqueio. O token de isolamento pode vir de qualquer lugar. Para esse cenário, ele deve vir da versão do LockName.
O diagrama a seguir mostra o processo de Client1 fazer uma solicitação SET no LockName:
Em seguida, Client1 usa a propriedade __ts (Property=1696374425000:1:StateStore) não modificada como base da propriedade __ft na solicitação para modificar ProtectedKey. Como todas as solicitações SET, o cliente deve definir a propriedade __ts de ProtectedKey.
O diagrama a seguir mostra o processo de Client1 fazer uma solicitação SET no ProtectedKey:
Se a solicitação for bem-sucedida, desse ponto em ProtectedKey exigirá um token de isolamento igual ou maior que o especificado na solicitação SET.
Algoritmo de token de isolamento
O armazenamento de estado aceita qualquer HLC para o __ts de um par chave-valor, se o valor estiver dentro da distorção máxima do relógio. No entanto, o mesmo não ocorre em tokens de isolamento.
O algoritmo do armazenamento de estado para tokens de isolamento é o seguinte:
- Se um par chave-valor não tiver um token de isolamento associado a ele e uma solicitação
SETdefine__ft, o armazenamento de estado armazenará o__ftassociado com o par chave-valor. - Se um par chave-valor tiver um token de isolamento associado a ele:
- Se uma solicitação
SETnão tiver especificado__ft, rejeite a solicitação. - Se uma solicitação
SETespecificar um__ftque tenha um valor HLC mais antigo do que o token de isolamento associado ao par chave-valor, rejeite a solicitação. - Se uma solicitação
SETespecificar um__ftque tenha um valor HLC igual ou mais recente do que o token de isolamento associado ao par chave-valor, aceite a solicitação. O armazenamento de estado atualiza o token de isolamento do par chave-valor para ser o único definido na solicitação, se ele for mais recente.
- Se uma solicitação
Depois que uma chave é marcada com um token de isolamento, para que uma solicitação seja bem-sucedida, as solicitações DEL e VDEL também exigem que a propriedade __ft seja incluída. O algoritmo é idêntico ao anterior, exceto que o token de isolamento não é armazenado porque a chave está sendo excluída.
Comportamento do cliente
Esses mecanismos de bloqueio dependem de clientes serem bem comportados. No exemplo anterior, um Client2 mal comportado não podia ter o LockName e ainda executar com êxito um SET ProtectedKey escolhendo um token de isolamento mais recente que o token de ProtectedKey. O armazenamento de estado não está ciente de que LockName e ProtectedKey têm qualquer relação. Como resultado, o armazenamento de estado não executa a validação de que Client2 realmente possui o valor.
Os clientes que podem gravar chaves para as quais eles realmente não possuem o bloqueio são comportamentos indesejáveis. Você pode proteger contra esse mau comportamento do cliente implementando corretamente os clientes e usando a autenticação para limitar o acesso a chaves somente para clientes confiáveis.
Notificações
Os clientes podem se registrar no repositório de estado para receber notificações de chaves que estão sendo modificadas. Considere o cenário em que um termostato usa a chave do repositório de estado {thermostatName}\setPoint. Outros clientes do repositório de estado podem alterar o valor dessa chave para alterar o setPoint do termostato. Em vez de sondar alterações, o termostato pode se registrar no repositório de estado para receber mensagens quando {thermostatName}\setPoint é modificado.
Mensagens de solicitação KEYNOTIFY
Os clientes do repositório de estado solicitam que o repositório de estado monitore uma determinada keyName para alterações enviando uma mensagem de KEYNOTIFY. Assim como todas as solicitações do repositório de estado, os clientes publicam uma mensagem QoS1 com essa mensagem por meio do MQTT v5 para o tópico statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invokedo sistema do repositório de estado.
O conteúdo da solicitação tem a forma a seguir:
KEYNOTIFY<CR><LF>
{keyName}<CR><LF>
{optionalFields}<CR><LF>
Em que:
- KEYNOTIFY é um literal de cadeia de caracteres que especifica o comando.
-
{keyName}é o nome da chave para escutar as notificações. No momento, não há suporte para caracteres curinga. -
{optionalFields}Os valores de campo opcionais com suporte no momento são:-
{STOP}Se houver uma notificação existente com o mesmokeyNameeclientIdque essa solicitação, o repositório de estado a removerá.
-
A saída de exemplo a seguir mostra uma solicitação KEYNOTIFY para monitorar a chave SOMEKEY:
*2<CR><LF>
$9<CR><LF>
KEYNOTIFY<CR><LF>
$7<CR><LF>
SOMEKEY<CR><LF>
Mensagem de resposta KEYNOTIFY
Como todas as solicitações RPC do repositório de estado, o repositório de estado retorna sua resposta ao Response Topic e usa as propriedades de Correlation Data especificadas da solicitação inicial. Para KEYNOTIFY, uma resposta bem-sucedida indica que o repositório de estado processou a solicitação. Depois que o repositório de estado processa a solicitação com êxito, ela monitora a chave do cliente atual ou interrompe o monitoramento.
Com êxito, a resposta do repositório de estado é a mesma de um SET bem-sucedido.
+OK<CR><LF>
Se um cliente enviar uma solicitação KEYNOTIFY SOMEKEY STOP mas o repositório de estado não estiver monitorando essa chave, a resposta do repositório de estado será a mesma que tentar excluir uma chave que não existe.
:0<CR><LF>
Qualquer outra falha segue o padrão geral de relatório de erros do repositório de estado:
-ERR: <DESCRIPTION OF ERROR><CR><LF>
Tópicos de notificação KEYNOTIFY e ciclo de vida
Quando uma keyName sendo monitorada por meio de KEYNOTIFY é modificada ou excluída, o repositório de estado envia uma notificação ao cliente. O tópico é determinado por convenção – o cliente não especifica o tópico durante o processo de KEYNOTIFY.
O tópico é definido no exemplo a seguir. O clientId é uma representação codificada em hexadecimal de maiúsculas e minúsculas da ClientId MQTT do cliente que iniciou a solicitação KEYNOTIFY e keyName é uma representação codificada em hexadecimal da chave que foi alterada. O repositório de estado segue as regras de codificação Base 16 do RFC 4648 - As Codificações de Dados Base16, Base32 e Base64 para essa codificação.
clients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/{clientId}/command/notify/{keyName}
Por exemplo, o agente do MQTT publica uma mensagem NOTIFY enviada para client-id1 com o nome da chave modificado SOMEKEY para o tópico:
clients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/636C69656E742D696431/command/notify/534F4D454B4559`
Um cliente que usa notificações deve SUBSCRIBE para este tópico e aguardar o SUBACK ser recebido antes de enviar solicitações KEYNOTIFY para que nenhuma mensagem seja perdida.
Se um cliente se desconectar, ele deverá assinar novamente o tópico de notificação KEYNOTIFY e reenviar o comando KEYNOTIFY para todas as chaves necessárias para continuar o monitoramento. Ao contrário das assinaturas MQTT, que podem ser mantidas em uma sessão não limpa, o repositório de estado remove internamente qualquer mensagens KEYNOTIFY quando um determinado cliente se desconecta.
Formato de mensagem de notificação KEYNOTIFY
Quando uma chave que está sendo monitorada por meio de KEYNOTIFY for modificada, o repositório de estado PUBLISH uma mensagem para o tópico de notificação seguindo o formato para os clientes do repositório de estado registrados para a alteração.
NOTIFY<CR><LF>
{operation}<CR><LF>
{optionalFields}<CR><LF>
Os seguintes detalhes estão incluídos na mensagem:
-
NOTIFYé um literal de cadeia de caracteres incluído como o primeiro argumento no conteúdo, indicando que uma notificação chegou. -
{operation}é o evento que ocorreu. Atualmente, essas operações são:-
SETo valor foi modificado. Essa operação só pode ocorrer como resultado de um comandoSETde um cliente do repositório de estado. -
DELo valor foi excluído. Essa operação pode ocorrer devido a um comandoDELouVDELde um cliente do repositório de estado.
-
optionalFields-
VALUEe{MODIFIED-VALUE}.VALUEé um literal de cadeia de caracteres que indica que o próximo campo,{MODIFIED-VALUE}, contém o valor para o qual a chave foi alterada. Esse valor é enviado somente em resposta a chaves que estão sendo modificadas devido a umSET.
-
A saída de exemplo a seguir mostra uma mensagem de notificação enviada quando a chave SOMEKEY é modificada para o valor abc, com o VALUE incluído porque a solicitação inicial especificou a opção GET:
*4<CR><LF>
$6<CR><LF>
NOTIFY<CR><LF>
$3<CR><LF>
SET<CR><LF>
$5<CR><LF>
VALUE<CR><LF>
$3<CR><LF>
abc<CR><LF>
A mensagem de notificação KEYNOTIFY contém o carimbo de data/hora do valor ao notificar um cliente sobre uma solicitação SET (valor atualizado) ou ao notificar um cliente sobre uma solicitação DEL ou VDEL (valor excluído). O carimbo de data/hora é incluído como parte do __ts da Propriedade de Usuário MQTT v5 da mensagem. Para obter mais informações, consulte a seção Versões como Relógios Lógicos Híbridos.