475 lines
20 KiB
Markdown
475 lines
20 KiB
Markdown
# Codex Handoff - QRIS Soundbox Platform
|
|
|
|
Tanggal update: 2026-06-08, Asia/Jakarta.
|
|
|
|
Dokumen ini adalah snapshot kerja terakhir untuk melanjutkan project tanpa perlu membaca ulang seluruh chat.
|
|
|
|
## Update Terbaru - 2026-06-08
|
|
|
|
- `soundbox-backend-mqtt-spec.md` sekarang mendokumentasikan device command QF100 category `5` untuk `reboot` dan `poweroff`.
|
|
- Backend sudah sinkron dengan spec command tersebut:
|
|
- `POST /admin/devices/{id}/commands` menerima `device.poweroff`;
|
|
- publisher MQTT membuat payload QF100 category `5` dengan `data.command = "poweroff"`;
|
|
- downlink tercatat sebagai `poweroff_command` di `mqtt_messages`.
|
|
- `scripts/smoke-qf100-adapter.mjs` sudah menambahkan assertion untuk command `device.poweroff`.
|
|
- Dashboard `/ui/soundbox-ops` dirapikan untuk operator:
|
|
- KPI warning sekarang menunjukkan breakdown stale vs degraded;
|
|
- KPI card bisa dipakai sebagai quick filter;
|
|
- tabel Fleet Status menampilkan health bar, reason, signal, dan battery;
|
|
- kolom utama Fleet Status sekarang memakai Serial Number sebagai identitas utama, dengan device code hanya sebagai detail sekunder;
|
|
- Remote Actions menambahkan tombol `Power Off Device`;
|
|
- layout mobile header/filter dibuat full-width agar tidak overflow.
|
|
- Registry `/ui/device-registry-monitoring` sekarang mendukung koreksi device metadata:
|
|
- tabel dan detail mengutamakan Serial Number, bukan internal device id;
|
|
- menu row punya `Edit Device`;
|
|
- menu row baris bawah otomatis membuka ke atas agar tidak tertutup pagination;
|
|
- modal edit bisa koreksi `serial_number/dev-sn`, vendor, model, communication mode, status, dan firmware version;
|
|
- perubahan model ikut memperbarui `capability_profile_json` dari katalog model aktif;
|
|
- backend menolak duplicate `serial_number` supaya config pull/MQTT lookup tidak ambigu.
|
|
- Device Technical Detail mengutamakan Serial Number di breadcrumb/title, menaruh device code sebagai detail, dan remote action menambahkan `Power Off Device`.
|
|
- Search UI yang sebelumnya dekoratif sudah mulai difungsikan:
|
|
- Admin Dashboard global search route ke Device Registry, Merchant List, atau Transaction History dengan `?q=`;
|
|
- Transaction History dan Merchant List membaca `?q=` sebagai initial search;
|
|
- Admin Reconciliation top search route ke Transaction History;
|
|
- Settlement Batch search live-filter batch table;
|
|
- Merchant Settlement History search live-filter disbursement table dan membaca `?q=`;
|
|
- Merchant Dashboard search route ke Merchant Settlement History;
|
|
- Fee Pricing search route ke Audit Logs, dan Audit Logs membaca `?q=`;
|
|
- Merchant Detail search route ke Merchant List;
|
|
- Device QR Payment Display search live-filter transaction rows.
|
|
- Verifikasi lokal update ini:
|
|
- `npm run typecheck`: pass;
|
|
- `node --check scripts/smoke-qf100-adapter.mjs`: pass.
|
|
- `node scripts/ui-qa-check.mjs`: pass;
|
|
- direct script parse `ui/device-registry-monitoring/index.html`: pass;
|
|
- headless Chrome screenshot desktop/mobile `/ui/soundbox-ops/?preview=1`: pass visual sanity.
|
|
|
|
## Update Terbaru - 2026-06-07
|
|
|
|
- Production saat ini fokus ke portal Soundbox Ops di `sms.bizone.id`, dengan MQTT broker `broker.bizone.id`.
|
|
- Commit terakhir yang sudah dipush sebelum update handoff ini:
|
|
- `1e0f36f Split MQTT trace and commands pages`
|
|
- `ef23b09 Parse QF100 heartbeat time as WIB`
|
|
- `e3d7e60 Complete QF100 ops commands and detail UI`
|
|
- Perubahan UI/ops terbaru:
|
|
- menu `MQTT Trace` sekarang halaman sendiri: `/ui/mqtt-trace`;
|
|
- menu `Config & Commands` sekarang halaman sendiri: `/ui/config-commands`;
|
|
- sidebar tidak lagi lompat ke anchor dashboard untuk dua menu tersebut;
|
|
- dashboard tetap ada summary ringkas, tetapi menu operasional utama pindah ke screen masing-masing.
|
|
- Halaman `/ui/mqtt-trace`:
|
|
- menampilkan trail uplink/downlink ala audit trail;
|
|
- filter direction `uplink/downlink`;
|
|
- filter message type;
|
|
- search topic/device/type/payload;
|
|
- limit 100/250/500;
|
|
- auto refresh 10 detik;
|
|
- klik event untuk lihat full payload JSON.
|
|
- Endpoint `/admin/mqtt/status` sekarang mendukung:
|
|
- `limit` sampai 500;
|
|
- `direction`;
|
|
- `message_type`;
|
|
- `device_id`.
|
|
- Halaman `/ui/config-commands`:
|
|
- menampilkan status database, pending/failed notification, export worker;
|
|
- menampilkan MQTT publisher/subscriber runtime;
|
|
- dropdown device dengan SN, model, connection, last seen;
|
|
- tombol `Reboot Device`;
|
|
- tombol `Open Device Detail`.
|
|
- Fix dashboard terbaru:
|
|
- kolom `Last Seen` di `/ui/soundbox-ops` tidak lagi menampilkan `[object Object]`;
|
|
- formatter sekarang membaca `latest_heartbeat.received_at`, `latest_heartbeat.timestamp`, lalu fallback `last_seen_at`.
|
|
- QF100 firmware categories yang sudah disiapkan:
|
|
- category `1`: payment sound, payload `data.pay-amount`;
|
|
- category `3`: heartbeat dari device;
|
|
- category `4`: dynamic QR display, payload `data.qr-url`, `data.amount`, `data.expire-seconds`;
|
|
- category `5`: reboot command, payload `data.command = "reboot"`.
|
|
- Dynamic QR:
|
|
- modal preview di Device Technical Detail sudah generate QR dari `data["qr-url"]`;
|
|
- tombol `Send Test QR` mengirim command `dynamic_qr.display`;
|
|
- backend menerima payload nested `header/data` dan publish category `4` ke `soundbox/{serial_number}/down`.
|
|
- Reboot:
|
|
- command `device.reboot` publish category `5` ke `soundbox/{serial_number}/down`;
|
|
- bisa dikirim dari Device Technical Detail, Device Registry drawer, dan `/ui/config-commands`.
|
|
- Heartbeat:
|
|
- QF100 mengirim `data.time` sebagai WIB/UTC+7;
|
|
- backend sekarang parse waktu itu sebagai WIB lalu simpan UTC;
|
|
- contoh `20260607023400` disimpan menjadi `2026-06-06T19:34:00.000Z`.
|
|
- Device Registry dan Device Detail:
|
|
- SN ditampilkan di tabel Device Registry;
|
|
- SN ditampilkan di drawer Device Detail;
|
|
- SN ditampilkan di header Device Technical Detail.
|
|
- Verifikasi lokal terakhir:
|
|
- `npm run typecheck`: pass;
|
|
- `node scripts/ui-qa-check.mjs`: pass;
|
|
- `node --check scripts/smoke-qf100-adapter.mjs`: pass pada patch QF100 sebelumnya;
|
|
- `git diff --check`: pass.
|
|
|
|
## Update Terbaru - 2026-06-06
|
|
|
|
- Fokus produk sekarang: `sms.bizone.id` menjadi portal utama Soundbox Ops / Monitoring, bukan katalog UI atau dashboard admin campuran.
|
|
- Default route sudah disesuaikan:
|
|
- `GET /` redirect ke `/ui/soundbox-ops`;
|
|
- `GET /ui` redirect ke `/ui/soundbox-ops`;
|
|
- halaman Soundbox Ops tetap berada di `/ui/soundbox-ops`.
|
|
- Server target deploy diganti menjadi Debian 13, memakai user khusus `qrisapp`.
|
|
- Dokumen deploy:
|
|
- `DEBIAN12_APP_SERVER_SETUP.md` diganti menjadi `DEBIAN13_APP_SERVER_SETUP.md`;
|
|
- README sudah menunjuk ke dokumen Debian 13;
|
|
- install dari server kosong mencakup package dasar, Node.js 22, PostgreSQL, Nginx, Certbot, UFW, env production, migration, systemd, TLS, dan verification;
|
|
- semua proses app/repo/build/migration/service dijalankan sebagai `qrisapp`;
|
|
- root/sudo hanya untuk install package, direktori, env, Nginx, systemd.
|
|
- Env deploy sekarang mencantumkan `DATABASE_URL` selain `PGHOST/PGPORT/PGUSER/PGPASSWORD/PGDATABASE`, supaya `npm run deploy:check-env` tidak gagal dengan error `DATABASE_URL is required`.
|
|
- Endpoint config device sudah men-support:
|
|
- `GET /speaker/dev-config`;
|
|
- `POST /speaker/dev-config`;
|
|
- lookup device berdasarkan `dev-sn` ke `devices.serial_number`;
|
|
- device tidak dikunci model tertentu, sehingga tipe device asli bisa diinput lewat master data/model dan matching tetap berdasarkan SN.
|
|
- Response config device tetap vendor-compatible:
|
|
- `error-code`;
|
|
- `mqtt.broker-ip`;
|
|
- `mqtt.broker-port`;
|
|
- `mqtt.client-id`;
|
|
- `mqtt.user-name`;
|
|
- `mqtt.password`;
|
|
- `mqtt.subscribe-topic`;
|
|
- `mqtt.keep-alive`.
|
|
- Production target:
|
|
- HTTP config URL device: `https://sms.bizone.id/speaker/dev-config`;
|
|
- MQTT broker: `broker.bizone.id`;
|
|
- MQTT TLS default: `mqtts://broker.bizone.id:8883`;
|
|
- jika firmware belum support TLS, siapkan listener non-TLS terbatas atau patch firmware.
|
|
- Dashboard Soundbox Ops sudah dirapikan untuk fokus operasional:
|
|
- sidebar hanya menu ops: Monitoring, Registry, MQTT Trace, Config & Commands, Catalog;
|
|
- menu Register Device dihapus dari sidebar, action register ada di Device Registry;
|
|
- Technical Detail dihapus dari sidebar, akses detail lewat row action di Device Registry;
|
|
- footer/dev nav UI katalog dihapus dari halaman ops yang relevan.
|
|
- Master data `Catalog` sudah ditambahkan:
|
|
- vendor create/edit/delete;
|
|
- model create/edit/delete;
|
|
- model code generated backend;
|
|
- model thumbnail upload;
|
|
- country dropdown searchable dengan Palestine/Palestina masuk list;
|
|
- structured vendor contact: PIC name, phone/WhatsApp, email, notes.
|
|
- Device Registry sudah dibuat live dari API, bukan dummy:
|
|
- KPI dari data device;
|
|
- search berfungsi;
|
|
- pagination nyata;
|
|
- filter reset page;
|
|
- row action 3-dot untuk View Device Detail / Quick Inspect.
|
|
- Device Detail sudah dibuat lebih operasional:
|
|
- tombol refresh, retry push, test QR, copy payload, clear console, reboot, firmware update, unbind, rotate MQTT credential, decommission punya action;
|
|
- Dynamic QR preview dibuka sebagai modal inline, bukan pindah ke dashboard lain.
|
|
- Verifikasi terakhir lokal:
|
|
- `npm run typecheck`: pass.
|
|
|
|
## Status Terakhir
|
|
|
|
- Fokus sebelumnya bergeser dari production readiness umum ke integrasi device soundbox QF100.
|
|
- Folder SDK lokal `QF100-60s-l511-SecondApp-260107/` ditemukan dan dianalisis. Folder ini sengaja tidak dimasukkan git.
|
|
- Backend sekarang sudah punya adapter awal untuk firmware QF100 sample:
|
|
- config server vendor-compatible;
|
|
- payload MQTT payment success format QF100;
|
|
- smoke script backend untuk static + dynamic QF100.
|
|
- Target milestone berikutnya: dua soundbox real, satu static dan satu dynamic, bisa ambil config dari backend, connect MQTT, lalu static payment test bunyi dan tercatat di dashboard.
|
|
- Worktree aktif/dirty karena perubahan backend QF100 dan update handoff. Jangan revert perubahan yang tidak eksplisit diminta.
|
|
|
|
## Verifikasi Terakhir
|
|
|
|
- `npm run typecheck`: pass setelah perubahan QF100.
|
|
- `npm install`: sudah dijalankan untuk memasang dependency lokal; perubahan lockfile accidental sudah dibalik.
|
|
- `npm run smoke:qf100`: script sudah dibuat, belum dijalankan end-to-end di DB/server lokal pada turn ini.
|
|
- Verifikasi lama yang masih relevan:
|
|
- `npm run db:migrate`: sebelumnya pass dan idempotent sampai migration `003_export_job_storage.sql`.
|
|
- `npm audit --json`: sebelumnya pass, 0 vulnerability.
|
|
- `npm run ui:qa`: sebelumnya pass.
|
|
- `npm run smoke:e2e`: sebelumnya pass.
|
|
- Real MQTT smoke sebelumnya pernah pass terhadap `mqtts://broker.bizone.id:8883`.
|
|
|
|
## SDK QF100 Yang Ditemukan
|
|
|
|
- Folder lokal: `QF100-60s-l511-SecondApp-260107/`.
|
|
- Sudah ditambahkan ke `.gitignore`:
|
|
- `QF100-60s-l511-SecondApp-260107/`
|
|
- Struktur penting:
|
|
- `docs/Config Server.docx`: kontrak config server vendor.
|
|
- `docs/Cloud Speaker API Spec V2.8.7.pdf`: API spec cloud speaker.
|
|
- `app/source/MainApp/globalDefine.h`: device model, demo mode, `CONFIG_ADDR`.
|
|
- `app/source/MainApp/demo.c`: alur config server, MQTT connect/subscribe, parse payment payload.
|
|
- `app/source/MainApp/demo.h`: MQTT TLS/QoS/clean session/cert config.
|
|
- `app/source/MainApp/main.c`: boot flow dan monitor network/MQTT.
|
|
- `app/inc/MercuryMqtt.h`: header MQTT SDK.
|
|
- `app/release/user_app.bin`: firmware build existing.
|
|
|
|
## Kesimpulan SDK QF100
|
|
|
|
- SDK ini memungkinkan develop/patch aplikasi firmware sendiri, tetapi bentuknya embedded C firmware app, bukan SDK backend.
|
|
- Strategi dipilih: firmware hanya hardcode URL config server backend kita, bukan hardcode broker MQTT.
|
|
- Firmware sample boot lalu call `CONFIG_ADDR` ke endpoint vendor `/speaker/dev-config`.
|
|
- Request config berisi field seperti:
|
|
- `dev-model`
|
|
- `item-number`
|
|
- `dev-sn`
|
|
- `fw-version`
|
|
- `fw-build`
|
|
- `app-config-version`
|
|
- `imei`
|
|
- `imsi`
|
|
- `iccid`
|
|
- Response yang firmware cari memiliki blok:
|
|
- `mqtt.broker-ip`
|
|
- `mqtt.broker-port`
|
|
- `mqtt.client-id`
|
|
- `mqtt.user-name`
|
|
- `mqtt.password`
|
|
- `mqtt.subscribe-topic`
|
|
- `mqtt.keep-alive`
|
|
- Payment success payload yang firmware sample bisa bunyikan:
|
|
```json
|
|
{
|
|
"header": {
|
|
"category": 1
|
|
},
|
|
"data": {
|
|
"pay-amount": 15000
|
|
}
|
|
}
|
|
```
|
|
- `MQTT_TLS_ENABLE` di SDK sample masih `0`. Jika broker production memakai `mqtts://...:8883`, firmware perlu patch TLS atau pilot perlu listener non-TLS terbatas.
|
|
|
|
## Implementasi QF100 Backend Hari Ini
|
|
|
|
### 1. Config Server Vendor-Compatible
|
|
|
|
- Route baru:
|
|
- `GET /speaker/dev-config`
|
|
- File:
|
|
- `src/routes/speaker.ts`
|
|
- mounted di `src/app.ts`
|
|
- Perilaku:
|
|
- menerima query/body vendor;
|
|
- lookup device memakai `dev-sn` -> `devices.serial_number`;
|
|
- jika device aktif, update:
|
|
- `vendor`
|
|
- `model`
|
|
- `communication_mode`
|
|
- `last_seen_at`
|
|
- `firmware_version`
|
|
- mencatat heartbeat `state: config_pull`;
|
|
- balas JSON vendor top-level, bukan wrapper internal `successResponse`.
|
|
- Error vendor style:
|
|
- `1001`: `dev-sn` kosong;
|
|
- `1002`: device tidak terdaftar atau inactive;
|
|
- `1003`: broker MQTT belum dikonfigurasi.
|
|
|
|
### 2. Env QF100
|
|
|
|
- Env baru di `src/config/env.ts` dan `.env.example`:
|
|
- `QF100_MQTT_BROKER_HOST`
|
|
- `QF100_MQTT_BROKER_PORT`
|
|
- `QF100_MQTT_USERNAME`
|
|
- `QF100_MQTT_PASSWORD`
|
|
- `QF100_MQTT_KEEP_ALIVE_SECONDS`
|
|
- Jika host/port QF100 kosong, endpoint mencoba parse dari `MQTT_BROKER_URL`.
|
|
- Catatan penting: password MQTT yang dikirim ke QF100 diambil dari `QF100_MQTT_PASSWORD` atau fallback `MQTT_PASSWORD`. Sistem saat ini menyimpan credential device sebagai fingerprint, jadi plaintext per-device tidak bisa dibaca ulang dari DB.
|
|
|
|
### 3. Payload MQTT QF100
|
|
|
|
- File:
|
|
- `src/shared/services/mqttPublisher.ts`
|
|
- `src/shared/orchestrators/notificationOrchestrator.ts`
|
|
- Topic QF100:
|
|
- `soundbox/{dev-sn}/down`
|
|
- Adapter memilih format QF100 jika:
|
|
- `device.model` mengandung `QF100`; atau
|
|
- `capability_profile_json.mqtt_payload_profile`, `protocol_profile`, atau `vendor_protocol` bernilai `qf100`.
|
|
- Downlink payment sekarang juga dicatat ke `mqtt_messages`, sehingga dashboard device detail bisa melihat topic/payload yang dikirim.
|
|
|
|
### 4. Device Store dan Schema
|
|
|
|
- Lookup baru:
|
|
- `getDeviceBySerialNumber(serialNumber)` di `src/shared/store/deviceStore.ts`.
|
|
- Schema bootstrap menambahkan index:
|
|
- `idx_devices_serial_number`.
|
|
|
|
### 5. Smoke QF100
|
|
|
|
- Script baru:
|
|
- `scripts/smoke-qf100-adapter.mjs`
|
|
- Package script baru:
|
|
- `npm run smoke:qf100`
|
|
- Script ini:
|
|
- create merchant/outlet/terminal/device static;
|
|
- create merchant/outlet/terminal/device dynamic MQTT;
|
|
- set `model: QF100` dan `capability_profile_json.mqtt_payload_profile: qf100`;
|
|
- hit `/speaker/dev-config` untuk dua SN;
|
|
- validasi MQTT config vendor;
|
|
- trigger static QRIS paid callback;
|
|
- validasi `mqtt_messages` downlink QF100 payload `category: 1`;
|
|
- trigger backend dynamic QR MQTT flow untuk device dynamic.
|
|
- Untuk memakai SN real:
|
|
```bash
|
|
QF100_STATIC_SN=<sn-static> \
|
|
QF100_DYNAMIC_SN=<sn-dynamic> \
|
|
BASE_URL=http://127.0.0.1:3000 \
|
|
npm run smoke:qf100
|
|
```
|
|
|
|
## Device Flow Yang Disepakati
|
|
|
|
### Static Soundbox
|
|
|
|
1. Device boot.
|
|
2. Firmware call backend `/speaker/dev-config`.
|
|
3. Backend balas MQTT config.
|
|
4. Device connect MQTT dan subscribe `soundbox/{dev-sn}/down`.
|
|
5. QRIS callback paid masuk backend.
|
|
6. Backend publish payload QF100 `category: 1`.
|
|
7. Device bunyi nominal.
|
|
8. Dashboard melihat transaction, notification, mqtt message, last seen/config pull.
|
|
|
|
### Dynamic Soundbox
|
|
|
|
- Prinsip: trigger tetap via MQTT, bukan polling terus-menerus.
|
|
- HTTP polling dynamic QR dianggap tidak cocok untuk skala 20 ribu device karena `gap=30s` berarti sekitar 40 ribu request/menit.
|
|
- Desain lanjutan:
|
|
1. Backend/admin/merchant membuat dynamic QR request.
|
|
2. Backend publish MQTT command ke device.
|
|
3. Device menampilkan QR langsung atau HTTP fetch QR detail dari URL.
|
|
4. Payment callback tetap jadi source of truth.
|
|
5. Payment success tetap via MQTT `category: 1`.
|
|
- Firmware dynamic handler belum dipatch. Perlu tambah handler misalnya `category == 10` di `demo.c`.
|
|
|
|
## Dashboard Yang Perlu Disiapkan Berikutnya
|
|
|
|
Prioritas UI/dashboard untuk test dua soundbox real:
|
|
|
|
1. Device detail QF100 panel:
|
|
- SN;
|
|
- model/profile;
|
|
- config pull terakhir;
|
|
- broker host/port yang dikirim;
|
|
- client-id;
|
|
- subscribe-topic;
|
|
- keepalive.
|
|
2. Test payment button:
|
|
- nominal quick actions, misalnya Rp1.000 dan Rp15.000;
|
|
- create dummy tx/callback internal;
|
|
- tampilkan notification dan MQTT payload result.
|
|
3. MQTT timeline:
|
|
- direction;
|
|
- topic;
|
|
- message_type;
|
|
- payload JSON;
|
|
- publish_status/reason;
|
|
- timestamp.
|
|
4. Dynamic QR panel:
|
|
- input nominal;
|
|
- create dynamic QR;
|
|
- tampilkan QR payload/status;
|
|
- nanti `Send to Soundbox` via MQTT command setelah firmware handler siap.
|
|
5. Ops summary:
|
|
- total soundbox;
|
|
- online/stale/offline;
|
|
- config pull terbaru;
|
|
- payment notification sent/failed;
|
|
- dynamic QR active/paid/expired.
|
|
|
|
## Endpoint Penting Saat Ini
|
|
|
|
- Health:
|
|
- `GET /health`
|
|
- `GET /health/deep`
|
|
- QF100 vendor config:
|
|
- `GET /speaker/dev-config`
|
|
- Admin auth/session:
|
|
- `POST /admin/login`
|
|
- `POST /admin/logout`
|
|
- `GET /admin/me`
|
|
- Admin device:
|
|
- `POST /admin/devices`
|
|
- `GET /admin/devices`
|
|
- `GET /admin/devices/{id}`
|
|
- `POST /admin/devices/{id}/credentials/rotate`
|
|
- `POST /admin/devices/{id}/bind`
|
|
- `POST /admin/devices/{id}/unbind`
|
|
- `GET /admin/devices/{id}/mqtt-messages`
|
|
- `GET /admin/devices/{id}/notifications`
|
|
- Device API:
|
|
- `POST /device/heartbeat`
|
|
- `POST /device/transactions/dynamic-qr`
|
|
- `POST /device/mqtt/uplink/dynamic-qr/request`
|
|
- `GET /device/config`
|
|
- `POST /device/config/ack`
|
|
- Integrations:
|
|
- `POST /integrations/qris/callback`
|
|
- Observability:
|
|
- `GET /admin/observability/summary`
|
|
- `GET /admin/observability/mqtt-status`
|
|
|
|
## Package Scripts Penting
|
|
|
|
- `npm run typecheck`
|
|
- `npm run db:migrate`
|
|
- `npm run smoke:qf100`
|
|
- `npm run smoke:e2e`
|
|
- `npm run smoke:mqtt-real`
|
|
- `npm run smoke:mqtt-acl`
|
|
- `npm run ui:qa`
|
|
- `npm run deploy:check-env`
|
|
- `npm run load:test`
|
|
- `npm run load:test:staging`
|
|
- `npm run mqtt:provision-device`
|
|
- `npm run mqtt:check-acl`
|
|
- `npm run admin:create-user`
|
|
- `npm run merchant:create-user`
|
|
|
|
## File Kunci Yang Sering Disentuh
|
|
|
|
- App bootstrap: `src/app.ts`
|
|
- Env config: `src/config/env.ts`
|
|
- QF100 config route: `src/routes/speaker.ts`
|
|
- Device route: `src/routes/device.ts`
|
|
- Admin route: `src/routes/admin.ts`
|
|
- MQTT publisher: `src/shared/services/mqttPublisher.ts`
|
|
- MQTT subscriber: `src/shared/services/mqttSubscriber.ts`
|
|
- Notification orchestrator: `src/shared/orchestrators/notificationOrchestrator.ts`
|
|
- Device store: `src/shared/store/deviceStore.ts`
|
|
- MQTT message store: `src/shared/store/mqttMessageStore.ts`
|
|
- Heartbeat store: `src/shared/store/heartbeatStore.ts`
|
|
- Schema bootstrap: `src/shared/db/pool.ts`
|
|
- QF100 smoke: `scripts/smoke-qf100-adapter.mjs`
|
|
- Env sample: `.env.example`
|
|
|
|
## Sisa Gap Utama
|
|
|
|
1. Jalankan `npm run smoke:qf100` terhadap backend + DB lokal/staging.
|
|
2. Register dua device real:
|
|
- static SN -> device static;
|
|
- dynamic SN -> device dynamic.
|
|
3. Patch firmware QF100:
|
|
- `CONFIG_ADDR` ke backend kita;
|
|
- TLS setting sesuai broker.
|
|
4. Test static device real:
|
|
- config pull;
|
|
- MQTT connect;
|
|
- payment success bunyi;
|
|
- dashboard melihat downlink.
|
|
5. Patch firmware dynamic:
|
|
- tambah handler command dynamic QR, kemungkinan `category == 10`;
|
|
- pilih direct QR payload vs HTTP fetch detail.
|
|
6. Siapkan dashboard QF100 detail/test panel.
|
|
7. Putuskan credential strategy production:
|
|
- shared pilot password saat ini cukup untuk lab;
|
|
- production sebaiknya credential per-device yang bisa diprovisioning aman.
|
|
8. Tetap perlu staging rehearsal, restore drill, export storage strategy, dan manual visual QA dari handoff lama.
|
|
|
|
## Catatan Penting
|
|
|
|
- Folder SDK QF100 adalah artefak lokal dan jangan dimasukkan git.
|
|
- Jangan hardcode broker credential production di firmware.
|
|
- Firmware cukup hardcode config server URL; broker/topic/credential dikirim dari backend.
|
|
- Jangan gunakan wildcard MQTT subscribe di production kecuali maintenance terkontrol.
|
|
- Jika memakai MQTT TLS (`mqtts://...:8883`), firmware QF100 perlu `MQTT_TLS_ENABLE=1` dan sertifikat yang sesuai.
|
|
- Rate limiting aktif default; `/speaker` memakai limiter device.
|
|
- `CODEX_HANDOFF.md` ini adalah snapshot operasional terbaru; untuk detail historis keputusan, baca `DECISIONS_LOG.md`.
|