Available Hooks
useBatteryLevel
Monitor battery level with real-time updates
useCharging
Track charging status and power source
useBluetooth
Control and monitor Bluetooth status
useQRScanner
Scan QR codes with camera
Battery Monitoring
TheuseBatteryLevel hook provides real-time battery level monitoring with automatic updates.
Basic Battery Display
import { useBatteryLevel } from 'node-fullykiosk';
function BatteryIndicator() {
const { batteryLevel } = useBatteryLevel();
const getBatteryIcon = (level: number | undefined) => {
if (level === undefined) return '?';
if (level > 75) return '🔋';
if (level > 50) return '🔋';
if (level > 25) return '🪫';
return '🪫';
};
return (
<div>
<span>{getBatteryIcon(batteryLevel)}</span>
<span>{batteryLevel ?? '--'}%</span>
</div>
);
}
The
useBatteryLevel hook automatically subscribes to battery level changes and updates in real-time using the onBatteryLevelChanged event.Charging Status Monitor
Track charging status and power source type:import { useCharging, useBatteryLevel } from 'node-fullykiosk';
function PowerStatus() {
const { batteryLevel } = useBatteryLevel();
const { charging, chargeState } = useCharging();
const getChargeTypeLabel = (state: string | undefined) => {
if (!state) return 'Unknown';
switch (state) {
case 'pluggedAC': return 'AC Adapter';
case 'pluggedUSB': return 'USB';
case 'pluggedWireless': return 'Wireless';
case 'unplugged': return 'Not charging';
default: return 'Charging';
}
};
return (
<div>
<h3>Power Status</h3>
<p>Battery Level: {batteryLevel}%</p>
<p>Status: {charging ? 'Charging' : 'Not Charging'}</p>
<p>Power Source: {getChargeTypeLabel(chargeState)}</p>
{charging && batteryLevel !== undefined && batteryLevel < 100 && (
<p className="info">Charging in progress...</p>
)}
{batteryLevel !== undefined && batteryLevel < 20 && !charging && (
<p className="warning">Low battery! Please charge device.</p>
)}
</div>
);
}
Battery Health Dashboard
Create a comprehensive battery monitoring dashboard:import { useBatteryLevel, useCharging } from 'node-fullykiosk';
import { useEffect, useState } from 'react';
interface BatterySnapshot {
timestamp: string;
level: number;
charging: boolean;
}
function BatteryDashboard() {
const { batteryLevel } = useBatteryLevel();
const { charging, chargeState } = useCharging();
const [history, setHistory] = useState<BatterySnapshot[]>([]);
useEffect(() => {
if (batteryLevel === undefined) return;
setHistory(prev => [
...prev.slice(-20), // Keep last 20 readings
{
timestamp: new Date().toISOString(),
level: batteryLevel,
charging: charging ?? false,
},
]);
}, [batteryLevel]);
const getHealthStatus = () => {
if (batteryLevel === undefined) return 'Unknown';
if (batteryLevel > 80) return 'Excellent';
if (batteryLevel > 50) return 'Good';
if (batteryLevel > 20) return 'Fair';
return 'Critical';
};
return (
<div className="battery-dashboard">
<h2>Battery Dashboard</h2>
<div className="battery-gauge">
<div
className="battery-fill"
style={{
width: `${batteryLevel ?? 0}%`,
backgroundColor: batteryLevel && batteryLevel > 20 ? '#4CAF50' : '#F44336'
}}
/>
<span className="battery-text">{batteryLevel}%</span>
</div>
<div className="status-grid">
<div>
<strong>Health:</strong> {getHealthStatus()}
</div>
<div>
<strong>Charging:</strong> {charging ? 'Yes' : 'No'}
</div>
<div>
<strong>Source:</strong> {chargeState}
</div>
</div>
<div className="battery-history">
<h3>Recent History</h3>
{history.slice(-5).reverse().map((snapshot, i) => (
<div key={i}>
{new Date(snapshot.timestamp).toLocaleTimeString()}: {snapshot.level}%
{snapshot.charging && ' (charging)'}
</div>
))}
</div>
</div>
);
}
Bluetooth Control
TheuseBluetooth hook provides Bluetooth status monitoring and control.
Basic Bluetooth Control
import { useBluetooth } from 'node-fullykiosk';
function BluetoothControl() {
const { enabled, enable, disable, openSettings } = useBluetooth();
return (
<div>
<h3>Bluetooth</h3>
<p>Status: {enabled ? 'Enabled' : 'Disabled'}</p>
<button onClick={enable} disabled={enabled}>
Enable Bluetooth
</button>
<button onClick={disable} disabled={!enabled}>
Disable Bluetooth
</button>
<button onClick={openSettings}>
Open Settings
</button>
</div>
);
}
The
useBluetooth hook polls the Bluetooth status every second. This is suitable for most applications, but be aware of the performance implications in resource-constrained environments.NFC Access Control System
Implement an access control system using NFC tags:import { useNFC } from 'node-fullykiosk';
import { useState } from 'react';
interface AccessLog {
timestamp: string;
serial: string;
granted: boolean;
}
function NFCAccessControl() {
const [accessLog, setAccessLog] = useState<AccessLog[]>([]);
const [currentUser, setCurrentUser] = useState<string | null>(null);
// Simulated authorized tags database
const authorizedTags = new Set([
'04:A1:B2:C3:D4:E5:F6',
'04:11:22:33:44:55:66',
]);
const { isScanning, start } = useNFC({
onNfcTagDiscovered: (serial, type, message, data) => {
const granted = authorizedTags.has(serial);
setAccessLog(prev => [
...prev,
{
timestamp: new Date().toISOString(),
serial,
granted,
},
]);
if (granted) {
setCurrentUser(serial);
// Unlock door, grant access, etc.
}
},
onNfcTagRemoved: (serial) => {
if (currentUser === serial) {
setCurrentUser(null);
}
},
});
return (
<div className="access-control">
<h2>NFC Access Control</h2>
{!isScanning && (
<button onClick={start}>Start Access Control</button>
)}
{currentUser ? (
<div className="access-granted">
<h3>Access Granted</h3>
<p>User: {currentUser}</p>
</div>
) : (
<div className="access-waiting">
<p>Scan your NFC tag to gain access</p>
</div>
)}
<div className="access-log">
<h3>Access Log</h3>
{accessLog.slice(-10).reverse().map((entry, i) => (
<div key={i} className={entry.granted ? 'granted' : 'denied'}>
<span>{new Date(entry.timestamp).toLocaleTimeString()}</span>
<span>{entry.serial}</span>
<span>{entry.granted ? '✓ Granted' : '✗ Denied'}</span>
</div>
))}
</div>
</div>
);
}
QR Code Scanner
TheuseQRScanner hook provides QR code scanning with extensive configuration options.
Basic QR Scanner
import { useQRScanner } from 'node-fullykiosk';
import { useState } from 'react';
function QRScanner() {
const [scannedCodes, setScannedCodes] = useState<string[]>([]);
const { scannedQR, startScanning } = useQRScanner({
onScan: (code) => {
console.log('QR Code scanned:', code);
setScannedCodes(prev => [...prev, code]);
},
onCancel: () => {
console.log('Scan cancelled');
},
});
const handleScan = () => {
startScanning(
'Scan QR Code', // Prompt message
'', // Result URL (empty for callback)
-1, // Camera ID (-1 for default)
-1, // Timeout (-1 for no timeout)
true, // Beep on success
true, // Show cancel button
false // Use flashlight
);
};
return (
<div>
<h3>QR Code Scanner</h3>
<button onClick={handleScan}>Scan QR Code</button>
{scannedQR && (
<div className="scan-result">
<h4>Last Scanned:</h4>
<code>{scannedQR}</code>
</div>
)}
{scannedCodes.length > 0 && (
<div className="scan-history">
<h4>Scan History</h4>
<ul>
{scannedCodes.slice(-5).reverse().map((code, i) => (
<li key={i}><code>{code}</code></li>
))}
</ul>
</div>
)}
</div>
);
}
Advanced QR Scanner with Options
Implement a scanner with customizable options:import { useQRScanner } from 'node-fullykiosk';
import { useState } from 'react';
function AdvancedQRScanner() {
const [options, setOptions] = useState({
timeout: 30000,
beepEnabled: true,
showCancelButton: true,
useFlashlight: false,
});
const [scannedData, setScannedData] = useState<string | null>(null);
const { startScanning } = useQRScanner({
onScan: (code) => {
setScannedData(code);
// Process scanned data
if (code.startsWith('http')) {
// Handle URL
window.location.href = code;
} else {
// Handle other data types
console.log('Data:', code);
}
},
onCancel: () => {
console.log('User cancelled scan');
},
});
const handleScan = () => {
startScanning(
'Point camera at QR code',
'',
-1,
options.timeout,
options.beepEnabled,
options.showCancelButton,
options.useFlashlight
);
};
return (
<div>
<h3>Advanced QR Scanner</h3>
<div className="scanner-options">
<label>
<input
type="checkbox"
checked={options.beepEnabled}
onChange={(e) => setOptions({ ...options, beepEnabled: e.target.checked })}
/>
Beep on success
</label>
<label>
<input
type="checkbox"
checked={options.showCancelButton}
onChange={(e) => setOptions({ ...options, showCancelButton: e.target.checked })}
/>
Show cancel button
</label>
<label>
<input
type="checkbox"
checked={options.useFlashlight}
onChange={(e) => setOptions({ ...options, useFlashlight: e.target.checked })}
/>
Use flashlight
</label>
<label>
Timeout (ms):
<input
type="number"
value={options.timeout}
onChange={(e) => setOptions({ ...options, timeout: parseInt(e.target.value) })}
/>
</label>
</div>
<button onClick={handleScan}>Start Scan</button>
{scannedData && (
<div className="result">
<h4>Scanned Data:</h4>
<pre>{scannedData}</pre>
</div>
)}
</div>
);
}
Inventory Scanner Application
Build a complete inventory management scanner:import { useQRScanner } from 'node-fullykiosk';
import { useState } from 'react';
interface InventoryItem {
code: string;
scannedAt: string;
verified: boolean;
}
function InventoryScanner() {
const [items, setItems] = useState<InventoryItem[]>([]);
const [scanning, setScanning] = useState(false);
const { startScanning } = useQRScanner({
onScan: async (code) => {
// Verify item in database
const verified = await verifyInventoryItem(code);
setItems(prev => [
...prev,
{
code,
scannedAt: new Date().toISOString(),
verified,
},
]);
// Continue scanning
if (scanning) {
setTimeout(() => handleScan(), 1000);
}
},
onCancel: () => {
setScanning(false);
},
});
const verifyInventoryItem = async (code: string): Promise<boolean> => {
// Simulate API call
return new Promise(resolve => {
setTimeout(() => resolve(Math.random() > 0.2), 500);
});
};
const handleScan = () => {
startScanning(
'Scan inventory item',
'',
-1,
30000,
true,
true,
false
);
};
const startBatchScan = () => {
setScanning(true);
handleScan();
};
const stopBatchScan = () => {
setScanning(false);
};
const exportData = () => {
const csv = [
'Code,Scanned At,Verified',
...items.map(item =>
`${item.code},${item.scannedAt},${item.verified}`
),
].join('\n');
const blob = new Blob([csv], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `inventory-${new Date().toISOString()}.csv`;
a.click();
};
return (
<div className="inventory-scanner">
<h2>Inventory Scanner</h2>
<div className="controls">
{!scanning ? (
<button onClick={startBatchScan}>Start Batch Scan</button>
) : (
<button onClick={stopBatchScan}>Stop Scanning</button>
)}
<button onClick={exportData} disabled={items.length === 0}>
Export Data
</button>
</div>
<div className="stats">
<div>Total Scanned: {items.length}</div>
<div>Verified: {items.filter(i => i.verified).length}</div>
<div>Failed: {items.filter(i => !i.verified).length}</div>
</div>
<table>
<thead>
<tr>
<th>Code</th>
<th>Time</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{items.slice(-10).reverse().map((item, i) => (
<tr key={i} className={item.verified ? 'verified' : 'failed'}>
<td><code>{item.code}</code></td>
<td>{new Date(item.scannedAt).toLocaleTimeString()}</td>
<td>{item.verified ? '✓' : '✗'}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
Best Practices
Handle hardware availability
Always check if hooks return
undefined and provide appropriate fallbacksClean up event listeners
Hooks automatically clean up on unmount, but be mindful of component lifecycle
NFC and QR scanning require appropriate permissions in Fully Kiosk Browser. Ensure your device has the necessary hardware and permissions configured.
Battery monitoring, Bluetooth control, and hardware scanning can impact device performance. Use polling intervals wisely and stop scanning when not needed.
Related Hooks
- Device Information - Device identifiers and information
- Screen Control - Display management
- Network Connectivity - Network status monitoring
