Protocolo de armazenamento de estado
O armazenamento de estado é um sistema de armazenamento distribuído dentro do cluster de Operações IoT do Azure. O armazenamento de estado oferece as mesmas garantias de alta disponibilidade que as mensagens MQTT no broker MQTT. De acordo com as diretrizes do protocolo MQTT5/RPC, os clientes devem usar o MQTT5 para interagir com o armazenamento de estado. Este artigo fornece orientação de protocolo para desenvolvedores que precisam implementar seus próprios clientes de armazenamento de estado.
Descrição geral
O armazenamento de estado suporta os seguintes comandos:
SET
<keyName><keyValue><setOptions>GET
<Nome da chave>DEL
<Nome da chave>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:
- Pedido. 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.
- Response. O armazenamento de estado processa a solicitação de forma assíncrona e responde sobre o tópico de resposta que o cliente forneceu inicialmente.
O diagrama a seguir mostra a visão básica da solicitação e da resposta:
Tópico do sistema de armazenamento de estado, QoS e propriedades MQTT5 necessárias
Para se comunicar com o armazenamento de estado, os clientes devem atender aos seguintes requisitos:
- Use MQTT5. Para obter mais informações, consulte a especificação MQTT 5.
- Use QoS 1 (Qualidade de Serviço nível 1). QoS 1 é descrito na especificação MQTT 5.
- Tenha um relógio que esteja dentro de um minuto do relógio do corretor MQTT.
Para se comunicar com o armazenamento de estado, os clientes devem PUBLISH
solicitar para o tópico statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke
do sistema . Como o repositório de estado faz parte das Operações do Azure IoT, ele faz um implícito SUBSCRIBE
a este tópico na inicialização.
Para criar uma solicitação, as seguintes propriedades MQTT5 são necessárias. Se essas propriedades não estiverem presentes ou se 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/invoke
ou como um que começa comclients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8
não é permitido em uma solicitação de armazenamento de estado. O armazenamento 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
comportam-se como esperado.
Os valores que o SET
comando define e o GET
comando recupera são dados binários arbitrários. O tamanho dos valores é limitado apenas pelo tamanho máximo da carga útil MQTT e pelas limitações de recursos do broker MQTT e do cliente.
SET
Opções
O SET
comando fornece mais sinalizadores opcionais além do básico 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 ela não existir ou se o valor da chave já estiver definido como <valor>. ONEX
sinalizador é normalmente usado para um cliente renovar a expiração (PX
) em uma chave.PX
. Quanto tempo a chave deve persistir antes de expirar, em milissegundos.
VDEL
Opções
O VDEL
comando é um caso especial do DEL
comando. DEL
exclui incondicionalmente o dado keyName
. VDEL
requer outro argumento chamado keyValue
. VDEL
só elimina o dado keyName
se tiver o mesmo keyValue
.
Formato da carga útil
O formato de carga útil do armazenamento PUBLISH
de estado é inspirado no RESP3, que é o protocolo subjacente que o Redis usa. RESP3 codifica tanto o verbo, como SET
ou GET
, quanto os parâmetros como keyName
e keyValue
.
Sensível às maiúsculas e minúsculas
O cliente deve enviar os verbos e as opções em maiúsculas.
Formato do pedido
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 a CRLF à direita.
Os comandos suportados 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>
O exemplo de saída a seguir mostra as cargas úteis 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>
Nota
SET
requer propriedades MQTT5 adicionais, conforme explicado na seção Versionamento e relógios lógicos híbridos.
Formato da resposta
Quando o armazenamento de estado deteta uma carga RESP3 inválida, ele ainda retorna uma resposta ao Response Topic
. Exemplos de cargas inválidas incluem um comando inválido, um RESP3 ilegal ou estouro de inteiro. Uma carga inválida começa com a cadeia de caracteres -ERR
e contém mais detalhes.
Nota
Um GET
, DEL
, ou VDEL
solicitação em uma chave inexistente não é considerado um erro.
Se um cliente enviar uma carga inválida, o armazenamento de estado enviará uma carga como o exemplo a seguir:
-ERR syntax error
SET
resposta
Quando uma SET
solicitação é bem-sucedida, o armazenamento de estado retorna a seguinte carga útil:
+OK<CR><LF>
Se uma solicitação SET falhar porque uma verificação de condição, conforme especificado nas opções de conjunto NX ou NEX, significa que a chave não pode ser definida, o armazenamento de estado retornará a seguinte carga:
-1<CR><LF>
GET
resposta
Quando uma GET
solicitação é feita em uma chave inexistente, o armazenamento de estado retorna a seguinte carga:
$-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 exemplo a seguir:
$4<CR><LF>1234<CR><LF>
DEL
e VDEL
resposta
O armazenamento de estado retorna o número de valores que exclui em uma solicitação de exclusão. Atualmente, o armazenamento de estado só pode excluir um valor de cada 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 bem-sucedido DEL
:
: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 cadeias de caracteres de erro. Seu aplicativo cliente deve lidar com cadeias de caracteres de erro desconhecidas para oferecer suporte a atualizações para o armazenamento de estado.
Seqüência de erro retornada do armazenamento de estado | Explicação |
---|---|
o carimbo de data/hora do pedido está demasiado longe no futuro; Verifique se os relógios do sistema do cliente e do corretor estão sincronizados | O carimbo de data/hora de solicitação inesperada causado pelo armazenamento de estado e os relógios do cliente não estão sincronizados. |
Um token de esgrima é necessário para esta solicitação | O erro ocorre se uma chave estiver marcada com um token de esgrima, mas o cliente não especificar o token de esgrima. |
o carimbo de data/hora do token de esgrima de solicitação está muito longe no futuro; Verifique se os relógios do sistema do cliente e do corretor estão sincronizados | O carimbo de data/hora do token de vedação inesperado causado pelo armazenamento de estado e pelos relógios do cliente não está sincronizado. |
O token de esgrima de solicitação é uma versão inferior que o token de esgrima que protege o recurso | Versão incorreta do token de vedação de solicitação. Para obter mais informações, consulte [Controle de versão e relógios lógicos híbridos]. (relógios lógicos #versioning e híbridos) |
a quota 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 carimbo de data/hora. |
carimbo de data/hora malformado | O carimbo de data/hora no __ts ou o 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. A loja estatal poderia usar um contador monotonicamente crescente para manter as versões. Em vez disso, o armazenamento de estado usa um relógio lógico híbrido (HLC) para representar versões. Para obter mais informações, consulte os artigos sobre o design original dos HLCs e a intenção por trás dos 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 Unix. counter
e node-Id
funcionam como HLCs em geral.
Quando os clientes fazem um SET
, eles devem definir a propriedade __ts
de usuário MQTT5 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 __ts
propriedade de usuário MQTT5. O HLC retornado é sempre maior do 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, 11:07:05PM GMT. O valor do relógio é 1696374425000
milissegundos desde a época Unix. Suponha que o relógio do sistema do armazenamento de estado é idêntico ao relógio do sistema cliente. O cliente executa o SET
comando conforme descrito anteriormente.
O diagrama a seguir ilustra o SET
comando:
A __ts
propriedade (timestamp) no conjunto inicial contém 1696374425000
como o relógio de parede do cliente, o contador como 0
, e seu node-Id como CLIENT
. Na resposta, a __ts
propriedade que o armazenamento de estado retorna contém o wallClock
, o contador incrementado por um e o node-Id como StateStore
. O armazenamento estatal poderia retornar um valor mais alto wallClock
se seu relógio estivesse adiantado, com base na forma como as atualizações do HLC funcionam.
Esta versão também é retornada em solicitações bem-sucedidas GET
, DEL
, e VDEL
. Nessas solicitações, o cliente não especifica um __ts
arquivo .
O diagrama a seguir ilustra o GET
comando:
Nota
O carimbo de data/hora __ts
que o armazenamento de estado retorna é o mesmo que ele retornou na solicitação inicial SET
.
Se uma determinada chave for posteriormente atualizada com um novo SET
, o processo será semelhante. O cliente deve definir o seu pedido __ts
com base no seu relógio atual. O armazenamento de estado atualiza a versão do valor e retorna o __ts
, seguindo as regras de atualização HLC.
Distorção de relógio
A loja estadual rejeita um __ts
(e também um __ft
) que está mais de um minuto à frente do relógio local da loja estadual.
A loja do estado aceita um __ts
que está atrás do relógio local da loja do estado. Conforme especificado no algoritmo HLC, o armazenamento de estado define a versão da chave para seu relógio local porque é maior.
Fichas de bloqueio e esgrima
Esta seção descreve a finalidade e o uso de tokens de bloqueio e esgrima.
Fundo
Suponha que haja dois ou mais clientes MQTT usando o armazenamento de estado. Ambos os clientes desejam gravar em uma determinada chave. Os clientes de armazenamento de estado precisam de um mecanismo para bloquear a chave, de modo que apenas um cliente de cada 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 de armazenamento de estado. Em um determinado momento, um dos clientes está ativo e o outro está de prontidão para assumir imediatamente o controle se o sistema ativo travar ou falhar. Idealmente, apenas um cliente deve escrever para o 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 tentem simultaneamente gravar nas mesmas chaves. Este cenário cria uma condição de corrida.
O armazenamento estatal fornece mecanismos para evitar essa condição de corrida usando tokens de esgrima. Para obter mais informações sobre tokens de esgrima e a classe de condições de corrida contra as quais eles foram projetados para se proteger, consulte este artigo.
Obter um token de esgrima
Este exemplo pressupõe que temos os seguintes elementos:
Client1
eClient2
. 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 de vários escritores.
Os clientes tentam obter um bloqueio como primeiro passo. Eles obtêm um bloqueio fazendo um SET LockName {CLIENT-NAME} NEX PX {TIMEOUT-IN-MILLISECONDS}
. Lembre-se de Definir Opções de que o NEX
sinalizador significa que o SET
êxito somente se uma das seguintes condições for atendida:
- A chave estava vazia
- O valor da chave já está definido como <valor> e
PX
especifica o tempo limite em milissegundos.
Suponha que Client1
vai primeiro com um pedido de SET LockName Client1 NEX PX 10000
. Este pedido dá-lhe a propriedade de LockName
10.000 milissegundos. Se Client2
as tentativas demorarem algum SET LockName Client2 NEX ...
tempo Client1
a possuir o bloqueio, o sinalizador NEX
significa que o Client2
pedido falha. Client1
precisa renovar este bloqueio enviando o mesmo SET
comando usado para adquirir o bloqueio, se Client1
quiser continuar a propriedade.
Nota
A SET NX
é conceitualmente equivalente a AcquireLock()
.
Use os tokens de esgrima em solicitações SET
Quando Client1
executa com êxito um SET
("AcquireLock") no LockName
, o armazenamento de estado retorna a versão de LockName
como um relógio lógico híbrido (HLC) na propriedade __ts
de usuário MQTT5.
Quando um cliente executa uma SET
solicitação, ele pode opcionalmente incluir a propriedade __ft
de usuário MQTT5 para representar um "token de esgrima". O __ft
é representado como um HLC. O token de esgrima associado a um determinado par chave-valor fornece verificação de propriedade de bloqueio. O token de esgrima pode vir de qualquer lugar. Para este cenário, ele deve vir da versão do LockName
.
O diagrama a seguir mostra o processo de Client1
fazer uma SET
solicitação em LockName
:
Em seguida, Client1
usa a __ts
propriedade (Property=1696374425000:1:StateStore
) não modificada como base da __ft
propriedade na solicitação de modificação ProtectedKey
. Como todas as SET
solicitações, o cliente deve definir a __ts
propriedade de ProtectedKey
.
O diagrama a seguir mostra o processo de Client1
fazer uma SET
solicitação em ProtectedKey
:
Se a solicitação for bem-sucedida, a partir deste ponto ProtectedKey
será necessário um token de esgrima igual ou maior do que o especificado na SET
solicitação.
Algoritmo de token de esgrima
O armazenamento de estado aceita qualquer HLC para o __ts
de um par chave-valor, se o valor estiver dentro da inclinação máxima do relógio. No entanto, o mesmo não acontece com os tokens de esgrima.
O algoritmo de armazenamento de estado para tokens de esgrima é o seguinte:
- Se um par chave-valor não tiver um token de vedação associado a ele e uma
SET
solicitação for definida__ft
, o armazenamento de estado armazenará o associado__ft
ao par chave-valor. - Se um par chave-valor tiver um token de esgrima associado a ele:
- Se uma
SET
solicitação não especificar__ft
, rejeite a solicitação. - Se uma
SET
solicitação especificou um__ft
que tem um valor HLC mais antigo do que o token de vedação associado ao par chave-valor, rejeite a solicitação. - Se uma
SET
solicitação especificou um__ft
que tem um valor HLC igual ou mais recente do que o token de vedação associado ao par chave-valor, aceite a solicitação. O armazenamento de estado atualiza o token de vedação do par chave-valor para ser o definido na solicitação, se for mais recente.
- Se uma
Depois que uma chave é marcada com um token de cerca, para que uma solicitação seja bem-sucedida, DEL
as VDEL
solicitações também exigem que a __ft
propriedade seja incluída. O algoritmo é idêntico ao anterior, exceto que o token de esgrima não é armazenado porque a chave está sendo excluída.
Comportamento do cliente
Estes mecanismos de bloqueio dependem de os clientes serem bem comportados. No exemplo anterior, um comportamento Client2
incorreto não poderia possuir o e ainda executar com sucesso um LockName
SET ProtectedKey
escolhendo um token de esgrima que é mais recente do que o ProtectedKey
token. A loja estatal não tem conhecimento disso LockName
e ProtectedKey
tem qualquer relação. Como resultado, o armazenamento de estado não executa a validação que Client2
realmente possui o valor.
Os clientes serem capazes de escrever chaves para as quais eles realmente não possuem a fechadura, é um comportamento indesejável. Você pode se proteger contra esse mau comportamento do cliente implementando corretamente os clientes e usando a autenticação para limitar o acesso a chaves apenas a clientes confiáveis.
Notificações
Os clientes podem se registrar no armazenamento estadual para receber notificações de chaves que estão sendo modificadas. Considere o cenário em que um termostato usa a chave {thermostatName}\setPoint
de armazenamento de estado. Outros clientes de armazenamento de estado podem alterar o valor dessa chave para alterar o setPoint do termostato. Em vez de sondar para alterações, o termostato pode se registrar no armazenamento de estado para receber mensagens quando {thermostatName}\setPoint
for modificado.
KEYNOTIFY mensagens de solicitação
Os clientes do State Store solicitam que o State Store monitore um determinado keyName
para alterações enviando uma KEYNOTIFY
mensagem. Assim como todas as solicitações de armazenamento de estado, os clientes PUBLICAM uma mensagem QoS1 com essa mensagem via MQTT5 no tópico statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke
do sistema de armazenamento de estado.
A carga útil da solicitação tem a seguinte forma:
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-chave para ouvir as notificações. Atualmente, não há suporte para curingas.{optionalFields}
Os valores de campo opcionais atualmente suportados são:{STOP}
Se houver uma notificação existente com a mesmakeyName
solicitação eclientId
como essa solicitação, o armazenamento de estado a removerá.
O exemplo de saída a seguir mostra uma KEYNOTIFY
solicitação 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 de armazenamento de estado, o armazenamento de estado retorna sua resposta para o Response Topic
e usa as Correlation Data
propriedades especificadas da solicitação inicial. Para KEYNOTIFY
, uma resposta bem-sucedida indica que o armazenamento de estado processou a solicitação. Depois que o armazenamento de estado processa a solicitação com êxito, ele monitora a chave para o cliente atual ou interrompe o monitoramento.
Sobre o sucesso, a resposta da loja estatal é a mesma de um sucesso SET
.
+OK<CR><LF>
Se um cliente enviar uma KEYNOTIFY SOMEKEY STOP
solicitação, mas o armazenamento de estado não estiver monitorando essa chave, a resposta do armazenamento 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 armazenamento de estado:
-ERR: <DESCRIPTION OF ERROR><CR><LF>
Tópicos de notificação KEYNOTIFY e ciclo de vida
Quando uma keyName
via KEYNOTIFY
que está sendo monitorada é modificada ou excluída, o armazenamento de estado envia uma notificação para o cliente. O tópico é determinado por convenção - o cliente não especifica o tópico durante o KEYNOTIFY
processo.
O tópico é definido no exemplo a seguir. O clientId
é uma representação codificada hexadecimal maiúscula do MQTT ClientId do cliente que iniciou a KEYNOTIFY
solicitação e keyName
é uma representação codificada hexadecimal da chave que foi alterada. O armazenamento de estado segue as regras de codificação Base 16 da 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}
Como exemplo, o broker MQTT publica uma NOTIFY
mensagem enviada para client-id1
com o nome SOMEKEY
da chave modificada 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 esperar que o SUBACK
seja recebido antes de enviar quaisquer KEYNOTIFY
solicitações para que nenhuma mensagem seja perdida.
Se um cliente se desconectar, ele deverá se inscrever novamente no tópico de notificação e reenviar o comando para todas as KEYNOTIFY
KEYNOTIFY
chaves necessárias para continuar monitorando. Ao contrário das assinaturas MQTT, que podem ser persistidas em uma sessão não limpa, o armazenamento de estado remove internamente todas KEYNOTIFY
as mensagens quando um determinado cliente se desconecta.
KEYNOTIFY formato de mensagem de notificação
Quando uma chave que está sendo monitorada é KEYNOTIFY
modificada, o armazenamento de estado enviará PUBLISH
uma mensagem para o tópico de notificação seguindo o formato para declarar os clientes de armazenamento 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 na carga útil, indicando que uma notificação chegou.{operation}
é o evento que ocorreu. Atualmente estas operações são:SET
o valor foi modificado. Essa operação só pode ocorrer como resultado de umSET
comando de um cliente de armazenamento de estado.DEL
O valor foi excluído. Essa operação pode ocorrer devido a umDEL
comando ouVDEL
de um cliente de armazenamento de estado.
optionalFields
VALUE
e{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 só é enviado em resposta a chaves que estão sendo modificadas devido a umSET
arquivo .
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 GET
opção:
*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 KEYNOTIFY
mensagem de notificação 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 de 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.