- Complete Next.js 14 app with TypeScript and Tailwind CSS - ESP32 serial communication via API routes - Real-time UWB positioning visualization - Interactive 2D warehouse mapping with Canvas - Device connection interface with auto-detection - AT command parsing for UWBHelper library integration - Clean project structure with comprehensive documentation
71 lines
No EOL
2 KiB
TypeScript
71 lines
No EOL
2 KiB
TypeScript
// Utility functions for serial communication and UWB data processing
|
|
|
|
export interface SerialPortInfo {
|
|
path: string
|
|
manufacturer?: string
|
|
serialNumber?: string
|
|
pnpId?: string
|
|
locationId?: string
|
|
productId?: string
|
|
vendorId?: string
|
|
}
|
|
|
|
export class UWBDataProcessor {
|
|
private static instance: UWBDataProcessor
|
|
private dataBuffer: string = ''
|
|
|
|
static getInstance(): UWBDataProcessor {
|
|
if (!UWBDataProcessor.instance) {
|
|
UWBDataProcessor.instance = new UWBDataProcessor()
|
|
}
|
|
return UWBDataProcessor.instance
|
|
}
|
|
|
|
// Process incoming serial data stream
|
|
processDataStream(chunk: string): string[] {
|
|
this.dataBuffer += chunk
|
|
const lines: string[] = []
|
|
|
|
// Split on line endings
|
|
const parts = this.dataBuffer.split(/\r?\n/)
|
|
|
|
// Keep last incomplete line in buffer
|
|
this.dataBuffer = parts.pop() || ''
|
|
|
|
// Return complete lines
|
|
return parts.filter(line => line.trim().length > 0)
|
|
}
|
|
|
|
// Check if ESP32 device based on port info
|
|
static isESP32Device(port: SerialPortInfo): boolean {
|
|
const esp32Vendors = ['10C4', '1A86', '0403'] // Silicon Labs, QinHeng, FTDI
|
|
const esp32Manufacturers = ['Silicon Labs', 'FTDI', 'QinHeng Electronics']
|
|
|
|
return (
|
|
(port.vendorId && esp32Vendors.includes(port.vendorId)) ||
|
|
(port.manufacturer && esp32Manufacturers.some(m =>
|
|
port.manufacturer?.includes(m)
|
|
))
|
|
)
|
|
}
|
|
|
|
// Validate UWB command format
|
|
static validateUWBCommand(command: string): boolean {
|
|
const validCommands = [
|
|
'AT?', 'AT+GETVER?', 'AT+RESTART', 'AT+RESTORE', 'AT+SAVE',
|
|
'AT+SETCFG=', 'AT+GETCFG?', 'AT+SETANT=', 'AT+GETANT?',
|
|
'AT+SETCAP=', 'AT+GETCAP?', 'AT+SETRPT=', 'AT+GETRPT?',
|
|
'AT+SLEEP=', 'AT+SETPOW=', 'AT+GETPOW?', 'AT+DATA=',
|
|
'AT+RDATA', 'AT+SETPAN=', 'AT+GETPAN?'
|
|
]
|
|
|
|
return validCommands.some(cmd =>
|
|
command.startsWith(cmd) || command === cmd
|
|
)
|
|
}
|
|
|
|
// Clear data buffer
|
|
clearBuffer(): void {
|
|
this.dataBuffer = ''
|
|
}
|
|
} |