303 lines
7.6 KiB
JavaScript
303 lines
7.6 KiB
JavaScript
// Pose Service for WiFi-DensePose UI
|
|
|
|
import { API_CONFIG } from '../config/api.config.js';
|
|
import { apiService } from './api.service.js';
|
|
import { wsService } from './websocket.service.js';
|
|
|
|
export class PoseService {
|
|
constructor() {
|
|
this.streamConnection = null;
|
|
this.eventConnection = null;
|
|
this.poseSubscribers = [];
|
|
this.eventSubscribers = [];
|
|
}
|
|
|
|
// Get current pose estimation
|
|
async getCurrentPose(options = {}) {
|
|
const params = {
|
|
zone_ids: options.zoneIds?.join(','),
|
|
confidence_threshold: options.confidenceThreshold,
|
|
max_persons: options.maxPersons,
|
|
include_keypoints: options.includeKeypoints,
|
|
include_segmentation: options.includeSegmentation
|
|
};
|
|
|
|
// Remove undefined values
|
|
Object.keys(params).forEach(key =>
|
|
params[key] === undefined && delete params[key]
|
|
);
|
|
|
|
return apiService.get(API_CONFIG.ENDPOINTS.POSE.CURRENT, params);
|
|
}
|
|
|
|
// Analyze pose (requires auth)
|
|
async analyzePose(request) {
|
|
return apiService.post(API_CONFIG.ENDPOINTS.POSE.ANALYZE, request);
|
|
}
|
|
|
|
// Get zone occupancy
|
|
async getZoneOccupancy(zoneId) {
|
|
const endpoint = API_CONFIG.ENDPOINTS.POSE.ZONE_OCCUPANCY.replace('{zone_id}', zoneId);
|
|
return apiService.get(endpoint);
|
|
}
|
|
|
|
// Get zones summary
|
|
async getZonesSummary() {
|
|
return apiService.get(API_CONFIG.ENDPOINTS.POSE.ZONES_SUMMARY);
|
|
}
|
|
|
|
// Get historical data (requires auth)
|
|
async getHistoricalData(request) {
|
|
return apiService.post(API_CONFIG.ENDPOINTS.POSE.HISTORICAL, request);
|
|
}
|
|
|
|
// Get recent activities
|
|
async getActivities(options = {}) {
|
|
const params = {
|
|
zone_id: options.zoneId,
|
|
limit: options.limit || 50
|
|
};
|
|
|
|
// Remove undefined values
|
|
Object.keys(params).forEach(key =>
|
|
params[key] === undefined && delete params[key]
|
|
);
|
|
|
|
return apiService.get(API_CONFIG.ENDPOINTS.POSE.ACTIVITIES, params);
|
|
}
|
|
|
|
// Calibrate system (requires auth)
|
|
async calibrate() {
|
|
return apiService.post(API_CONFIG.ENDPOINTS.POSE.CALIBRATE);
|
|
}
|
|
|
|
// Get calibration status (requires auth)
|
|
async getCalibrationStatus() {
|
|
return apiService.get(API_CONFIG.ENDPOINTS.POSE.CALIBRATION_STATUS);
|
|
}
|
|
|
|
// Get pose statistics
|
|
async getStats(hours = 24) {
|
|
return apiService.get(API_CONFIG.ENDPOINTS.POSE.STATS, { hours });
|
|
}
|
|
|
|
// Start pose stream
|
|
startPoseStream(options = {}) {
|
|
if (this.streamConnection) {
|
|
console.warn('Pose stream already active');
|
|
return this.streamConnection;
|
|
}
|
|
|
|
const params = {
|
|
zone_ids: options.zoneIds?.join(','),
|
|
min_confidence: options.minConfidence || 0.5,
|
|
max_fps: options.maxFps || 30,
|
|
token: options.token || apiService.authToken
|
|
};
|
|
|
|
// Remove undefined values
|
|
Object.keys(params).forEach(key =>
|
|
params[key] === undefined && delete params[key]
|
|
);
|
|
|
|
this.streamConnection = wsService.connect(
|
|
API_CONFIG.ENDPOINTS.STREAM.WS_POSE,
|
|
params,
|
|
{
|
|
onOpen: () => {
|
|
console.log('Pose stream connected');
|
|
this.notifyPoseSubscribers({ type: 'connected' });
|
|
},
|
|
onMessage: (data) => {
|
|
this.handlePoseMessage(data);
|
|
},
|
|
onError: (error) => {
|
|
console.error('Pose stream error:', error);
|
|
this.notifyPoseSubscribers({ type: 'error', error });
|
|
},
|
|
onClose: () => {
|
|
console.log('Pose stream disconnected');
|
|
this.streamConnection = null;
|
|
this.notifyPoseSubscribers({ type: 'disconnected' });
|
|
}
|
|
}
|
|
);
|
|
|
|
return this.streamConnection;
|
|
}
|
|
|
|
// Stop pose stream
|
|
stopPoseStream() {
|
|
if (this.streamConnection) {
|
|
wsService.disconnect(this.streamConnection);
|
|
this.streamConnection = null;
|
|
}
|
|
}
|
|
|
|
// Subscribe to pose updates
|
|
subscribeToPoseUpdates(callback) {
|
|
this.poseSubscribers.push(callback);
|
|
|
|
// Return unsubscribe function
|
|
return () => {
|
|
const index = this.poseSubscribers.indexOf(callback);
|
|
if (index > -1) {
|
|
this.poseSubscribers.splice(index, 1);
|
|
}
|
|
};
|
|
}
|
|
|
|
// Handle pose stream messages
|
|
handlePoseMessage(data) {
|
|
const { type, payload } = data;
|
|
|
|
switch (type) {
|
|
case 'pose_data':
|
|
this.notifyPoseSubscribers({
|
|
type: 'pose_update',
|
|
data: payload
|
|
});
|
|
break;
|
|
|
|
case 'historical_data':
|
|
this.notifyPoseSubscribers({
|
|
type: 'historical_update',
|
|
data: payload
|
|
});
|
|
break;
|
|
|
|
case 'zone_statistics':
|
|
this.notifyPoseSubscribers({
|
|
type: 'zone_stats',
|
|
data: payload
|
|
});
|
|
break;
|
|
|
|
case 'system_event':
|
|
this.notifyPoseSubscribers({
|
|
type: 'system_event',
|
|
data: payload
|
|
});
|
|
break;
|
|
|
|
default:
|
|
console.log('Unknown pose message type:', type);
|
|
}
|
|
}
|
|
|
|
// Notify pose subscribers
|
|
notifyPoseSubscribers(update) {
|
|
this.poseSubscribers.forEach(callback => {
|
|
try {
|
|
callback(update);
|
|
} catch (error) {
|
|
console.error('Error in pose subscriber:', error);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Start event stream
|
|
startEventStream(options = {}) {
|
|
if (this.eventConnection) {
|
|
console.warn('Event stream already active');
|
|
return this.eventConnection;
|
|
}
|
|
|
|
const params = {
|
|
event_types: options.eventTypes?.join(','),
|
|
zone_ids: options.zoneIds?.join(','),
|
|
token: options.token || apiService.authToken
|
|
};
|
|
|
|
// Remove undefined values
|
|
Object.keys(params).forEach(key =>
|
|
params[key] === undefined && delete params[key]
|
|
);
|
|
|
|
this.eventConnection = wsService.connect(
|
|
API_CONFIG.ENDPOINTS.STREAM.WS_EVENTS,
|
|
params,
|
|
{
|
|
onOpen: () => {
|
|
console.log('Event stream connected');
|
|
this.notifyEventSubscribers({ type: 'connected' });
|
|
},
|
|
onMessage: (data) => {
|
|
this.handleEventMessage(data);
|
|
},
|
|
onError: (error) => {
|
|
console.error('Event stream error:', error);
|
|
this.notifyEventSubscribers({ type: 'error', error });
|
|
},
|
|
onClose: () => {
|
|
console.log('Event stream disconnected');
|
|
this.eventConnection = null;
|
|
this.notifyEventSubscribers({ type: 'disconnected' });
|
|
}
|
|
}
|
|
);
|
|
|
|
return this.eventConnection;
|
|
}
|
|
|
|
// Stop event stream
|
|
stopEventStream() {
|
|
if (this.eventConnection) {
|
|
wsService.disconnect(this.eventConnection);
|
|
this.eventConnection = null;
|
|
}
|
|
}
|
|
|
|
// Subscribe to events
|
|
subscribeToEvents(callback) {
|
|
this.eventSubscribers.push(callback);
|
|
|
|
// Return unsubscribe function
|
|
return () => {
|
|
const index = this.eventSubscribers.indexOf(callback);
|
|
if (index > -1) {
|
|
this.eventSubscribers.splice(index, 1);
|
|
}
|
|
};
|
|
}
|
|
|
|
// Handle event stream messages
|
|
handleEventMessage(data) {
|
|
this.notifyEventSubscribers({
|
|
type: 'event',
|
|
data
|
|
});
|
|
}
|
|
|
|
// Notify event subscribers
|
|
notifyEventSubscribers(update) {
|
|
this.eventSubscribers.forEach(callback => {
|
|
try {
|
|
callback(update);
|
|
} catch (error) {
|
|
console.error('Error in event subscriber:', error);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Update stream configuration
|
|
updateStreamConfig(connectionId, config) {
|
|
wsService.sendCommand(connectionId, 'update_config', config);
|
|
}
|
|
|
|
// Get stream status
|
|
requestStreamStatus(connectionId) {
|
|
wsService.sendCommand(connectionId, 'get_status');
|
|
}
|
|
|
|
// Clean up
|
|
dispose() {
|
|
this.stopPoseStream();
|
|
this.stopEventStream();
|
|
this.poseSubscribers = [];
|
|
this.eventSubscribers = [];
|
|
}
|
|
}
|
|
|
|
// Create singleton instance
|
|
export const poseService = new PoseService(); |