718 lines
37 KiB
Markdown
718 lines
37 KiB
Markdown
# 📊 Diagram Alur Kerja Printer Niimbot
|
||
|
||
## 🔄 Alur Lengkap: Dari UI ke Printer
|
||
|
||
```mermaid
|
||
graph TD
|
||
A[User buka halaman Brankas] --> B{Printer sudah<br/>terhubung?}
|
||
B -->|Tidak| C[Klik 'Hubungkan Printer']
|
||
B -->|Ya| D[Status: Terhubung]
|
||
|
||
C --> E[Modal NiimbotConnector muncul]
|
||
E --> F{Pilih metode koneksi}
|
||
F -->|Bluetooth| G[Klik 'Hubungkan Printer']
|
||
F -->|USB/Serial| G
|
||
|
||
G --> H[Browser: Dialog pairing muncul]
|
||
H --> I[User pilih Niimbot device]
|
||
I --> J[Library: initClient & connect]
|
||
|
||
J --> K{Koneksi<br/>berhasil?}
|
||
K -->|Tidak| L[Tampilkan error]
|
||
K -->|Ya| M[Fetch printer info]
|
||
|
||
M --> N[Status: Terhubung ✓]
|
||
N --> D
|
||
|
||
D --> O[User klik item di Brankas]
|
||
O --> P[Modal item muncul]
|
||
P --> Q[Generate QR Code URL]
|
||
Q --> R[Tampilkan preview QR]
|
||
|
||
R --> S[User klik 'Cetak ke Niimbot']
|
||
S --> T{Printer<br/>terhubung?}
|
||
|
||
T -->|Tidak| U[Alert: Hubungkan printer]
|
||
U --> C
|
||
|
||
T -->|Ya| V[createQRLabelCanvas]
|
||
V --> W[Load QR image]
|
||
W --> X[Draw ke canvas:<br/>QR + Kode + Nama + Berat]
|
||
X --> Y[Convert canvas to DataURL]
|
||
|
||
Y --> Z[printQRCode composable]
|
||
Z --> AA[Stop heartbeat]
|
||
AA --> AB[Create PrintTask]
|
||
AB --> AC[ImageEncoder.encodeCanvas]
|
||
AC --> AD[printTask.printInit]
|
||
AD --> AE[printTask.printPage]
|
||
|
||
AE --> AF{Print<br/>sukses?}
|
||
AF -->|Tidak| AG[Tampilkan error]
|
||
AF -->|Ya| AH[printTask.printEnd]
|
||
|
||
AH --> AI[Start heartbeat]
|
||
AI --> AJ[Alert: Berhasil dicetak!]
|
||
AJ --> AK[Printer cetak label]
|
||
```
|
||
|
||
---
|
||
|
||
## 🏗️ Arsitektur Komponen
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ BrankasList.vue │
|
||
│ ┌────────────────────────────────────────────────────────┐ │
|
||
│ │ UI Layer │ │
|
||
│ │ - Tombol "Hubungkan Printer" │ │
|
||
│ │ - Tombol "Cetak ke Niimbot" │ │
|
||
│ │ - Modal item dengan QR Code │ │
|
||
│ └────────────────────────────────────────────────────────┘ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ ┌────────────────────────────────────────────────────────┐ │
|
||
│ │ Logic Layer │ │
|
||
│ │ - printQR() → Trigger print │ │
|
||
│ │ - createQRLabelCanvas() → Generate canvas dengan QR │ │
|
||
│ │ - handlePrinterConnected() → Event handler │ │
|
||
│ └────────────────────────────────────────────────────────┘ │
|
||
└───────────────────────┬─────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ useNiimbotPrinter.js (Composable) │
|
||
│ ┌────────────────────────────────────────────────────────┐ │
|
||
│ │ State Management │ │
|
||
│ │ - printerClient (reactive) │ │
|
||
│ │ - connectionState │ │
|
||
│ │ - isPrinting, printProgress │ │
|
||
│ └────────────────────────────────────────────────────────┘ │
|
||
│ ┌────────────────────────────────────────────────────────┐ │
|
||
│ │ Methods │ │
|
||
│ │ - initClient() → Buat NiimbotClient │ │
|
||
│ │ - connect() → Hubungkan ke printer │ │
|
||
│ │ - disconnect() → Putuskan koneksi │ │
|
||
│ │ - printQRCode() → Print image ke printer │ │
|
||
│ └────────────────────────────────────────────────────────┘ │
|
||
└───────────────────────┬─────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ @mmote/niimbluelib (Library) │
|
||
│ ┌────────────────────────────────────────────────────────┐ │
|
||
│ │ NiimbotBluetoothClient / NiimbotSerialClient │ │
|
||
│ │ - connect() → Web Bluetooth/Serial API │ │
|
||
│ │ - fetchPrinterInfo() → Get printer metadata │ │
|
||
│ │ - startHeartbeat() → Maintain connection │ │
|
||
│ └────────────────────────────────────────────────────────┘ │
|
||
│ ┌────────────────────────────────────────────────────────┐ │
|
||
│ │ PrintTask │ │
|
||
│ │ - newPrintTask() → Buat task print │ │
|
||
│ │ - printInit() → Inisialisasi print │ │
|
||
│ │ - printPage() → Kirim data gambar │ │
|
||
│ │ - waitForFinished() → Tunggu selesai │ │
|
||
│ │ - printEnd() → Akhiri print │ │
|
||
│ └────────────────────────────────────────────────────────┘ │
|
||
│ ┌────────────────────────────────────────────────────────┐ │
|
||
│ │ ImageEncoder │ │
|
||
│ │ - encodeCanvas() → Encode canvas ke binary │ │
|
||
│ └────────────────────────────────────────────────────────┘ │
|
||
└───────────────────────┬─────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ Browser Web APIs │
|
||
│ - Web Bluetooth API (navigator.bluetooth) │
|
||
│ - Web Serial API (navigator.serial) │
|
||
└───────────────────────┬─────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ Printer Niimbot (Hardware) │
|
||
│ - Terima perintah via BLE/USB │
|
||
│ - Decode binary image data │
|
||
│ - Print ke label thermal │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 📡 Sequence Diagram: Proses Print
|
||
|
||
```
|
||
User BrankasList useNiimbot niimbluelib Browser API Printer
|
||
│ │ │ │ │ │
|
||
│ Klik item │ │ │ │ │
|
||
├───────────────>│ │ │ │ │
|
||
│ │ │ │ │ │
|
||
│ Modal muncul │ │ │ │ │
|
||
│<───────────────┤ │ │ │ │
|
||
│ │ │ │ │ │
|
||
│ Klik 'Cetak' │ │ │ │ │
|
||
├───────────────>│ │ │ │ │
|
||
│ │ │ │ │ │
|
||
│ │ printQRCode()│ │ │ │
|
||
│ ├─────────────>│ │ │ │
|
||
│ │ │ │ │ │
|
||
│ │ │ stopHeartbeat() │ │
|
||
│ │ ├─────────────>│ │ │
|
||
│ │ │ │ │ │
|
||
│ │ │ newPrintTask() │ │
|
||
│ │ ├─────────────>│ │ │
|
||
│ │ │ │ │ │
|
||
│ │ │ encodeCanvas() │ │
|
||
│ │ ├─────────────>│ │ │
|
||
│ │ │ │ │ │
|
||
│ │ │ │ BLE/Serial │ │
|
||
│ │ │ │ Write Data │ │
|
||
│ │ │ ├─────────────>│ │
|
||
│ │ │ │ │ │
|
||
│ │ │ │ │ Send Data │
|
||
│ │ │ │ ├───────────>│
|
||
│ │ │ │ │ │
|
||
│ │ │ │ │ Printing │
|
||
│ │ │ │ │ ........ │
|
||
│ │ │ │ │ │
|
||
│ │ │ │ Status ACK │ │
|
||
│ │ │ │<─────────────┤ │
|
||
│ │ │ │ │ │
|
||
│ │ │ printEnd() │ │ │
|
||
│ │ ├─────────────>│ │ │
|
||
│ │ │ │ │ │
|
||
│ │ │ startHeartbeat() │ │
|
||
│ │ ├─────────────>│ │ │
|
||
│ │ │ │ │ │
|
||
│ │ Alert sukses │ │ │ │
|
||
│ │<─────────────┤ │ │ │
|
||
│ │ │ │ │ │
|
||
│ Label tercetak│ │ │ │ │
|
||
│<───────────────┴──────────────┴──────────────┴──────────────┴────────────┤
|
||
│ │
|
||
```
|
||
|
||
---
|
||
|
||
## 🔌 Connection Flow Detail
|
||
|
||
### Bluetooth Connection
|
||
```
|
||
1. User Action
|
||
└─> Klik "Hubungkan Printer"
|
||
|
||
2. initClient('bluetooth')
|
||
└─> new NiimbotBluetoothClient()
|
||
|
||
3. connect()
|
||
└─> navigator.bluetooth.requestDevice({
|
||
filters: [{ namePrefix: 'Niimbot' }],
|
||
optionalServices: [SERVICE_UUID]
|
||
})
|
||
|
||
4. Browser Dialog
|
||
└─> User pilih device "Niimbot-XXXX"
|
||
|
||
5. device.gatt.connect()
|
||
└─> Establish BLE connection
|
||
|
||
6. getPrimaryService(SERVICE_UUID)
|
||
└─> getCharacteristic(TX_CHAR, RX_CHAR)
|
||
|
||
7. Event: 'connect' triggered
|
||
└─> connectionState = 'connected'
|
||
|
||
8. fetchPrinterInfo()
|
||
└─> Send command: GET_INFO
|
||
└─> Receive: model, serial, firmware version
|
||
|
||
9. startHeartbeat()
|
||
└─> Kirim ping setiap 1 detik
|
||
└─> Cek printer masih hidup
|
||
```
|
||
|
||
### USB/Serial Connection
|
||
```
|
||
1. User Action
|
||
└─> Klik "Hubungkan Printer"
|
||
|
||
2. initClient('serial')
|
||
└─> new NiimbotSerialClient()
|
||
|
||
3. connect()
|
||
└─> navigator.serial.requestPort({
|
||
filters: [{ usbVendorId: 0xXXXX }]
|
||
})
|
||
|
||
4. Browser Dialog
|
||
└─> User pilih USB device
|
||
|
||
5. port.open({ baudRate: 9600 })
|
||
└─> Establish serial connection
|
||
|
||
6. Setup reader/writer streams
|
||
└─> readable.getReader()
|
||
└─> writable.getWriter()
|
||
|
||
7. Event: 'connect' triggered
|
||
└─> connectionState = 'connected'
|
||
|
||
8. fetchPrinterInfo() & startHeartbeat()
|
||
└─> (sama dengan Bluetooth)
|
||
```
|
||
|
||
---
|
||
|
||
## 🖼️ Image Processing Pipeline
|
||
|
||
```
|
||
QR Code URL (dari API)
|
||
│
|
||
▼
|
||
new Image()
|
||
│
|
||
▼
|
||
img.onload
|
||
│
|
||
▼
|
||
Create Canvas (384x384)
|
||
│
|
||
├─> Fill white background
|
||
│
|
||
├─> drawImage(qr, x, y, size, size)
|
||
│
|
||
├─> fillText(kode_item)
|
||
│
|
||
├─> fillText(nama_produk)
|
||
│
|
||
├─> fillText(berat)
|
||
│
|
||
▼
|
||
canvas.toDataURL('image/png')
|
||
│
|
||
▼
|
||
loadImageToCanvas(dataUrl)
|
||
│
|
||
▼
|
||
[Optional] applyThreshold(canvas, 140)
|
||
│
|
||
├─> getImageData()
|
||
│
|
||
├─> for each pixel:
|
||
│ avg = (r+g+b)/3
|
||
│ if avg < 140: black
|
||
│ else: white
|
||
│
|
||
├─> putImageData()
|
||
│
|
||
▼
|
||
ImageEncoder.encodeCanvas(canvas, 'top')
|
||
│
|
||
├─> Convert to 1-bit bitmap
|
||
│
|
||
├─> Rotate if needed (printDirection)
|
||
│
|
||
├─> Pack bits: 8 pixels = 1 byte
|
||
│
|
||
▼
|
||
Binary Data (EncodedImage)
|
||
│
|
||
▼
|
||
printTask.printPage(encoded, quantity)
|
||
│
|
||
▼
|
||
Send to Printer via BLE/Serial
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 State Machine Diagram
|
||
|
||
```
|
||
┌─────────────────┐
|
||
│ DISCONNECTED │◄────────┐
|
||
└────────┬────────┘ │
|
||
│ │
|
||
│ connect() │ disconnect()
|
||
│ │
|
||
▼ │
|
||
┌─────────────────┐ │
|
||
│ CONNECTING │ │
|
||
└────────┬────────┘ │
|
||
│ │
|
||
│ success │ error
|
||
│ │
|
||
▼ │
|
||
┌─────────────────┐ │
|
||
│ CONNECTED │─────────┤
|
||
└────────┬────────┘ │
|
||
│ │
|
||
│ printQRCode() │
|
||
│ │
|
||
▼ │
|
||
┌─────────────────┐ │
|
||
│ PRINTING │ │
|
||
│ [progress: X%] │ │
|
||
└────────┬────────┘ │
|
||
│ │
|
||
│ finished │
|
||
│ │
|
||
▼ │
|
||
┌─────────────────┐ │
|
||
│ CONNECTED │─────────┘
|
||
│ (heartbeat) │
|
||
└─────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 Data Flow: QR Code → Printed Label
|
||
|
||
```
|
||
┌────────────────────────────────────────────────────────────┐
|
||
│ 1. DATA SOURCE │
|
||
│ ─────────────────────────────────────────────────────────│
|
||
│ selectedItem = { │
|
||
│ kode_item: "BRN-001", │
|
||
│ produk: { │
|
||
│ nama: "Cincin Emas 24K", │
|
||
│ berat: 5.2 │
|
||
│ } │
|
||
│ } │
|
||
└────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌────────────────────────────────────────────────────────────┐
|
||
│ 2. QR CODE GENERATION (External API) │
|
||
│ ─────────────────────────────────────────────────────────│
|
||
│ URL: https://api.qrserver.com/v1/create-qr-code/ │
|
||
│ ?size=150x150&data=BRN-001 │
|
||
│ │
|
||
│ Returns: image/png (base64 or URL) │
|
||
└────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌────────────────────────────────────────────────────────────┐
|
||
│ 3. CANVAS CREATION │
|
||
│ ─────────────────────────────────────────────────────────│
|
||
│ createQRLabelCanvas(qrUrl, item) │
|
||
│ │
|
||
│ Canvas 384x384px: │
|
||
│ ┌──────────────────────┐ │
|
||
│ │ │ │
|
||
│ │ ┌──────────┐ │ ← QR Code (200x200) │
|
||
│ │ │ ▓▓ ▓▓▓▓│ │ │
|
||
│ │ │▓ ▓▓ ▓ │ │ │
|
||
│ │ │ ▓▓▓ ▓▓▓│ │ │
|
||
│ │ └──────────┘ │ │
|
||
│ │ │ │
|
||
│ │ BRN-001 │ ← Kode Item (bold 18px) │
|
||
│ │ Cincin Emas 24K │ ← Nama Produk (14px) │
|
||
│ │ 5.2g │ ← Berat (12px) │
|
||
│ │ │ │
|
||
│ └──────────────────────┘ │
|
||
└────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌────────────────────────────────────────────────────────────┐
|
||
│ 4. IMAGE ENCODING │
|
||
│ ─────────────────────────────────────────────────────────│
|
||
│ ImageEncoder.encodeCanvas(canvas, 'top') │
|
||
│ │
|
||
│ Process: │
|
||
│ - Convert RGB to grayscale │
|
||
│ - Apply threshold (< 140 = black, >= 140 = white) │
|
||
│ - Pack 8 pixels into 1 byte (1-bit bitmap) │
|
||
│ - Width: 384px = 48 bytes per row │
|
||
│ - Height: 384 rows │
|
||
│ - Total: 48 × 384 = 18,432 bytes │
|
||
│ │
|
||
│ Output: Uint8Array(18432) │
|
||
└────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌────────────────────────────────────────────────────────────┐
|
||
│ 5. PRINT PROTOCOL │
|
||
│ ─────────────────────────────────────────────────────────│
|
||
│ printTask.printInit() │
|
||
│ └─> Send: [CMD_INIT, density, labelType, ...] │
|
||
│ │
|
||
│ printTask.printPage(encoded, quantity) │
|
||
│ └─> Send in chunks: │
|
||
│ [CMD_IMAGE_HEADER, width, height] │
|
||
│ [CMD_IMAGE_DATA, chunk1...] │
|
||
│ [CMD_IMAGE_DATA, chunk2...] │
|
||
│ ... │
|
||
│ [CMD_IMAGE_END] │
|
||
│ │
|
||
│ printTask.waitForFinished() │
|
||
│ └─> Poll status every 100ms │
|
||
│ until status = FINISHED │
|
||
│ │
|
||
│ printTask.printEnd() │
|
||
│ └─> Send: [CMD_PRINT_END] │
|
||
└────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌────────────────────────────────────────────────────────────┐
|
||
│ 6. PHYSICAL OUTPUT │
|
||
│ ─────────────────────────────────────────────────────────│
|
||
│ Printer Niimbot: │
|
||
│ - Receives binary data via BLE/USB │
|
||
│ - Thermal head heats selected pixels │
|
||
│ - Paper feeds forward │
|
||
│ - Label printed with QR + text │
|
||
│ - Cut (automatic or manual) │
|
||
│ │
|
||
│ Result: Physical label 40x40mm dengan QR code │
|
||
└────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 🧩 Component Interaction Map
|
||
|
||
```
|
||
┌──────────────────────┐
|
||
│ App.vue / Router │
|
||
└──────────┬───────────┘
|
||
│
|
||
▼
|
||
┌──────────────────────┐
|
||
│ BrankasList.vue │
|
||
│ │
|
||
│ ┌────────────────┐ │
|
||
│ │ Header │ │
|
||
│ │ - Printer Btn │──┼──┐
|
||
│ └────────────────┘ │ │
|
||
│ │ │
|
||
│ ┌────────────────┐ │ │
|
||
│ │ Item List │ │ │
|
||
│ │ - Click item │──┼──┼──┐
|
||
│ └────────────────┘ │ │ │
|
||
│ │ │ │
|
||
│ ┌────────────────┐ │ │ │
|
||
│ │ Item Modal │ │ │ │
|
||
│ │ - QR Preview │ │ │ │
|
||
│ │ - Print Btn │──┼──┼──┼──┐
|
||
│ └────────────────┘ │ │ │ │
|
||
└──────────────────────┘ │ │ │
|
||
│ │ │
|
||
┌─────────────────────────────────────┘ │ │
|
||
│ │ │
|
||
▼ │ │
|
||
┌──────────────────┐ │ │
|
||
│ NiimbotConnector │ │ │
|
||
│ .vue │ │ │
|
||
│ │ │ │
|
||
│ - Connect UI │◄───────────────────────────┘ │
|
||
│ - Status display │ │
|
||
│ - Printer info │ │
|
||
└────────┬─────────┘ │
|
||
│ │
|
||
│ uses │
|
||
│ │
|
||
▼ │
|
||
┌──────────────────────────────────────────────────┼───┐
|
||
│ useNiimbotPrinter.js (Composable) │ │
|
||
│ │ │
|
||
│ - State: printerClient, connectionState, etc │◄──┘
|
||
│ - Methods: connect(), disconnect(), printQR() │
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────┐ │
|
||
│ │ Event Listeners Setup │ │
|
||
│ │ - on('connect') │ │
|
||
│ │ - on('disconnect') │ │
|
||
│ │ - on('printprogress') │ │
|
||
│ │ - on('heartbeat') │ │
|
||
│ └─────────────────────────────────────────────┘ │
|
||
└──────────────────┬───────────────────────────────┘
|
||
│ imports
|
||
▼
|
||
┌────────────────────────────────────────────────────┐
|
||
│ @mmote/niimbluelib │
|
||
│ │
|
||
│ - NiimbotBluetoothClient │
|
||
│ - NiimbotSerialClient │
|
||
│ - ImageEncoder │
|
||
│ - PrintTask abstraction │
|
||
│ - Utils │
|
||
└──────────────────┬─────────────────────────────────┘
|
||
│ uses
|
||
▼
|
||
┌────────────────────────────────────────────────────┐
|
||
│ Browser APIs │
|
||
│ - navigator.bluetooth (Web Bluetooth API) │
|
||
│ - navigator.serial (Web Serial API) │
|
||
└────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## ⚡ Performance Timeline
|
||
|
||
```
|
||
Event Timeline (typical print job):
|
||
|
||
0ms │ User clicks "Cetak ke Niimbot"
|
||
│
|
||
10ms │ Check printer connection
|
||
│ └─> Already connected ✓
|
||
│
|
||
20ms │ createQRLabelCanvas() start
|
||
│ └─> Load QR image
|
||
│
|
||
150ms │ Image loaded, draw to canvas
|
||
│ └─> Draw QR, text, etc
|
||
│
|
||
170ms │ canvas.toDataURL()
|
||
│
|
||
200ms │ printQRCode() called
|
||
│ └─> stopHeartbeat()
|
||
│
|
||
220ms │ newPrintTask()
|
||
│
|
||
240ms │ ImageEncoder.encodeCanvas()
|
||
│ └─> RGB → grayscale
|
||
│ └─> Threshold
|
||
│ └─> Pack to 1-bit
|
||
│
|
||
450ms │ Encoding complete (18KB data)
|
||
│
|
||
470ms │ printTask.printInit()
|
||
│ └─> Send init command
|
||
│
|
||
490ms │ ACK received
|
||
│
|
||
500ms │ printTask.printPage()
|
||
│ └─> Send image header
|
||
│
|
||
520ms │ Send data chunk 1/10
|
||
540ms │ Send data chunk 2/10
|
||
... │ ...
|
||
740ms │ Send data chunk 10/10
|
||
│
|
||
750ms │ All data sent
|
||
│
|
||
780ms │ waitForFinished() polling start
|
||
│
|
||
800ms │ Status: PRINTING (0%)
|
||
900ms │ Status: PRINTING (25%)
|
||
1000ms │ Status: PRINTING (50%)
|
||
1100ms │ Status: PRINTING (75%)
|
||
1200ms │ Status: PRINTING (100%)
|
||
│
|
||
1220ms │ Status: FINISHED
|
||
│
|
||
1230ms │ printTask.printEnd()
|
||
│
|
||
1250ms │ startHeartbeat()
|
||
│
|
||
1260ms │ Alert: "QR Code berhasil dicetak!"
|
||
│
|
||
Total: ~1.3 seconds dari klik hingga selesai
|
||
```
|
||
|
||
---
|
||
|
||
## 🔐 Security & Privacy
|
||
|
||
```
|
||
Data Flow Security:
|
||
|
||
┌──────────────────┐
|
||
│ User's Browser │
|
||
└────────┬─────────┘
|
||
│
|
||
│ HTTPS (encrypted)
|
||
│
|
||
▼
|
||
┌──────────────────┐
|
||
│ QR API Server │ ← External: api.qrserver.com
|
||
└────────┬─────────┘ (Kirim kode_item only)
|
||
│
|
||
│ Returns image URL
|
||
│
|
||
▼
|
||
┌──────────────────┐
|
||
│ User's Browser │
|
||
│ - Generate │
|
||
│ canvas │
|
||
│ - Encode image │
|
||
└────────┬─────────┘
|
||
│
|
||
│ BLE/USB (direct, tidak via internet)
|
||
│ Encrypted jika BLE
|
||
│
|
||
▼
|
||
┌──────────────────┐
|
||
│ Niimbot Printer │ ← Local device, tidak terkoneksi internet
|
||
└──────────────────┘
|
||
|
||
Privacy Notes:
|
||
- Data tidak lewat server backend aplikasi
|
||
- QR Code dibuat real-time di browser
|
||
- Gambar langsung dikirim ke printer lokal
|
||
- Tidak ada logging data item ke cloud
|
||
```
|
||
|
||
---
|
||
|
||
## 📈 Error Handling Flow
|
||
|
||
```
|
||
┌──────────────────┐
|
||
│ User Action │
|
||
└────────┬─────────┘
|
||
│
|
||
▼
|
||
┌──────────────────┐
|
||
│ Try: connect() │
|
||
└────────┬─────────┘
|
||
│
|
||
┌────────────┴────────────┐
|
||
│ │
|
||
┌──────▼──────┐ ┌──────▼──────┐
|
||
│ Success │ │ Error │
|
||
└──────┬──────┘ └──────┬──────┘
|
||
│ │
|
||
│ ▼
|
||
│ ┌────────────────┐
|
||
│ │ Catch error │
|
||
│ │ - Log to │
|
||
│ │ console │
|
||
│ │ - Set error │
|
||
│ │ message │
|
||
│ │ - Alert user │
|
||
│ └────────┬───────┘
|
||
│ │
|
||
│ ▼
|
||
│ ┌────────────────┐
|
||
│ │ connectionState│
|
||
│ │ = 'disconnected│
|
||
│ └────────────────┘
|
||
│
|
||
▼
|
||
┌────────────────┐
|
||
│ fetchPrinterInfo│
|
||
└────────┬────────┘
|
||
│
|
||
┌──────┴──────┐
|
||
│ │
|
||
┌─────▼─────┐ ┌────▼────┐
|
||
│ Success │ │ Error │
|
||
└─────┬─────┘ └────┬────┘
|
||
│ │
|
||
│ └──> Log & continue (non-critical)
|
||
│
|
||
▼
|
||
┌─────────────────┐
|
||
│ startHeartbeat()│
|
||
└─────────┬───────┘
|
||
│
|
||
└──> Connected & Ready
|
||
```
|
||
|
||
---
|
||
|
||
Semua diagram ini membantu memahami bagaimana sistem bekerja end-to-end! 🎉
|