Pular para o conteúdo
JelinaJelina DocumentationDocumentação técnica
Voltar ao site oficial

Envio em tempo real ao frontend e controle direto

A etapa de “Execução” da visão geral da arquitetura inclui, além de gravação em pontos, alarmes e MQTT, o atendimento direto ao frontend. O Edge-EMS Builder oferece dois canais WebSocket para que interfaces personalizadas possam receber dados em tempo real e enviar comandos diretamente aos dispositivos, sem desenvolver uma camada intermediária.

Canal Caminho Autenticação Finalidade
Canal de envio ao frontend ws://<host>:<port>/front Token de login (obtido após login com nome de usuário e senha) Interfaces personalizadas: verifica as permissões da função e oferece assinatura de dados + gravação direta
Canal de leitura/gravação de dados ws://<host>:<port>/data/rw data-rw-token estático (configurado em ems.yaml) Integração de sistemas de backend: independe de login e oferece leitura/gravação de baixa latência, adequada à integração entre sistemas

Os formatos de mensagem dos dois canais são idênticos; as diferenças estão na autenticação e na granularidade da verificação de permissões. Esta página se concentra em /front, e o uso de /data/rw segue o mesmo padrão.

Informe os parâmetros na Query ao conectar:

ws://<host>:<port>/front?socketId=<ID_de_conexão_personalizado>&token=<Token_de_login>
ws://<host>:<port>/data/rw?socketId=<ID_de_conexão_personalizado>&token=<data-rw-token>

Estrutura unificada do quadro de solicitação (frontend → Edge-EMS Builder):

{
"topic": "read | write | clear",
"messageId": "ID exclusivo personalizado para correlacionar a resposta",
"keep": true,
"content": [
{ "dataKey": "pcsActivePower" }
]
}

Quadro de resposta (Edge-EMS Builder → frontend), correlacionado individualmente à solicitação por messageId:

{
"code": "200",
"message": "Processed successfully",
"topic": "read",
"messageId": "...",
"time": "2026-07-23T10:00:00+08:00",
"data": { "...": "..." }
}

III. Receber dados em tempo real (assinatura = read + keep)

Seção intitulada “III. Receber dados em tempo real (assinatura = read + keep)”

O modelo de envio do Edge-EMS Builder não é uma publicação/assinatura em um Topic: cada conexão declara sua própria “configuração de envio”:

  1. O frontend envia topic: "read", lista os dataKey desejados em content (ou usa groupCode para acompanhar um grupo inteiro) e define keep como true.
  2. Ao receber a solicitação, o Edge-EMS Builder registra esse content como configuração de envio da conexão (socketId) e retorna imediatamente os valores atuais.
  3. Depois disso, uma tarefa em segundo plano do Edge-EMS Builder percorre a cada 1 segundo todos os sockets de frontend ainda conectados e envia os valores mais recentes definidos em suas configurações, sem exigir polling repetido do frontend.
  4. Se não precisar de envio contínuo, defina keep como false ou omita-o; o Edge-EMS Builder enviará dados apenas por 30s.
  5. Para cancelar a configuração de envio de uma conexão, envie topic: "clear".
// Assinatura: acompanha continuamente os valores mais recentes de pcsActivePower e bmsSOC
{
"topic": "read",
"messageId": "sub-001",
"keep": true,
"content": [
{ "dataKey": "pcsActivePower" },
{ "dataKey": "bmsSOC" }
]
}
// Ou assina por grupo, acompanhando todos os pontos, inclusive subgrupos
{
"topic": "read",
"messageId": "sub-002",
"keep": true,
"content": [
{ "groupCode": "pcs-group-01" }
]
}

A mesma conexão pode enviar read + keep:true várias vezes para acrescentar ou atualizar a configuração. Pelo menos um dos campos dataKey e groupCode deve ser informado.

O frontend envia topic: "write" e informa dataKey e dataValue em content, sem precisar especificar o tipo de dado. O Edge-EMS Builder identifica automaticamente pelo dataKey se o dado é original (Collection), agregado (Aggregation) ou por faixa de horário (Customization) e encaminha à lógica de gravação correspondente:

{
"topic": "write",
"messageId": "ctrl-001",
"content": [
{ "dataKey": "pcsActivePower", "dataValue": "300" }
]
}

Ao gravar dados por faixa de horário (Customization), é possível incluir o intervalo de vigência:

