mirror of
https://github.com/ruvnet/RuView
synced 2026-07-29 18:31:44 +00:00
feat: Implement RSSI service for iOS and Web platforms
- Added IosRssiService to handle synthetic RSSI data for iOS. - Created WebRssiService to simulate RSSI scanning on the web. - Defined shared types for WifiNetwork and RssiService in rssi.service.ts. - Introduced simulation service to generate synthetic sensing data. - Implemented WebSocket service for real-time data handling with reconnection logic. - Established Zustand stores for managing application state related to MAT and pose data. - Developed theme context and utility functions for consistent styling and formatting. - Added type definitions for various application entities including API responses and sensing data. - Created utility functions for color mapping and URL validation. - Configured TypeScript settings for the mobile application.
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
import { useEffect } from 'react';
|
||||
import { wsService } from '@/services/ws.service';
|
||||
import { usePoseStore } from '@/stores/poseStore';
|
||||
|
||||
export interface UsePoseStreamResult {
|
||||
connectionStatus: ReturnType<typeof usePoseStore.getState>['connectionStatus'];
|
||||
lastFrame: ReturnType<typeof usePoseStore.getState>['lastFrame'];
|
||||
isSimulated: boolean;
|
||||
}
|
||||
|
||||
export function usePoseStream(): UsePoseStreamResult {
|
||||
const connectionStatus = usePoseStore((state) => state.connectionStatus);
|
||||
const lastFrame = usePoseStore((state) => state.lastFrame);
|
||||
const isSimulated = usePoseStore((state) => state.isSimulated);
|
||||
|
||||
useEffect(() => {
|
||||
const unsubscribe = wsService.subscribe((frame) => {
|
||||
usePoseStore.getState().handleFrame(frame);
|
||||
});
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return { connectionStatus, lastFrame, isSimulated };
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { rssiService, type WifiNetwork } from '@/services/rssi.service';
|
||||
import { useSettingsStore } from '@/stores/settingsStore';
|
||||
|
||||
export function useRssiScanner(): { networks: WifiNetwork[]; isScanning: boolean } {
|
||||
const enabled = useSettingsStore((state) => state.rssiScanEnabled);
|
||||
const [networks, setNetworks] = useState<WifiNetwork[]>([]);
|
||||
const [isScanning, setIsScanning] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled) {
|
||||
rssiService.stopScanning();
|
||||
setIsScanning(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const unsubscribe = rssiService.subscribe((result) => {
|
||||
setNetworks(result);
|
||||
});
|
||||
rssiService.startScanning(2000);
|
||||
setIsScanning(true);
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
rssiService.stopScanning();
|
||||
setIsScanning(false);
|
||||
};
|
||||
}, [enabled]);
|
||||
|
||||
return { networks, isScanning };
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { apiService } from '@/services/api.service';
|
||||
|
||||
interface ServerReachability {
|
||||
reachable: boolean;
|
||||
latencyMs: number | null;
|
||||
}
|
||||
|
||||
const POLL_MS = 10000;
|
||||
|
||||
export function useServerReachability(): ServerReachability {
|
||||
const [state, setState] = useState<ServerReachability>({
|
||||
reachable: false,
|
||||
latencyMs: null,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
let active = true;
|
||||
|
||||
const check = async () => {
|
||||
const started = Date.now();
|
||||
try {
|
||||
await apiService.getStatus();
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
setState({
|
||||
reachable: true,
|
||||
latencyMs: Date.now() - started,
|
||||
});
|
||||
} catch {
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
setState({
|
||||
reachable: false,
|
||||
latencyMs: null,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
void check();
|
||||
const timer = setInterval(check, POLL_MS);
|
||||
|
||||
return () => {
|
||||
active = false;
|
||||
clearInterval(timer);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return state;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { useContext } from 'react';
|
||||
import { ThemeContext, ThemeContextValue } from '../theme/ThemeContext';
|
||||
|
||||
export const useTheme = (): ThemeContextValue => useContext(ThemeContext);
|
||||
Reference in New Issue
Block a user