|
Some checks failed
Build Android (APK + AAB) / build-android (push) Has been cancelled
Servidor (proxy assinado):
- server/src/tuya.js: cliente Tuya OpenAPI com HMAC-SHA256 + token cache
(2h TTL, retry 1x em token expirado), helpers categoryLabel
- 3 endpoints novos em server/src/index.js (todos requireAuth):
* GET /api/iot/devices → lista devices da conta Smart Life
* GET /api/iot/status/:deviceId → DPs (data points) atuais
* POST /api/iot/command/:deviceId → envia comandos {code,value}
- Audit log via db.audit('iot_command', ...) pra histórico de toggles
- 503 graceful quando TUYA_ACCESS_ID/SECRET ausentes
Client (UI):
- Card 🏠 Casa do Barco em Arquivo (após Bluetooth, antes Raymarine)
- Modal "Adicionar dispositivo" lista devices da conta Smart Life,
permite escolher quais aparecem no Shivão (multi-select via toque)
- Cards por device com ícone por categoria (cz=tomada, dj=lâmpada,
fs=ventilador, kt=ar-cond, sd=robô, etc.) + toggle ON/OFF + status
online/offline + tempo desde último ping
- Toggle optimistic UI: marca novo estado imediato, reverte se falhar
- Polling 10s pra sync de status, pausa em background (economiza
Starlink + bateria)
- Backoff: 3 falhas consec → marca offline, retry 30s
- state.smartDevices[] persistido no localStorage (mesmo padrão btDevices)
Setup (admin, 1x):
- Karlão precisa criar projeto em iot.tuya.com (5 min, gratuito) e
adicionar TUYA_ACCESS_ID + TUYA_ACCESS_SECRET no env Coolify
- Documentação completa no .env.example com passo a passo
- Sem credenciais: card mostra "⚙ Tuya não configurado"
Bumps:
- APP_VERSION 1.11.0 → 1.12.0
- sw.js VERSION shivao-v1.11.0 → shivao-v1.12.0
- mobile/package.json + build.gradle (versionCode 32→33)
- LATEST_APK_URL atualizado pro release v1.12.0
Fix gitignore:
- .env.example em pastas nested (server/.env.example) estava bloqueado
por **/.env.* — adicionado !**/.env.example pra liberar.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| public | ||
| src | ||
| .env.example | ||
| .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.