Files
NoIdle/ESPECIFICACAO_CLIENTE_WINDOWS.md
root 6086c13be7 feat: Implementação completa do NoIdle - Cliente, Backend e Scripts
- Cliente Windows com modo silencioso e auto-start robusto
- Backend Node.js + API REST
- Frontend Next.js + Dashboard
- Scripts PowerShell de configuração e diagnóstico
- Documentação completa
- Build scripts para Windows e Linux
- Solução de auto-start após reinicialização

Resolução do problema: Cliente não voltava ativo após reboot
Solução: Registro do Windows + Task Scheduler + Modo silencioso
2025-11-16 22:56:35 +00:00

6.5 KiB
Raw Blame History

Especificação Completa - Cliente Windows NoIdle

📋 Visão Geral

O cliente Windows deve monitorar e enviar para o servidor:

  1. Aplicativos ativos (window_title, application_name)
  2. Histórico de navegação (URLs do Chrome/Edge)
  3. Eventos de sessão (logon/logoff do Windows)

🔌 Endpoints da API

Base URL

https://admin.noidle.tech

1 Registrar Atividade (Aplicativos)

Endpoint: POST /api/activity/log

Frequência: A cada 5-10 segundos (quando há mudança de aplicativo/janela)

Headers:

Content-Type: application/json

Body:

{
  "device_id": "DEV-1762999424206-0BJR2Q",
  "window_title": "Documento - Word",
  "application_name": "WINWORD.EXE",
  "idle_time_seconds": 0,
  "urls": [
    {
      "url": "https://example.com/page",
      "title": "Example Page",
      "browser": "Chrome"
    }
  ]
}

Campos Obrigatórios:

  • device_id (string): ID único do dispositivo
  • window_title (string): Título da janela ativa (NÃO pode ser "System Idle" ou vazio)
  • application_name (string): Nome do executável (ex: "chrome.exe", "WINWORD.EXE", "notepad.exe")
  • idle_time_seconds (number): Tempo em segundos que o usuário está inativo (0 = ativo)

Campos Opcionais:

  • urls (array): Array de objetos com histórico de navegação (ver seção 2)

⚠️ IMPORTANTE:

  • NÃO envie window_title = "System Idle" ou application_name = "[IDLE]" quando o usuário está realmente usando um aplicativo
  • Se o usuário estiver inativo por mais de 30 segundos, aí sim pode enviar idle_time_seconds > 0
  • Capture o título real da janela e o executável real usando APIs do Windows

Exemplo de Resposta:

{
  "success": true,
  "message": "Atividade registrada"
}

2 Histórico de Navegação (Chrome/Edge)

Endpoint: POST /api/activity/log (mesmo endpoint, campo urls)

Frequência: A cada vez que uma nova URL é visitada no navegador

Como Capturar:

  • Use a API do Chrome/Edge para monitorar abas abertas
  • Capture URLs de todas as abas ativas
  • Envie no array urls dentro do mesmo POST de atividade

Estrutura do Array urls:

{
  "urls": [
    {
      "url": "https://www.google.com/search?q=exemplo",
      "title": "exemplo - Pesquisa Google",
      "browser": "Chrome"
    },
    {
      "url": "https://github.com/user/repo",
      "title": "user/repo · GitHub",
      "browser": "Chrome"
    }
  ]
}

Campos:

  • url (string): URL completa visitada
  • title (string): Título da página/aba
  • browser (string): "Chrome" ou "Edge"

⚠️ IMPORTANTE:

  • Envie URLs de TODAS as abas abertas, não apenas a ativa
  • Atualize a lista sempre que uma nova aba for aberta ou fechada
  • Não envie URLs vazias ou inválidas

3 Eventos de Sessão (Logon/Logoff)

Endpoint: POST /api/activity/session

Frequência: Imediatamente quando ocorre logon ou logoff

Headers:

Content-Type: application/json

Body para LOGON:

{
  "device_id": "DEV-1762999424206-0BJR2Q",
  "event_type": "logon",
  "username": "Sergio.Dev"
}

Body para LOGOFF:

{
  "device_id": "DEV-1762999424206-0BJR2Q",
  "event_type": "logoff",
  "username": "Sergio.Dev"
}

Campos Obrigatórios:

  • device_id (string): ID único do dispositivo
  • event_type (string): "logon" ou "logoff"
  • username (string): Nome do usuário do Windows

Como Capturar:

  • Use eventos do Windows: SessionSwitch, SessionLock, SessionUnlock
  • Monitore o evento de logon do sistema operacional
  • Capture o username do usuário logado

Exemplo de Resposta:

{
  "success": true,
  "message": "Evento logon registrado"
}

4 Heartbeat (Opcional mas Recomendado)

Endpoint: POST /api/devices/heartbeat

Frequência: A cada 30-60 segundos

Body:

{
  "device_id": "DEV-1762999424206-0BJR2Q"
}

Nota: O heartbeat é opcional se você estiver enviando atividades regularmente, mas ajuda a manter o dispositivo marcado como ativo.


🔧 Implementação Técnica

Capturar Window Title e Application Name (C#/PowerShell)

using System;
using System.Runtime.InteropServices;
using System.Text;

[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);

// Obter janela ativa
IntPtr hwnd = GetForegroundWindow();
StringBuilder windowTitle = new StringBuilder(256);
GetWindowText(hwnd, windowTitle, 256);

// Obter processo
uint processId;
GetWindowThreadProcessId(hwnd, out processId);
Process process = Process.GetProcessById((int)processId);
string appName = process.ProcessName + ".exe";

Capturar URLs do Chrome (PowerShell)

# Usar Chrome DevTools Protocol ou ler histórico do Chrome
# Alternativa: usar extensão do Chrome que envia dados via API local

Capturar Eventos de Sessão (C#)

using Microsoft.Win32;

SystemEvents.SessionSwitch += (sender, e) => {
    if (e.Reason == SessionSwitchReason.SessionLock) {
        // Logoff ou bloqueio
    } else if (e.Reason == SessionSwitchReason.SessionUnlock) {
        // Logon ou desbloqueio
    }
};

Checklist de Implementação

  • Cliente captura window_title real (não "System Idle")
  • Cliente captura application_name real (exe do processo)
  • Cliente envia atividades a cada 5-10 segundos quando há mudança
  • Cliente monitora e envia URLs do Chrome/Edge
  • Cliente detecta eventos de logon/logoff do Windows
  • Cliente envia eventos de sessão imediatamente
  • Cliente trata erros de rede e faz retry
  • Cliente valida dados antes de enviar

🐛 Troubleshooting

Problema: Apenas "System Idle" aparece nas atividades

Solução: Verifique se o código está capturando a janela ativa corretamente. Use GetForegroundWindow() e não confie em valores padrão.

Problema: URLs não aparecem

Solução: Verifique se o array urls está sendo enviado no POST /api/activity/log e se contém dados válidos.

Problema: Eventos de sessão não aparecem

Solução: Verifique se o cliente está escutando eventos do Windows corretamente e se está fazendo POST para /api/activity/session.


📞 Suporte

Para problemas técnicos, verifique:

  1. Logs do cliente (console/arquivo de log)
  2. Logs do servidor: pm2 logs pointcontrol-api
  3. Resposta HTTP dos endpoints (status code, mensagem de erro)