{"version":3,"file":"wifi-host.mjs","names":[],"sources":["../../src/hosts/wifi-host.ts"],"sourcesContent":["/* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD */\n/* SPDX-License-Identifier: Apache-2.0 */\n\n/**\n * In-memory BrookesiaHost for Wi-Fi — Node/vitest only, not used on device.\n * Import: `@brookesia/service/hosts/wifi`\n */\n\nimport type { BrookesiaHost } from '../common/brookesia-host.ts';\nimport { serializeRpcError, serializeRpcResult } from '../common/rpc-json.ts';\nimport { WIFI_FUNCTIONS, WIFI_SERVICE_NAME } from '../wifi/wifi-client.ts';\nimport type {\n  WifiConnectApInfo,\n  WifiGeneralAction,\n  WifiGeneralState,\n  WifiScanParams,\n  WifiSoftApParams,\n} from '../wifi/wifi-types.ts';\n\ntype WifiMockState = {\n  generalState: WifiGeneralState;\n  connectAp: WifiConnectApInfo;\n  connectedAps: WifiConnectApInfo[];\n  scanParams: WifiScanParams;\n  scanRunning: boolean;\n  softApParams: WifiSoftApParams;\n  softApRunning: boolean;\n  provisionRunning: boolean;\n};\n\nlet nextHandle = 1;\nconst handles = new Map<number, WifiMockState>();\n\nfunction defaultState(): WifiMockState {\n  return {\n    generalState: 'Idle',\n    connectAp: { ssid: '', password: '' },\n    connectedAps: [],\n    scanParams: { ap_count: 20, interval_ms: 10000, timeout_ms: 60000 },\n    scanRunning: false,\n    softApParams: { ssid: '', password: '', max_connection: 4 },\n    softApRunning: false,\n    provisionRunning: false,\n  };\n}\n\nfunction getState(handle: number): WifiMockState {\n  const state = handles.get(handle);\n  if (!state) {\n    throw new Error(`Wi-Fi memory host: invalid handle ${handle}`);\n  }\n  return state;\n}\n\nfunction applyGeneralAction(state: WifiMockState, action: WifiGeneralAction): void {\n  switch (action) {\n    case 'Init':\n      state.generalState = 'Inited';\n      break;\n    case 'Deinit':\n      state.generalState = 'Idle';\n      state.connectedAps = [];\n      state.scanRunning = false;\n      state.softApRunning = false;\n      state.provisionRunning = false;\n      break;\n    case 'Start':\n      if (state.generalState === 'Inited') {\n        state.generalState = 'Started';\n      }\n      break;\n    case 'Stop':\n      if (state.generalState === 'Started' || state.generalState === 'Connected') {\n        state.generalState = 'Inited';\n        state.connectedAps = [];\n      }\n      break;\n    case 'Connect':\n      if (state.generalState === 'Started' && state.connectAp.ssid) {\n        state.generalState = 'Connected';\n        state.connectedAps = [{ ...state.connectAp }];\n      }\n      break;\n    case 'Disconnect':\n      if (state.generalState === 'Connected') {\n        state.generalState = 'Started';\n        state.connectedAps = [];\n      }\n      break;\n    default:\n      break;\n  }\n}\n\nexport function createWifiHost(initial?: Partial<WifiMockState>): BrookesiaHost {\n  const seed = { ...defaultState(), ...initial };\n\n  return {\n    service_available(name: string): boolean {\n      return name === WIFI_SERVICE_NAME;\n    },\n\n    start_service(name: string): number {\n      if (name !== WIFI_SERVICE_NAME) {\n        throw new Error(`Wi-Fi memory host: unknown service ${name}`);\n      }\n      const handle = nextHandle++;\n      handles.set(handle, {\n        ...defaultState(),\n        connectAp: { ...seed.connectAp },\n        scanParams: { ...seed.scanParams },\n        softApParams: { ...seed.softApParams },\n        generalState: seed.generalState,\n      });\n      return handle;\n    },\n\n    stop_service(handle: number): void {\n      handles.delete(handle);\n    },\n\n    call_function(handle: number, functionName: string, paramsJson: string): string {\n      const state = getState(handle);\n      const params = JSON.parse(paramsJson) as Record<string, unknown>;\n\n      try {\n        if (functionName === WIFI_FUNCTIONS.TriggerGeneralAction) {\n          applyGeneralAction(state, params.Action as WifiGeneralAction);\n          return serializeRpcResult();\n        }\n\n        if (functionName === WIFI_FUNCTIONS.GetGeneralState) {\n          return serializeRpcResult(state.generalState);\n        }\n\n        if (functionName === WIFI_FUNCTIONS.SetConnectAp) {\n          state.connectAp = {\n            ssid: String(params.SSID ?? ''),\n            password: String(params.Password ?? ''),\n            is_connectable: true,\n          };\n          return serializeRpcResult();\n        }\n\n        if (functionName === WIFI_FUNCTIONS.GetConnectAp) {\n          return serializeRpcResult({ ...state.connectAp });\n        }\n\n        if (functionName === WIFI_FUNCTIONS.GetConnectedAps) {\n          return serializeRpcResult([...state.connectedAps]);\n        }\n\n        if (functionName === WIFI_FUNCTIONS.RemoveConnectedAp) {\n          const ssid = String(params.SSID ?? '');\n          state.connectedAps = state.connectedAps.filter((ap) => ap.ssid !== ssid);\n          if (state.connectedAps.length === 0 && state.generalState === 'Connected') {\n            state.generalState = 'Started';\n          }\n          return serializeRpcResult();\n        }\n\n        if (functionName === WIFI_FUNCTIONS.SetScanParams) {\n          state.scanParams = { ...(params.Param as WifiScanParams) };\n          return serializeRpcResult();\n        }\n\n        if (functionName === WIFI_FUNCTIONS.TriggerScanStart) {\n          state.scanRunning = true;\n          return serializeRpcResult();\n        }\n\n        if (functionName === WIFI_FUNCTIONS.TriggerScanStop) {\n          state.scanRunning = false;\n          return serializeRpcResult();\n        }\n\n        if (functionName === WIFI_FUNCTIONS.SetSoftApParams) {\n          state.softApParams = { ...(params.Param as WifiSoftApParams) };\n          return serializeRpcResult();\n        }\n\n        if (functionName === WIFI_FUNCTIONS.GetSoftApParams) {\n          return serializeRpcResult({ ...state.softApParams });\n        }\n\n        if (functionName === WIFI_FUNCTIONS.TriggerSoftApStart) {\n          state.softApRunning = true;\n          return serializeRpcResult();\n        }\n\n        if (functionName === WIFI_FUNCTIONS.TriggerSoftApStop) {\n          state.softApRunning = false;\n          return serializeRpcResult();\n        }\n\n        if (functionName === WIFI_FUNCTIONS.TriggerSoftApProvisionStart) {\n          state.provisionRunning = true;\n          return serializeRpcResult();\n        }\n\n        if (functionName === WIFI_FUNCTIONS.TriggerSoftApProvisionStop) {\n          state.provisionRunning = false;\n          return serializeRpcResult();\n        }\n\n        if (functionName === WIFI_FUNCTIONS.LoadData) {\n          return serializeRpcResult();\n        }\n\n        if (functionName === WIFI_FUNCTIONS.ResetData) {\n          Object.assign(state, defaultState());\n          return serializeRpcResult();\n        }\n\n        return serializeRpcError(`unknown function ${functionName}`);\n      } catch (err) {\n        const message = err instanceof Error ? err.message : String(err);\n        return serializeRpcError(message);\n      }\n    },\n  };\n}\n\nexport function resetWifiHostState(): void {\n  handles.clear();\n  nextHandle = 1;\n}\n"],"mappings":"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"}