Initial commit: Next.js UWB positioning webapp

- 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
This commit is contained in:
martin 2025-08-20 15:14:34 +02:00
commit fa75faa69d
20 changed files with 7600 additions and 0 deletions

71
lib/serial-utils.ts Normal file
View file

@ -0,0 +1,71 @@
// 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 = ''
}
}

67
lib/uwb-types.ts Normal file
View file

@ -0,0 +1,67 @@
// UWB Device Data Types (from ESP32 project context)
export interface DeviceData {
deviceId: number;
distance: number;
rssi: number;
lastUpdate: number;
active: boolean;
}
export interface AnchorPosition {
anchorId: number;
x: number;
y: number;
confidence: number;
valid: boolean;
}
export interface RangeResult {
tagId: number;
mask: number;
sequence: number;
ranges: number[]; // 8 elements
rssi: number[]; // 8 elements
anchorIds: number[]; // 8 elements
timer: number;
timerSys: number;
}
export interface TagPosition {
x: number;
y: number;
timestamp: number;
confidence: number;
}
// Configuration constants from ESP32 project
export const UWB_CONFIG = {
MAX_ANCHORS: 8,
UWB_TAG_COUNT: 64,
NETWORK_ID: 1234,
DEVICE_TIMEOUT: 5000,
BAUD_RATE: 115200,
DATA_RATE: 1, // 6.8Mbps
RANGE_FILTER: 1
} as const;
// Serial data parsing types
export interface SerialData {
type: 'range' | 'config' | 'status';
raw: string;
parsed?: RangeResult | DeviceData[];
timestamp: number;
}
// File upload types for offline analysis
export interface PositioningSession {
rawData: RangeResult[];
anchors: AnchorPosition[];
tagPath: TagPosition[];
sessionInfo: {
startTime: number;
endTime: number;
duration: number;
totalPoints: number;
};
}