import { request } from './api' import { loadCurrentChildBindingContext } from './binding' export interface DeviceStatus { device_id: string child_id?: number | null child_name?: string | null sleep_mode?: number | null manual_sleep_mode?: number | null schedule_suppressed_until?: string | null disable_time_start?: string | null disable_time_end?: string | null timezone?: string | null power?: number | null volume?: number | null signal?: number | null version?: string | null settings_updated_at?: string | null coord_type?: string | null lat?: number | null lng?: number | null accuracy_m?: number | null altitude_m?: number | null speed_mps?: number | null heading_deg?: number | null source?: number | null battery_pct?: number | null device_time?: string | null server_time?: string | null location_updated_at?: string | null } export interface DeviceOnlineStatus { device_id: string online: boolean reason: string message: string last_location_at?: string | null checked_at: string } export interface DeviceAlarmItem { alarm_id: number device_id: string child_id?: number | null child_name?: string | null source_msg_id: string coord_type?: string | null lat?: number | null lng?: number | null location_updated_at?: string | null location_stale?: boolean address?: string | null address_resolved_at?: string | null address_resolve_status?: number | null created_at: string } export interface DeviceAlarmListResponse { items: DeviceAlarmItem[] total: number } export interface DeviceVolumeUpdateResponse { device_id: string level: number msg_id: string } export interface DeviceSleepScheduleUpdateResponse { device_id: string sleep_mode: number start?: string | null end?: string | null timezone: string msg_id?: string | null } export interface DeviceRemoteSleepWakeResponse { device_id: string switch: 'on' | 'off' msg_id: string } export interface DeviceFirmwareStatus { device_id: string current_version?: string | null latest_version?: string | null update_available: boolean can_update: boolean update_status: string progress: number target_version?: string | null updated_at?: string | null } export interface DeviceFirmwareUpdateResponse extends DeviceFirmwareStatus { msg_id: string } export interface DeviceRoleSummary { role_key: string name: string description?: string | null default_language?: string | null languages: string[] } export interface DeviceCurrentRole { device_id: string role_key: string name: string description?: string | null preferred_language?: string | null languages: string[] } function normalizeTimeValue(value?: string | null): string | null { if (value === null || value === undefined) return null const trimmed = String(value).trim() if (!trimmed) return null const matched = trimmed.match(/^(\d{1,2}):(\d{2})(?::\d{2})?:?$/) if (!matched) return trimmed.replace(/:+$/, '') const hour = matched[1].padStart(2, '0') return `${hour}:${matched[2]}` } function normalizeDeviceStatus(status: DeviceStatus): DeviceStatus { return { ...status, disable_time_start: normalizeTimeValue(status.disable_time_start), disable_time_end: normalizeTimeValue(status.disable_time_end), } } async function resolveDeviceId(deviceId?: string): Promise { const normalizedDeviceId = String(deviceId || '').trim() if (normalizedDeviceId) return normalizedDeviceId const context = await loadCurrentChildBindingContext() return context.currentBinding?.device_id || '' } export async function getDeviceStatus(deviceId?: string): Promise { const resolvedDeviceId = await resolveDeviceId(deviceId) if (!resolvedDeviceId) return null try { const result = await request(`/banban/devices/${resolvedDeviceId}/status`) return normalizeDeviceStatus(result) } catch (error: any) { if (error?.status === 404) return null throw error } } export async function getDeviceOnlineStatus(deviceId?: string): Promise { const resolvedDeviceId = await resolveDeviceId(deviceId) if (!resolvedDeviceId) return null try { return await request(`/banban/devices/${resolvedDeviceId}/online-status`) } catch (error: any) { if (error?.status === 404) return null throw error } } export async function setDeviceVolume(level: number, deviceId?: string): Promise { const resolvedDeviceId = await resolveDeviceId(deviceId) if (!resolvedDeviceId) { throw new Error('当前没有可用设备') } return request(`/banban/devices/${resolvedDeviceId}/volume`, { method: 'POST', data: { level }, }) } export async function setDeviceSleepSchedule( start: string, end: string, timezone = 'Asia/Shanghai', deviceId?: string ): Promise { const resolvedDeviceId = await resolveDeviceId(deviceId) if (!resolvedDeviceId) { throw new Error('当前没有可用设备') } const result = await request(`/banban/devices/${resolvedDeviceId}/sleep-schedule`, { method: 'POST', data: { start, end, timezone }, }) return { ...result, start: normalizeTimeValue(result.start), end: normalizeTimeValue(result.end), } } export async function setDeviceRemoteSleepWake( switchValue: 'on' | 'off', deviceId?: string ): Promise { const resolvedDeviceId = await resolveDeviceId(deviceId) if (!resolvedDeviceId) { throw new Error('当前没有可用设备') } return request(`/banban/devices/${resolvedDeviceId}/sleep-wake`, { method: 'POST', data: { switch: switchValue }, }) } export async function getDeviceFirmwareStatus(deviceId?: string): Promise { const resolvedDeviceId = await resolveDeviceId(deviceId) if (!resolvedDeviceId) return null try { return await request(`/banban/devices/${resolvedDeviceId}/firmware`) } catch (error: any) { if (error?.status === 404) return null throw error } } export async function startDeviceFirmwareUpdate(deviceId?: string): Promise { const resolvedDeviceId = await resolveDeviceId(deviceId) if (!resolvedDeviceId) { throw new Error('当前没有可用设备') } return request(`/banban/devices/${resolvedDeviceId}/firmware/update`, { method: 'POST', }) } export async function getDeviceAlarms( deviceId?: string, limit = 20 ): Promise { const resolvedDeviceId = await resolveDeviceId(deviceId) if (!resolvedDeviceId) { return { items: [], total: 0 } } return request(`/banban/devices/${resolvedDeviceId}/alarms?limit=${limit}`) } export async function getDeviceRoles(): Promise { return request('/banban/roles') } export async function getDeviceRole(deviceId?: string): Promise { const resolvedDeviceId = await resolveDeviceId(deviceId) if (!resolvedDeviceId) return null try { return await request(`/banban/roles/devices/${resolvedDeviceId}`) } catch (error: any) { if (error?.status === 404) return null throw error } } export async function updateDeviceRole( roleKey: string, language?: string | null, deviceId?: string, playWelcome = false ): Promise { const resolvedDeviceId = await resolveDeviceId(deviceId) if (!resolvedDeviceId) { throw new Error('当前没有可用设备') } return request(`/banban/roles/devices/${resolvedDeviceId}`, { method: 'PUT', data: { role_key: roleKey, language: language || undefined, play_welcome: playWelcome, }, }) }