Phase 8: Visitor Management - Visitor/VisitorLog/AccessZone models - Check-in/out with badge generation - Zone occupancy tracking - Kiosk and management pages Phase 9: Messaging & Communication - Announcements with priority levels - Acknowledgement tracking - Shift notes for team handoffs - AnnouncementBanner component Phase 10: Compliance & Audit Trail - Immutable AuditLog model - Document versioning and approval workflow - Acknowledgement tracking for SOPs - CSV export for audit logs Phase 11: Accessibility & i18n - WCAG 2.1 AA compliance utilities - react-i18next with EN/ES translations - User preferences context (theme, font size, etc) - High contrast and reduced motion support Phase 12: Hardware Integration - QR code generation for batches/plants/visitors - Printable label system - Visitor badge printing Phase 13: Advanced Features - Environmental monitoring (sensors, readings, alerts) - Financial tracking (transactions, P&L reports) - AI/ML insights (yield predictions, anomaly detection)
288 lines
9.3 KiB
Markdown
288 lines
9.3 KiB
Markdown
# Hardware Integration Spec: NFC, QR Codes & E-Ink Displays
|
|
|
|
## 🔖 NFC/RFID Integration
|
|
|
|
### Use Cases
|
|
|
|
1. **Visitor Badge Scan**: Tap badge to check in/out
|
|
2. **Employee Time Clock**: Tap badge to clock in/out
|
|
3. **Zone Access**: Tap to log entry into restricted areas
|
|
4. **Equipment Checkout**: Tap to log tool/equipment usage
|
|
5. **Plant/Batch Tags**: Tap to view batch details on mobile
|
|
|
|
### Hardware Options
|
|
|
|
| Device Type | Range | Use Case | Est. Cost |
|
|
|-------------|-------|----------|-----------|
|
|
| **MIFARE DESFire EV3** | 3-5cm | High-security badges | $2-5/card |
|
|
| **NFC Tags (NTAG216)** | 1-3cm | Plant/room tags | $0.20-0.50/tag |
|
|
| **USB NFC Reader** | 3-5cm | Desktop check-in | $30-50 |
|
|
| **Embedded NFC (Phone)** | 1-5cm | Mobile scan | Built-in |
|
|
|
|
### Data Model
|
|
|
|
```prisma
|
|
model NFCTag {
|
|
id String @id @default(uuid())
|
|
uid String @unique // NFC chip unique ID
|
|
type String // BADGE, PLANT_TAG, ROOM_TAG, EQUIPMENT
|
|
linkedId String // Points to User, Batch, Room, or Equipment
|
|
linkedType String // USER, BATCH, ROOM, EQUIPMENT
|
|
isActive Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
}
|
|
|
|
model NFCScan {
|
|
id String @id @default(uuid())
|
|
tagId String
|
|
scannedBy String? // User who scanned
|
|
deviceId String? // Which reader/phone
|
|
action String // CHECK_IN, CHECK_OUT, VIEW, ACCESS
|
|
location String?
|
|
timestamp DateTime @default(now())
|
|
}
|
|
```
|
|
|
|
### API Endpoints
|
|
|
|
```
|
|
POST /api/nfc/scan
|
|
Body: { uid, deviceId, location }
|
|
Returns: { action, linkedEntity, redirect? }
|
|
|
|
POST /api/nfc/provision
|
|
Body: { uid, type, linkedId }
|
|
Returns: { tagId, success }
|
|
|
|
GET /api/nfc/tag/:uid
|
|
Returns: Tag details + linked entity
|
|
```
|
|
|
|
### Frontend Integration
|
|
|
|
```tsx
|
|
// Using Web NFC API (Chrome Android only currently)
|
|
if ('NDEFReader' in window) {
|
|
const reader = new NDEFReader();
|
|
await reader.scan();
|
|
reader.onreading = (event) => {
|
|
const uid = event.serialNumber;
|
|
await api.post('/nfc/scan', { uid, deviceId: getDeviceId() });
|
|
};
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📱 QR Code System
|
|
|
|
### Use Cases
|
|
|
|
1. **Batch QR**: Scan to view batch details, log touch points
|
|
2. **Room QR**: Posted at room entrance, shows room status
|
|
3. **Visitor Badge**: QR code printed on visitor badges
|
|
4. **Equipment Tags**: Scan to view maintenance history
|
|
5. **SOP Access**: Scan to view relevant procedures
|
|
|
|
### QR Code Content Format
|
|
|
|
```json
|
|
{
|
|
"v": 1, // Version
|
|
"t": "BATCH", // Type
|
|
"id": "abc123", // Entity ID
|
|
"u": "https://app.777wolfpack.com/batch/abc123"
|
|
}
|
|
```
|
|
|
|
### Generation & Display
|
|
|
|
```tsx
|
|
// Using qrcode.react
|
|
import { QRCodeSVG } from 'qrcode.react';
|
|
|
|
<QRCodeSVG
|
|
value={JSON.stringify({ t: 'BATCH', id: batch.id, u: batchUrl })}
|
|
size={200}
|
|
level="H" // High error correction for durability
|
|
includeMargin={true}
|
|
/>
|
|
```
|
|
|
|
### Scanning
|
|
|
|
- **Mobile App**: Use device camera + library like `@zxing/browser`
|
|
- **Kiosk**: USB camera with continuous scanning
|
|
- **Web**: `navigator.mediaDevices.getUserMedia()` + `jsQR`
|
|
|
|
### Printable Labels
|
|
|
|
- **Batch Labels**: 2x1" thermal labels with QR + batch name
|
|
- **Room Signs**: 4x6" laminated signs with room QR
|
|
- **Visitor Badges**: 3x4" sticky label printer
|
|
|
|
---
|
|
|
|
## 📺 E-Ink Display Network
|
|
|
|
### Vision
|
|
|
|
Mount low-power e-ink displays throughout the facility showing real-time room status, tasks, and alerts. Zero maintenance (battery lasts 2+ years).
|
|
|
|
### Hardware Recommendations
|
|
|
|
| Device | Display | Battery | WiFi | Est. Cost | Use Case |
|
|
|--------|---------|---------|------|-----------|----------|
|
|
| **Waveshare 7.5" e-Paper** | 800x480 | 6-12 mo | ESP32 | $45 | Room status boards |
|
|
| **LILYGO T5** | 2.13" | 12+ mo | ESP32 | $20 | Shelf tags |
|
|
| **Good Display 4.2"** | 400x300 | 12+ mo | ESP32 | $35 | Plant row tags |
|
|
| **Inkplate 6** | 6" | 12+ mo | ESP32 | $80 | Task boards |
|
|
|
|
### Display Locations & Content
|
|
|
|
#### 1. Room Entrance Displays (7.5")
|
|
|
|
```
|
|
┌────────────────────────────────┐
|
|
│ 🌿 ROOM: VEG-A │
|
|
│ ─────────────────────────────│
|
|
│ Batches: 4 │
|
|
│ Plants: 847 │
|
|
│ Stage: Vegetative │
|
|
│ ─────────────────────────────│
|
|
│ CURRENT TASKS: │
|
|
│ □ Water all trays (Due 2pm) │
|
|
│ □ Trim lower fan leaves │
|
|
│ ─────────────────────────────│
|
|
│ Last updated: Dec 10, 2:30pm │
|
|
│ [QR CODE] Scan for details │
|
|
└────────────────────────────────┘
|
|
```
|
|
|
|
#### 2. Batch Row Tags (2.13")
|
|
|
|
```
|
|
┌──────────────┐
|
|
│ BATCH: OGK-4 │
|
|
│ Plants: 48 │
|
|
│ Day 24 / Veg │
|
|
│ [QR] │
|
|
└──────────────┘
|
|
```
|
|
|
|
#### 3. Task Board (6")
|
|
|
|
```
|
|
┌────────────────────────────────┐
|
|
│ 📋 TODAY'S TASKS │
|
|
│ ─────────────────────────────│
|
|
│ OVERDUE (2) │
|
|
│ • IPM spray - Flower-B │
|
|
│ • Transplant clones │
|
|
│ ─────────────────────────────│
|
|
│ DUE TODAY (5) │
|
|
│ □ Morning inspection │
|
|
│ □ Water schedule - All rooms │
|
|
│ □ Foliar feed - Veg rooms │
|
|
│ □ Trim - Flower-A │
|
|
│ □ Harvest prep - Dry room │
|
|
│ ─────────────────────────────│
|
|
│ Shift: Day | Staff: 4 active │
|
|
└────────────────────────────────┘
|
|
```
|
|
|
|
### Architecture
|
|
|
|
```
|
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
│ Backend │────▶ │ Redis/ │────▶ │ Display │
|
|
│ API │ │ MQTT │ │ Controller │
|
|
└─────────────┘ └─────────────┘ └─────────────┘
|
|
│
|
|
┌───────────────────────────┼───────────────────────────┐
|
|
│ │ │
|
|
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
|
|
│ Room-A │ │ Room-B │ │ Lobby │
|
|
│ E-Ink │ │ E-Ink │ │ E-Ink │
|
|
└─────────────┘ └─────────────┘ └─────────────┘
|
|
```
|
|
|
|
### Update Protocol
|
|
|
|
1. **Backend publishes** status change to MQTT topic `display/room/{roomId}`
|
|
2. **ESP32 subscribes** to its topic, wakes on message
|
|
3. **ESP32 fetches** image from `GET /api/display/room/{roomId}?format=bmp`
|
|
4. **Backend renders** server-side image (using Puppeteer or Sharp)
|
|
5. **ESP32 displays** image and goes back to deep sleep
|
|
|
|
### API Endpoints
|
|
|
|
```
|
|
GET /api/display/room/:id
|
|
Returns: BMP/PNG image optimized for e-ink
|
|
|
|
GET /api/display/tasks
|
|
Query: ?type=overview|room
|
|
Returns: Task board image
|
|
|
|
POST /api/display/register
|
|
Body: { deviceId, type, linkedId }
|
|
Returns: { displayId, config }
|
|
```
|
|
|
|
### Power Management
|
|
|
|
- **Deep Sleep**: ESP32 sleeps 90%+ of time
|
|
- **Wake Schedule**: Every 15 min OR on MQTT push
|
|
- **Battery Monitor**: Report battery level with each update
|
|
- **Solar Option**: Some displays have solar panels (2+ years)
|
|
|
|
### Firmware (ESP32 Arduino)
|
|
|
|
```cpp
|
|
#include <WiFi.h>
|
|
#include <HTTPClient.h>
|
|
#include <GxEPD2_BW.h>
|
|
|
|
void loop() {
|
|
connectWiFi();
|
|
|
|
HTTPClient http;
|
|
http.begin("https://api.777wolfpack.com/display/room/veg-a?format=bmp");
|
|
http.addHeader("Authorization", "Bearer " + String(API_KEY));
|
|
|
|
int httpCode = http.GET();
|
|
if (httpCode == 200) {
|
|
// Stream directly to display
|
|
display.drawBitmap(http.getStream());
|
|
}
|
|
|
|
http.end();
|
|
WiFi.disconnect();
|
|
|
|
// Sleep for 15 minutes
|
|
esp_deep_sleep(15 * 60 * 1000000);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Implementation Priority
|
|
|
|
| Feature | Priority | Effort | Impact |
|
|
|---------|----------|--------|--------|
|
|
| QR Code generation | 🔴 High | 1 day | Immediate utility |
|
|
| Batch QR labels | 🔴 High | 2 days | Track & trace |
|
|
| Visitor badge QR | 🔴 High | 1 day | Compliance |
|
|
| Room entrance e-ink | 🟡 Medium | 1 week | Visibility |
|
|
| NFC badge check-in | 🟡 Medium | 3 days | Efficiency |
|
|
| Batch row e-ink tags | 🟢 Low | 2 weeks | Nice to have |
|
|
|
|
---
|
|
|
|
## 🔧 Quick Wins (Start Here)
|
|
|
|
1. **Add QR codes to batch cards** - Use `qrcode.react`
|
|
2. **Print batch labels** - Thermal printer + QR
|
|
3. **Visitor badge printing** - Generate PDF with QR
|
|
4. **One pilot e-ink display** - Room entrance PoC
|