Synaplan
기업을 위한 오픈소스 AI 플랫폼
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Plataforma SaaS multi-empresa para monitoreo de flotas y teléfonos en tiempo real: mapa en vivo con seguimiento, historial de rutas con reproducción, geocercas con alertas, comandos remotos, usuarios cliente de solo lectura y localización de teléfonos Android/iOS con consentimiento.
┌──────────── Equipos GPS ────────────┐
│ Gateway JSON │ TCP $POS │ OsmAnd │ Teléfono (navegador)
└──────┬─────────────────────┬────────┘
HTTP │ │ TCP :5023
▼ ▼
┌──────────────────────────────┐ ┌─────────────────────┐
│ apps/web /api/ingest/* │ │ apps/ingest │ Fastify + net
│ (Vercel, serverless) │ │ (Fly/Railway/VPS) │
└──────────────┬───────────────┘ └──────────┬──────────┘
└─────────┬────────────────────┘
▼
packages/ingest-core (pipeline)
IMEI→dispositivo · hipertabla · última posición · geocercas PostGIS
│ │
▼ ▼
PostgreSQL + TimescaleDB + PostGIS Redis Pub/Sub tenant:<id>:live
▲ │
│ ▼
┌──────────────┴───────────────┐ ┌─────────────────────┐
│ apps/web (Next.js UI + API) │◄──│ apps/realtime (ws) │ JWT por tenant
└──────────────────────────────┘ └─────────────────────┘
| Paquete | Responsabilidad |
|---|---|
packages/telemetry | Contrato TelemetryEvent normalizado, decodificadores (gateway JSON, OsmAnd, TCP $POS) y catálogo de comandos. Puro TS, sin BD ni UI. |
packages/db | Migraciones SQL (TimescaleDB + PostGIS), esquema Drizzle, cliente postgres.js, seed. |
packages/ingest-core | Pipeline de procesamiento (IMEI → posición → geocercas → Redis) y cola de comandos. Independiente del transporte. |
apps/ingest | Servicio de ingesta de larga duración: HTTP (/gateway, /osmand) y socket TCP con entrega de comandos. |
apps/realtime | Gateway WebSocket (ws) suscrito a Redis; reparte eventos por tenant. Escalable horizontalmente. |
apps/web | Next.js (App Router) + Tailwind + shadcn/ui + MapLibre/OSM. UI, API REST y webhooks de ingesta serverless. |
tenants, users, memberships(role: owner|admin|viewer) — autenticación multi-empresa. viewer = cliente: solo ve las unidades asignadas en user_vehicle_access, sin poder registrar equipos ni enviar comandos.devices (kind: gps|phone; IMEI único global) y vehicles (asignación 1:1 opcional).positions — particionada por tiempo: hipertabla TimescaleDB si la extensión existe; si no (Supabase), particionado nativo diario mantenido con pg_cron. Coordenadas DECIMAL(10, 7).device_last_positions, geofences (geography(Polygon, 4326) + GiST), device_geofence_states, geofence_events.device_commands (cola con estados pending → sent → delivered/failed), consent_log (aceptaciones y revocaciones de teléfonos).BYPASSRLS.| Rol | Ver mapa/historial | Geocercas | Vehículos / dispositivos | Comandos | Usuarios |
|---|---|---|---|---|---|
| Propietario | todo | crear/borrar | gestionar | sí | crear clientes y administradores |
| Administrador | todo | crear/borrar | gestionar | sí | crear clientes |
| Cliente | solo sus unidades | ver | — | — | — |
docker compose up -d # Postgres (Timescale+PostGIS) y Redis
cp .env.example .env # y exporta las variables (o usa direnv)
pnpm install
pnpm db:migrate && pnpm db:seed # usuario [email protected] / demo1234
pnpm dev # web :3000, ingest :4000/:5023, realtime :4001
pnpm simulate # 3 vehículos enviando tramas TCP
Tests y comprobaciones: pnpm test, pnpm typecheck.
El servicio apps/ingest escucha en un único puerto TCP (5023) e identifica el protocolo por los primeros bytes de cada conexión. Al recibir datos de un IMEI registrado, la web actualiza el protocolo del dispositivo; si el IMEI aún no está registrado, queda anotado y la web lo reconoce al darlo de alta (búsqueda por IMEI exacto).
| Protocolo | Equipos típicos | Comandos |
|---|---|---|
| GT06 / Concox | Concox GT06N, Jimi, WeTrack, TK100 | posición, intervalo, bloqueo/desbloqueo, reinicio, personalizado (con respuesta del equipo) |
| Teltonika Codec 8 / 8E | FMB, FMC, FMM, FMT | posición, bloqueo (DOUT1), reinicio, personalizado (Codec 12, con respuesta) |
| GPS103 / Coban | TK103A/B, TK102B, GPS303 | posición, intervalo, bloqueo/desbloqueo, personalizado |
| TK103 | Xexun TK103 y clones | personalizado |
| H02 | Sinotrack ST-901/906 (texto) | personalizado |
| Meitrack | MVT, T1, T3xx | personalizado |
Octopus $POS | Firmware propio | todos |
Puertos dedicados opcionales: INGEST_PROTOCOL_PORTS="gt06:5023,teltonika:5027,gps103:5001".
Los decodificadores son código propio escrito a partir de las especificaciones públicas de cada fabricante (packages/telemetry/src/protocols) y tienen pruebas con tramas de ejemplo.
Otras marcas (Queclink, Suntech, CalAmp, Ruptela, JT808, …): mediante un servidor de protocolos de código abierto que reenvía a /api/ingest/gateway (ejemplo en deploy/protocol-gateway). Sus comandos se reenvían a COMMANDS_WEBHOOK_URL.
| Origen HTTP | Endpoint |
|---|---|
Gateway JSON {position, device} | POST https://<web>/api/ingest/gateway con cabecera X-Ingest-Token |
| Apps con protocolo OsmAnd | https://<web>/api/ingest/osmand?token=INGEST_TOKEN&id=IMEI&lat=..&lon=.. |
| Teléfono Android/iOS | Enlace https://<web>/rastreo#t=… generado en Dispositivos → Teléfono |
En Geocercas → ⚡ Acciones cada zona puede tener reglas: al entrar, al salir o ambos, para cualquier unidad o una concreta, con acción notificación push o comando a la unidad que provoca el evento (geofence_rules, motor en packages/ingest-core/src/automation.ts). El bloqueo de motor nunca se ejecuta automáticamente.
Web Push estándar (VAPID, RFC 8291/8292) implementado sin dependencias en packages/ingest-core/src/webpush.ts. Cada usuario las activa en Mi cuenta (o desde el aviso del mapa); llegan a administradores y a los clientes que ven esa unidad. En iPhone requieren instalar la web en la pantalla de inicio (iOS 16.4+). Genera las claves con:
pnpm --filter @octopus/ingest-core exec tsx -e 'import {generateVapidKeys} from "./src/webpush.ts"; console.log(generateVapidKeys())'
y define NEXT_PUBLIC_VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY y VAPID_SUBJECT (también en apps/ingest).
Los navegadores pausan la geolocalización con la pantalla bloqueada. Tras aceptar el consentimiento, la página del teléfono muestra una URL personal https://<web>/api/ingest/osmand/<token> para configurar cualquier app de rastreo compatible con el protocolo OsmAnd (p. ej. Traccar Client, gratuita y de código abierto), que sí envía en segundo plano con el aviso del sistema. La URL solo acepta datos mientras el consentimiento esté vigente.
En el diálogo de comandos: pestaña Predefinidos (comandos integrados del protocolo + los guardados por la empresa en command_templates) y pestaña Personalizado (texto libre con la sintaxis del fabricante, con opción de guardarlo como predefinido, para un protocolo o para todos). El bloqueo de motor exige el vehículo detenido.
consent_log. El token se guarda solo como hash SHA-256 y viaja en el fragmento # de la URL (no llega a registros de servidor).Limitación de la plataforma: los navegadores (en especial iOS) pausan la geolocalización cuando la página se cierra o el teléfono se bloquea. Para seguimiento continuo en segundo plano hace falta una app nativa.
Catálogo en packages/telemetry/src/commands.ts: solicitar posición, intervalo de reporte, bloqueo/desbloqueo de motor (solo con el vehículo detenido ≤ 5 km/h y posición de < 10 min), reinicio, mensaje y comando libre.
$POS: el servicio de ingesta envía $CMD,<id>,<tipo>,<k=v;…>* al equipo conectado (o al reconectar) y espera $CMDACK,<id>,OK|ERR[,msg]*.POST COMMANDS_WEBHOOK_URL con { id, imei, type, params } (Bearer COMMANDS_WEBHOOK_TOKEN).Web → Vercel (Root Directory apps/web, framework Next.js).
Base de datos en Vercel (Neon, plan gratuito): Storage → Create Database → Neon y conéctala al proyecto. En cada despliegue el build ejecuta db:deploy: aplica las migraciones con la URL directa (DATABASE_URL_UNPOOLED, también con prefijo, p. ej. octopus_DATABASE_URL_UNPOOLED) y, si la base está vacía, crea la empresa y el propietario con BOOTSTRAP_ADMIN_EMAIL / BOOTSTRAP_ADMIN_PASSWORD (contraseña temporal, se obliga a cambiarla). El mantenimiento diario (particiones y retención) lo hace Vercel Cron en /api/cron/maintenance (requiere CRON_SECRET).
Variables:
| Variable | Requerida | Descripción |
|---|---|---|
DATABASE_URL | sí | PostgreSQL con PostGIS. Se aceptan también octopus_DATABASE_URL / POSTGRES_URL (integración Neon de Vercel). |
BOOTSTRAP_ADMIN_EMAIL / BOOTSTRAP_ADMIN_PASSWORD | primer despliegue | Propietario inicial si la base está vacía. |
CRON_SECRET | sí con Vercel Cron | Protege /api/cron/maintenance. |
NEXT_PUBLIC_INGEST_HOST / NEXT_PUBLIC_INGEST_TCP_PORT | no | Dirección del servicio TCP mostrada en Protocolos. |
AUTH_SECRET | sí | Secreto de sesión (≥ 32 caracteres aleatorios). |
INGEST_TOKEN | para ingesta | Token de /api/ingest/gateway y /api/ingest/osmand. |
COMMANDS_WEBHOOK_URL / COMMANDS_WEBHOOK_TOKEN | no | Destino de comandos para equipos tipo gateway. |
NEXT_PUBLIC_LEGAL_* | sí, antes de operar | Razón social, domicilio, correo de privacidad, país y jurisdicción mostrados en /legal/*. |
REDIS_URL | para tiempo real | Redis accesible por TCP (Upstash rediss://…, etc.). |
REALTIME_JWT_SECRET | para tiempo real | Compartido con apps/realtime. |
NEXT_PUBLIC_REALTIME_URL | para tiempo real | wss:// del gateway. Sin ella la UI usa polling cada 10 s. |
ALLOW_SIGNUP | no | false (recomendado): solo el administrador crea usuarios. |
NEXT_PUBLIC_MAP_STYLE_URL | no | Estilo MapLibre propio. Por defecto OpenFreeMap (gratuito, uso comercial permitido). |
Migraciones: DATABASE_URL=... pnpm db:migrate (desde tu máquina o CI, con un rol con permisos DDL). 0003_retention.sql programa el borrado diario de ubicaciones con más de 180 días.
Ingesta TCP y gateway WebSocket necesitan procesos persistentes (Vercel no admite sockets TCP ni WebSockets de larga duración). Hay Dockerfile en apps/ingest y apps/realtime para Fly.io, Railway, Render o cualquier VPS:
docker build -f apps/ingest/Dockerfile -t octopus-ingest .
docker build -f apps/realtime/Dockerfile -t octopus-realtime .
apps/realtime acepta REALTIME_ALLOWED_ORIGINS (lista separada por comas) para restringir el Origin de los navegadores.
/legal/licencias./legal/privacidad, /legal/terminos y /legal/cookies redactadas como plantilla (LFPDPPP de México / principios del RGPD). Deben revisarlas un abogado de tu jurisdicción y completarse con los datos NEXT_PUBLIC_LEGAL_*.