Pular para o conteúdo

Tempo real por WebSocket

Guia de uso do canal ao vivo. A referência completa do canal está na navegação lateral, em Canais assíncronos.

  1. Abra a conexão, autenticando conforme o seu tipo de cliente (ver autenticação).
  2. Envie um subscribe com os ids das estações.
  3. Receba subscription.updated, depois reading a cada leitura nova.

Uma conexão sem assinatura não recebe nada: abrir e esperar não funciona.

De servidor, o handshake leva a credencial no cabeçalho:

// Node, biblioteca ws
const ws = new WebSocket('wss://stream.radar-sandbox.kitelife.com.br/v1/stream', {
headers: { Authorization: `Bearer ${process.env.RADAR_API_KEY}` },
})
ws.on('open', () => ws.send(JSON.stringify({
action: 'subscribe',
stations: ['stn_barra-da-tijuca-01'],
})))
ws.on('message', (raw) => {
const msg = JSON.parse(raw)
if (msg.type === 'reading') gravar(msg.data)
if (msg.type === 'station.status' && msg.status === 'offline') marcarComoAntigo(msg.stationId)
})

Do navegador, onde não há como definir cabeçalhos, o handshake usa um ticket pedido antes na REST:

const ws = new WebSocket(`wss://stream.radar-sandbox.kitelife.com.br/v1/stream?ticket=${ticket}`)

Cada subscribe troca a lista inteira. Para acompanhar mais uma estação, mande as antigas junto com a nova. Mandar só a nova cancela as outras, e este é o erro mais comum nesta API.

Confira o subscription.updated que volta: ele traz o que ficou assinado de fato. Um id inexistente ou fora do escopo da sua chave é omitido em silêncio, sem erro, então a única forma de perceber o engano é comparar o que você pediu com o que voltou.

Conexão de longa duração cai, e isso não é falha de ninguém. Rede móvel oscila, proxies encerram conexões ociosas, e de vez em quando publicamos uma versão nova. Nenhuma dessas situações está sob o seu controle, então o cliente precisa saber reconectar sozinho.

Três regras:

Espere antes de tentar de novo, e espere cada vez mais. Comece em 1 segundo e dobre até um teto de 30. Reconexão imediata em laço, multiplicada por todos os clientes que caíram ao mesmo tempo, transforma uma implantação de rotina em uma indisponibilidade.

Adicione aleatoriedade. Se todos os clientes esperam exatamente 1, 2, 4 segundos, todos voltam no mesmo instante. Um desvio aleatório de até 30% no intervalo resolve.

No navegador, peça um ticket novo a cada tentativa. O ticket é de uso único e expira em 60 segundos. Reaproveitar o da conexão anterior falha com Ticket.Expired, e tentar em laço com um ticket morto queima a sua cota sem nunca conectar.

let tentativa = 0
async function conectar() {
const ticket = await pedirTicket()
const ws = new WebSocket(`wss://…/v1/stream?ticket=${ticket}`)
ws.onopen = () => { tentativa = 0; assinar(ws) }
ws.onclose = () => {
const base = Math.min(1000 * 2 ** tentativa++, 30000)
setTimeout(conectar, base * (0.85 + Math.random() * 0.3))
}
}

Tudo o que passou enquanto você estava fora. O canal não tem fila nem reposição: ao reconectar, você recebe a próxima leitura, não as anteriores.

Se a lacuna importa, preencha pela REST, com GET /stations/{id}/readings e from no instante da última leitura recebida. Se lacunas importam sempre e em volume, o canal certo é o relay AMQP, que guarda.

Uma mensagem error é informativa: a conexão segue aberta e a assinatura anterior continua valendo. A exceção é fatal: true, quando o servidor fecha logo depois. Aí reconectar imediatamente não adianta, porque o problema é a credencial ou a requisição, e vai se repetir.

Quando uma estação assinada cai, chega um station.status com offline. As estações não têm bateria, então uma queda de energia no local as derruba por inteiro, em segundos.

O que a sua interface faz com isso importa mais do que parece. O último valor recebido continua na tela, correto quando chegou e cada vez mais velho depois. Marque-o como antigo: mostre a hora da medição, esmaeça o número, o que couber no seu desenho. Um vento de 20 nós exibido como atual, medido há três horas, é pior do que não mostrar nada.

Limite Valor
Estações por conexão 50
Conexões simultâneas por chave negociável
Validade do ticket 60 s, uso único

Precisando de mais de 50 estações, abra outra conexão ou vá de AMQP. Trinta estações de 8 segundos já são cerca de quatro mensagens por segundo: verifique se o seu cliente aguenta antes de aumentar.