UNPKG

@rwesa/payu-ble

Version:

A flexible, smart Bluetooth Low Energy challenge system for secure device connections

542 lines (438 loc) 11.8 kB
# PayuBLE Troubleshooting Guide This guide helps you diagnose and resolve common issues when working with PayuBLE. ## Table of Contents - [Installation Issues](#installation-issues) - [Challenge Creation Problems](#challenge-creation-problems) - [Verification Failures](#verification-failures) - [Platform Integration Issues](#platform-integration-issues) - [Browser Demo Problems](#browser-demo-problems) - [Performance Issues](#performance-issues) - [Common Error Messages](#common-error-messages) - [Debugging Tips](#debugging-tips) ## Installation Issues ### NPM Installation Failures **Problem**: `npm install payu-ble` fails with permission errors ```bash Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/payu-ble' ``` **Solutions**: ```bash # Option 1: Use npm with --user flag npm install --user payu-ble # Option 2: Configure npm to use different directory npm config set prefix ~/.npm-global export PATH=~/.npm-global/bin:$PATH # Option 3: Use yarn instead yarn add payu-ble ``` **Problem**: Native module compilation fails ```bash Error: Failed to compile native modules ``` **Solutions**: ```bash # Linux/macOS: Install build tools sudo apt-get install build-essential python3-dev # Ubuntu/Debian # or xcode-select --install # macOS # Windows: Install Visual Studio Build Tools npm install --global windows-build-tools ``` ### TypeScript Configuration Issues **Problem**: TypeScript compilation errors ```typescript error TS2307: Cannot find module 'payu-ble' or its corresponding type declarations ``` **Solutions**: ```bash # Ensure TypeScript is installed npm install -g typescript # Check tsconfig.json includes correct module resolution { "compilerOptions": { "moduleResolution": "node", "esModuleInterop": true } } # Force reinstall with types npm uninstall payu-ble npm install payu-ble --save ``` ## Challenge Creation Problems ### Invalid Challenge Configuration **Problem**: Custom challenges throw configuration errors ```typescript Error: Custom challenge requires either validate function or validAnswers array ``` **Solution**: ```typescript // ❌ Incorrect - missing validation createChallenge({ type: 'custom', formula: () => 'What is your name?' // Missing validate or validAnswers }); // ✅ Correct - with validAnswers createChallenge({ type: 'custom', formula: () => 'What is your name?', validAnswers: ['Alice', 'Bob'] }); // ✅ Correct - with validate function createChallenge({ type: 'custom', formula: () => 'What is your name?', validate: (input) => input.length > 0 }); ``` ### Arithmetic Challenge Issues **Problem**: Arithmetic challenges produce invalid expressions ```typescript // Challenge shows: "Solve: NaN + undefined" ``` **Solution**: ```typescript // Check difficulty level is valid const validDifficulties = [1, 2, 3, 4]; const difficulty = Math.min(Math.max(userDifficulty, 1), 4); createChallenge({ type: 'arithmetic', difficulty: difficulty }); ``` ### Hash Challenge Problems **Problem**: Hash challenges fail with crypto errors ```typescript Error: Cannot find module 'crypto' ``` **Solution**: ```typescript // Ensure crypto is properly imported const crypto = require('crypto'); // For browser environments, use a crypto polyfill npm install crypto-browserify // In webpack config: module.exports = { resolve: { fallback: { "crypto": require.resolve("crypto-browserify") } } }; ``` ## Verification Failures ### Case Sensitivity Issues **Problem**: Correct answers are rejected due to case differences ```typescript // User enters "BLUE" but answer is "blue" ``` **Solution**: ```typescript // Enable case-insensitive matching createChallenge({ type: 'custom', formula: () => 'What color is the sky?', validAnswers: ['blue'], caseInsensitive: true // Add this flag }); ``` ### Whitespace Handling **Problem**: Answers with extra spaces are rejected ```typescript // User enters " 42 " but validation expects "42" ``` **Solution**: ```typescript // Trim whitespace in validation createChallenge({ type: 'custom', formula: () => 'What is 6 × 7?', validate: (input) => { const trimmed = input.trim(); return parseInt(trimmed) === 42; } }); ``` ### Expired Challenge Verification **Problem**: Getting "Challenge has expired" errors ```typescript Error: Challenge has expired ``` **Solutions**: ```typescript // 1. Increase TTL for slower users createChallenge({ type: 'custom', formula: () => 'Enter password:', validAnswers: ['secret'], ttl: 300000 // 5 minutes instead of default }); // 2. Check system time synchronization console.log('Current time:', new Date()); console.log('Challenge expires:', new Date(challenge.expiresAt)); // 3. Handle expiration gracefully try { const result = verifyAnswer(userInput); } catch (error) { if (error.message.includes('expired')) { // Generate new challenge const newChallenge = createChallenge(options); } } ``` ## Platform Integration Issues ### GPIO Problems (Raspberry Pi) **Problem**: GPIO access denied ```bash Error: EACCES: permission denied, open '/sys/class/gpio/export' ``` **Solutions**: ```bash # Add user to gpio group sudo usermod -a -G gpio $USER # Enable GPIO interface sudo raspi-config # Interface Options > GPIO > Enable # Check GPIO permissions ls -la /sys/class/gpio/ # Alternative: Run with sudo (not recommended for production) sudo node your-app.js ``` **Problem**: GPIO pins already in use ```typescript Error: EBUSY: resource busy or locked ``` **Solutions**: ```typescript // Properly cleanup GPIO on exit const gpio = new GPIOButtonHelper({ pin: 18 }); process.on('SIGINT', () => { gpio.cleanup(); process.exit(); }); process.on('SIGTERM', () => { gpio.cleanup(); process.exit(); }); // Check if pin is already exported const fs = require('fs'); if (fs.existsSync('/sys/class/gpio/gpio18')) { // Pin is already exported, unexport first fs.writeFileSync('/sys/class/gpio/unexport', '18'); } ``` ### Network Detection Issues **Problem**: No devices found in network scan ```typescript // Empty array returned from discoverLocalDevices() ``` **Solutions**: ```bash # 1. Populate ARP table first ping -c 1 192.168.1.1 nmap -sn 192.168.1.0/24 # 2. Check network interface ip addr show ifconfig # on older systems # 3. Verify subnet configuration ``` ```typescript // Use correct subnet for your network const networkHelper = new NetworkMACHelper({ scanSubnet: true, subnet: '192.168.1.0/24' // Adjust to your network }); ``` **Problem**: ARP command not found ```bash Error: Command not found: arp ``` **Solutions**: ```bash # Install network tools sudo apt-get install net-tools # Ubuntu/Debian sudo yum install net-tools # CentOS/RHEL brew install arp-scan # macOS ``` ### GPS/Location Issues **Problem**: IP geolocation fails ```typescript Error: Fetch failed ``` **Solutions**: ```typescript // Use alternative geolocation services const services = [ 'http://ip-api.com/json', 'https://ipapi.co/json', 'https://api.ipify.org?format=json' ]; for (const service of services) { try { const response = await fetch(service); if (response.ok) { // Use this service break; } } catch (error) { console.warn(`Service ${service} failed:`, error); } } ``` **Problem**: Location accuracy too low ```typescript // IP location shows city instead of building ``` **Solutions**: ```typescript // Increase radius for IP-based location const zone = { lat: 40.7128, lng: -74.0060, radius: 5000 // 5km radius for city-level accuracy }; // Or implement hardware GPS for precise location const gpsHelper = new GPSLocationHelper({ useIPLocation: false, // Use hardware GPS accuracyThreshold: 10 // 10 meter accuracy }); ``` ## Browser Demo Problems ### Web Bluetooth Not Supported **Problem**: "Web Bluetooth not supported" message ```javascript Error: navigator.bluetooth is undefined ``` **Solutions**: 1. **Use supported browser**: Chrome 56+, Edge 79+, Opera 43+ 2. **Enable HTTPS**: Web Bluetooth requires secure context 3. **Check flags**: For experimental features, enable `chrome://flags/#enable-experimental-web-platform-features` ```javascript // Feature detection if (!navigator.bluetooth) { console.error('Web Bluetooth not supported'); // Show alternative connection method } ``` ### Device Discovery Issues **Problem**: No PayuBLE devices found ```javascript Error: No devices found matching filters ``` **Solutions**: ```javascript // 1. Verify device is advertising // Check device implementation advertises correct service UUID // 2. Expand search filters const device = await navigator.bluetooth.requestDevice({ acceptAllDevices: true, // For testing optionalServices: [PAYU_BLE_SERVICE_UUID] }); // 3. Check service UUID matches const PAYU_BLE_SERVICE_UUID = '12345678-1234-1234-1234-123456789abc'; // Ensure device uses same UUID ``` ### Connection Failures **Problem**: GATT connection fails ```javascript Error: GATT Server is disconnected ``` **Solutions**: ```javascript // 1. Implement connection retry async function connectWithRetry(device, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { return await device.gatt.connect(); } catch (error) { if (i === maxRetries - 1) throw error; await new Promise(resolve => setTimeout(resolve, 1000)); } } } // 2. Handle disconnect events device.addEventListener('gattserverdisconnected', () => { console.log('Device disconnected, attempting reconnect...'); // Implement reconnection logic }); // 3. Check device power management // Some devices enter sleep mode, may need wake signal ``` ## Performance Issues ### Slow Challenge Generation **Problem**: Creating challenges takes too long ```typescript // Hash challenges taking several seconds ``` **Solutions**: ```typescript // 1. Pre-generate challenges const challengeCache = []; for (let i = 0; i < 10; i++) { challengeCache.push(createChallenge({ type: 'arithmetic', difficulty: 2 })); } // 2. Use worker threads for complex calculations const { Worker, isMainThread, parentPort } = require('worker_threads'); if (isMainThread) { const worker = new Worker(__filename); worker.postMessage({ type: 'generateChallenge' }); worker.on('message', (challenge) => { // Use generated challenge }); } else { parentPort.on('message', (data) => { if (data.type === 'generateChallenge') { const challenge = createChallenge({ type: 'hash' }); parentPort.postMessage(challenge); } }); } ``` ### Memory Leaks **Problem**: Memory usage increases over time ```bash # Process memory keeps growing ``` **Solutions**: ```typescript // 1. Clear expired challenges setInterval(() => { if (getCurrentChallenge()?.expiresAt && Date.now() > getCurrentChallenge().expiresAt) { clearChallenge(); } }, 60000); // 2. Cleanup GPIO resources process.on('exit', () => { gpioHelper.cleanup(); }); // 3. Limit cache sizes class LimitedCache { constructor(maxSize = 100) { this.cache = new Map(); this.maxSize = maxSize; } set(key, value) { if (this.cache.size >= this.maxSize) { const firstKey = this.cache.keys().next().value; this.cache.delete(firstKey); } this.cache.set(key, value); } } ``` ## Common Error Messages ### "No active challenge" **Cause**: Trying to verify answer without creating challenge first **Solution**: ```typescript // Always create challenge before verification const challenge = createChallenge({ type: 'arithmetic', difficulty: 1 }); // Then verify const result = verifyAnswer('42'); ``` ### "Unsupported challenge type" **Cause**: Invalid challenge type passed to createChallenge **Solution