{
"topic": "write",
"messageId": "ctrl-002",
"resetCustomValue": true,
"content": [
{
"dataKey": "import_price",
"dataValue": "0.85",
"availableDate": "2026-06-25T00:00:00+08:00",
"expiredDate": "2026-06-25T08:00:00+08:00"
}
]
}
  • resetCustomValue: true indica que os valores existentes desse dado por faixa de horário devem ser apagados antes de gravar o novo conteúdo. É usado na substituição integral de um plano para evitar conflitos de sobreposição entre períodos antigos e novos.
  • Para gravar pontos de outros dispositivos compartilhados, adicione o campo deviceCode ao elemento content correspondente. O Edge-EMS Builder identifica a gravação como compartilhada e a encaminha ao dispositivo de destino.
  • Conexão por /data/rw com data-rw-token estático: acesso direto, sem verificação de função, adequado à integração entre sistemas de backend.
  • Conexão por /front com Token de login: verifica se a conta tem a função de superadministrador, administrador ou operador. Observadores não podem gravar, seguindo as mesmas regras da interface; não existe um caminho de gravação que contorne as permissões do frontend.

DAILY_REPEAT usa availableTime / expiredTime (por exemplo, 08:00:00 a 12:00:00), com as datas gerais de vigência configuradas no ponto por faixa de horário. Apenas DAILY_CHANGE usa intervalos completos de data e hora. Os parâmetros não são intercambiáveis, e períodos que cruzam a meia-noite devem ser divididos.

/front verifica a conexão por heartbeat Ping/Pong. O cliente deve tratar o code/message de fechamento e restabelecer as assinaturas após reconectar. Solicitações de gravação não devem ser reenviadas automaticamente junto com as assinaturas.

A gravação no dispositivo depende da resposta do CommBridge ou do resultado de timeout; o sucesso do envio, isoladamente, não confirma a execução. Consulte os logs de controle de dispositivos para acompanhar processamento, sucesso e falha. A conversão inversa do coeficiente de gravação é feita pelo CommBridge; o chamador não deve repeti-la.

Durante o bloqueio para manutenção, gravações de controle protegidas retornam 200162. Não saia automaticamente do bloqueio para tentar novamente.

const ws = new WebSocket(`ws://<host>:<port>/front?socketId=web-ui-01&token=${loginToken}`);
ws.onopen = () => {
// Assina dados em tempo real: potência ativa do PCS e SOC
ws.send(JSON.stringify({
topic: 'read',
messageId: 'sub-' + Date.now(),
keep: true,
content: [
{ dataKey: 'pcsActivePower' },
{ dataKey: 'bmsSOC' }
]
}));
};
ws.onmessage = (event) => {
const resp = JSON.parse(event.data);
if (resp.topic === 'read') {
// Recebe os valores mais recentes a cada segundo e atualiza os painéis/gráficos da interface
renderDashboard(resp.data);
}
if (resp.topic === 'write') {
// Retorno do resultado da gravação: resp.successContent / resp.errorContent
showWriteResult(resp);
}
};
// Quando o usuário clica no botão "Definir potência em 300kW" na interface:
function setPower(value) {
ws.send(JSON.stringify({
topic: 'write',
messageId: 'ctrl-' + Date.now(),
content: [{ dataKey: 'pcsActivePower', dataValue: String(value) }]
}));
}

Esse código cobre a interação típica completa: “Assinar dados ao carregar a página → Atualizar a interface automaticamente a cada segundo → Enviar comandos diretamente a partir das ações do usuário → Receber o resultado da gravação”, sem um serviço adicional de backend intermediário.

  • Dados gravados por /front ou /data/rw são os mesmos dados lidos pelos perfis de acionamento e pelo mecanismo de expressões. Após a leitura de retorno pela aquisição, o resultado final do controle pelo frontend pode continuar participando de expressões agregadas e condições de gatilho. Consulte Modelo de dados.
  • Se precisar enviar dados também a um painel na nuvem, os dois caminhos podem coexistir: use /front para a interface própria e colaboração entre nuvem e borda por MQTT para enviar os mesmos dados à nuvem.
  • A Skill de configuração por IA aems-write-data encapsula as chamadas de /data/rw e /front, permitindo pedir ao AI Agent, em linguagem natural, que ajude a depurar comandos de gravação.