|
Some checks are pending
Build Android (APK + AAB) / build-android (push) Waiting to run
Confirmado: BMS responde ao app oficial Xiaoxiang. Problema é técnica de inicialização não implementada na nossa abordagem. Adicionado wake-up sequence ANTES do probe de protocolos: 1. ble.read na notify char (acorda stack BLE) 2. delay 300ms 3. write 0x5A x4 (handshake hello observado em alguns Xiaoxiang) 4. delay 1500ms (BMS processa wake) 5. probe normal de protocolos Cada step protegido por try/catch + timeout 2s — não trava loop. Logs detalhados pra ver onde falha se acontecer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| public | ||
| src | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
Shivao Cloud
Backend para o Diário de Bordo do Shivao com:
- ☁️ Sincronização dos dados na nuvem (multi-dispositivo)
- 📷 Mídia (fotos, áudios, vídeos) armazenada no servidor
- 🚨 Notificações automáticas (Telegram, e-mail, SMS, WhatsApp, ntfy, webhook) — sem precisar tocar em botão
- 🛡️ Dead-man switch: se o celular perde sinal/bateria enquanto fundeado, o servidor mesmo dispara o alarme
Deploy no Coolify (passo a passo)
1. Subir o código para um repositório Git
Crie um repo no GitHub/GitLab e envie esta pasta. Ou use o "Public Repository" do Coolify direto.
2. No painel Coolify
- + New Resource → Application → Public/Private Repository
- Cole a URL do seu repositório
- Build Pack:
Dockerfile - Port:
3000 - Domain: configure seu domínio (ex:
shivao.seu-dominio.com) — Coolify gera SSL automático
3. Variáveis de ambiente
Em Environment Variables no Coolify, adicione (mínimo):
| Variável | Valor |
|---|---|
BOAT_TOKEN |
string aleatória longa (ex: openssl rand -hex 32) |
TELEGRAM_BOT_TOKEN |
seu token do BotFather |
TELEGRAM_CHAT_IDS |
seu chat ID |
Veja .env.example para todas as opções (e-mail, SMS, etc.). Configure pelo menos um canal.
4. Volume persistente
Em Storages → Persistent Storage:
- Name:
shivao-data - Mount Path:
/data
Sem isso, ao reiniciar o container você perde o banco e as mídias.
5. Deploy
Clique em Deploy. Aguarde o build. Acesse https://shivao.seu-dominio.com — vai aparecer o app.
Configurando o Telegram (5 minutos, recomendado)
- No Telegram, fale com @BotFather →
/newbot - Escolha um nome e username → ele dá um token
- Inicie uma conversa com o bot que você criou (mande qualquer mensagem)
- Acesse
https://api.telegram.org/bot<SEU_TOKEN>/getUpdatesno navegador - No JSON, procure
"chat":{"id":123456789...}— esse é seuTELEGRAM_CHAT_IDS - Cole no Coolify e redeploy
Para receber em grupo: adicione o bot ao grupo, mande uma mensagem, repita o passo 4 (chat ID será negativo).
Configurando ntfy.sh (sem cadastro, push grátis)
- Instale o app ntfy (Android / iOS)
- No app, Subscribe → invente um tópico único e secreto (ex:
shivao-aljg29x71kqp) - Coloque esse mesmo nome em
NTFY_TOPICno Coolify
⚠️ Como ntfy é público, qualquer pessoa que adivinhe o tópico vê suas notificações. Use algo aleatório e longo.
Configurando E-mail SMTP
Gmail (mais comum):
- Ative verificação em 2 etapas na conta Google
- Vá em Senhas de app
- Gere uma senha → use ela em
SMTP_PASS - Configure:
SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_SECURE=false SMTP_USER=seu-email@gmail.com SMTP_PASS=senha-de-app-de-16-caracteres SMTP_FROM=Shivao Alertas <seu-email@gmail.com> SMTP_TO=destinatario@email.com,outro@email.com
Resend, SendGrid, Mailgun: similar, basta seguir o painel deles e usar SMTP.
Configurando Twilio (SMS / WhatsApp — pago)
Apenas se quiser SMS ou WhatsApp realmente automático.
- Crie conta em twilio.com
- Para SMS: compre um número (Brasil custa ~$1/mês + $0.05 por SMS)
- Para WhatsApp: ative o sandbox grátis OU peça aprovação Business
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=xxxxxxxxxxxxx
TWILIO_FROM_NUMBER=+15551234567
TWILIO_SMS_TO=+5521999998888
TWILIO_WHATSAPP_FROM=whatsapp:+14155238886
TWILIO_WHATSAPP_TO=whatsapp:+5521999998888
Como funciona o Dead-Man Switch
- Quando você toca em "Fundear" no app, ele avisa o servidor
- Enquanto a vigia está ativa, o app envia um heartbeat a cada 30 segundos: "estou vivo, GPS aqui"
- Se o servidor não receber heartbeat por 5 minutos (
HEARTBEAT_TIMEOUT_SECconfigurável), ele assume que algo deu errado (celular morreu, perdeu sinal, app fechou) e dispara o alarme remoto automaticamente para todos os contatos - Quando você levanta âncora normalmente, o app avisa o servidor para parar a vigia
Isso garante que mesmo se você dormir e o celular morrer, alguém vai ser avisado.
Endpoints da API (referência)
Todas requerem header Authorization: Bearer <BOAT_TOKEN> (exceto /api/health).
| Método | Rota | Função |
|---|---|---|
| GET | /api/health |
Status público |
| GET | /api/info |
Canais configurados |
| GET | /api/data |
Baixar todo o estado |
| POST | /api/data |
Enviar todo o estado |
| POST | /api/media |
Upload de arquivo (multipart) |
| GET | /api/media/list |
Lista de mídias |
| GET | /api/media/:id |
Baixar mídia |
| DELETE | /api/media/:id |
Apagar mídia |
| POST | /api/anchor/start |
Iniciar vigia no servidor |
| POST | /api/anchor/heartbeat |
Manter vivo |
| POST | /api/anchor/alarm |
Disparar alarme imediato |
| POST | /api/anchor/stop |
Encerrar vigia |
| GET | /api/anchor/status |
Estado atual |
| POST | /api/test |
Disparar mensagem de teste |
| GET | /api/alarms |
Histórico de alarmes |
| POST | /api/share/create |
Criar link público temporário |
| GET | /api/share/list |
Listar shares ativos |
| DELETE | /api/share/:token |
Revogar share |
| POST | /api/share/position |
Postar posição (boat → server) |
| GET | /share/:token |
Página pública do link (sem auth) |
| GET | /api/share/:token/info |
Info do share (público) |
| GET | /api/share/:token/positions |
Posições do share (público) |
Rodando localmente (dev)
cp .env.example .env
# edite .env
npm install
npm start
Ou com Docker:
docker compose up --build
Acesse http://localhost:3000
Conectando o app
No app (Diário de Bordo), vá em Arquivo → Configurações da Nuvem, preencha:
- Servidor:
https://shivao.seu-dominio.com - Token: o mesmo
BOAT_TOKENque você definiu
Toque em Testar conexão → deve receber a mensagem de teste em todos os canais configurados.
A partir daí o app sincroniza automaticamente.