robovac_auto_initialize
Discover and initialize the first Eufy RoboVac device by providing your account credentials and device index to enable automated control and cleaning functions.
Instructions
Automatically discover and initialize the first RoboVac device found
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| deviceIndex | No | Index of device to connect to (0 for first device) | |
| Yes | Your Eufy account email address | ||
| password | Yes | Your Eufy account password |
Implementation Reference
- src/server.ts:493-577 (handler)Main handler logic for the 'robovac_auto_initialize' tool. Discovers network devices, selects one by index, initializes connection using deviceId/localKey/IP (note: deviceId/localKey fields not present in NetworkDevice interface, possible code issue), falls back to best IP discovery.case "robovac_auto_initialize": try { const devices = await this.networkDiscovery.discoverDevices(); if (devices.length === 0) { return { content: [ { type: "text", text: "No RoboVac devices found.", }, ], isError: true, }; } const deviceIndex = (args?.deviceIndex as number) || 0; if (deviceIndex >= devices.length) { return { content: [ { type: "text", text: `Device index ${deviceIndex} is out of range. Found ${devices.length} device(s).`, }, ], isError: true, }; } const selectedDevice = devices[deviceIndex]; let autoInitSuccess = await this.initializeRoboVac( selectedDevice.deviceId, selectedDevice.localKey, selectedDevice.ip ); // If direct connection fails, try auto-discovery if (!autoInitSuccess) { console.error( "[DEBUG] Cloud connection failed, trying auto-discovery..." ); const discoveredIP = await this.discoverBestRoboVacIP(); if (discoveredIP) { autoInitSuccess = await this.initializeRoboVac( selectedDevice.deviceId, selectedDevice.localKey, discoveredIP ); } } return { content: [ { type: "text", text: autoInitSuccess ? `Successfully connected to ${selectedDevice.name}!` : `Failed to connect to ${selectedDevice.name}. Check network connection and ensure the device is online.`, }, ], isError: !autoInitSuccess, }; } catch (error) { return { content: [ { type: "text", text: `Auto-initialization failed: ${ (error as Error).message } ⚠️ The Eufy API appears to have changed since this implementation was created. As an alternative, you can: 1. Use the Eufy app to find your device IP address 2. Use a network scanner to find devices on your network 3. Check your router's device list 4. Use tools like eufy-security-client or other community projects Once you have the device credentials, you can use the eufy-robovac library directly.`, }, ], isError: true, }; }
- src/server.ts:273-295 (schema)Schema and registration of the 'robovac_auto_initialize' tool in the ListTools response, defining input parameters including email, password (though not used in handler), and deviceIndex.name: "robovac_auto_initialize", description: "Automatically discover and initialize the first RoboVac device found", inputSchema: { type: "object", properties: { email: { type: "string", description: "Your Eufy account email address", }, password: { type: "string", description: "Your Eufy account password", }, deviceIndex: { type: "number", description: "Index of device to connect to (0 for first device)", default: 0, }, }, required: ["email", "password"], },
- src/server.ts:43-59 (helper)Helper method called by the handler to create and connect a new RoboVac instance.private async initializeRoboVac( deviceId: string, localKey: string, ip?: string ): Promise<boolean> { try { this.robovac = new RoboVac({ deviceId: deviceId, localKey: localKey, ip: ip || "192.168.1.100", }); await this.robovac.connect(); return true; } catch (error) { console.error("Failed to initialize RoboVac:", error); return false; }
- src/server.ts:70-111 (helper)Fallback helper to discover the best IP for RoboVac connection when direct init fails.private async discoverBestRoboVacIP(): Promise<string | null> { try { console.error("[DEBUG] Auto-discovering RoboVac devices..."); const devices = await this.networkDiscovery.discoverDevices(); if (devices.length === 0) { console.error("[DEBUG] No devices found during auto-discovery"); return null; } // Filter for likely RoboVac devices const likelyRoboVacs = devices.filter((device) => device.isLikelyRoboVac); if (likelyRoboVacs.length > 0) { const bestDevice = likelyRoboVacs[0]; // Take the first likely device console.error( `[DEBUG] Found likely RoboVac at ${bestDevice.ip} (MAC: ${bestDevice.mac}, Vendor: ${bestDevice.vendor})` ); return bestDevice.ip; } // If no likely RoboVacs, try devices with port 6668 open const devicesWithPort6668 = devices.filter((device) => device.ports.includes(6668) ); if (devicesWithPort6668.length > 0) { const potentialDevice = devicesWithPort6668[0]; console.error( `[DEBUG] Found potential RoboVac at ${potentialDevice.ip} with port 6668 open` ); return potentialDevice.ip; } console.error("[DEBUG] No suitable RoboVac candidates found"); return null; } catch (error) { console.error( `[DEBUG] Auto-discovery failed: ${(error as Error).message}` ); return null; }
- src/network-discovery.ts:149-233 (helper)Core helper from imported NetworkDiscovery class: scans local network for potential RoboVac devices via ping, port scan, MAC vendor check. Used by handler to find devices.async discoverDevices(): Promise<NetworkDevice[]> { console.error("[DEBUG] Starting local network discovery..."); const networkRange = this.getLocalNetworkRange(); console.error(`[DEBUG] Scanning network range: ${networkRange}`); // Get current ARP table const arpTable = await this.getArpTable(); console.error(`[DEBUG] Found ${arpTable.size} devices in ARP table`); // Generate IP range to scan const baseIp = networkRange.split("/")[0]; const ipParts = baseIp.split("."); const ips: string[] = []; // Scan common ranges more efficiently for (let i = 1; i < 255; i++) { ips.push(`${ipParts[0]}.${ipParts[1]}.${ipParts[2]}.${i}`); } const devices: NetworkDevice[] = []; const batchSize = 20; // Process IPs in batches to avoid overwhelming the network for (let i = 0; i < ips.length; i += batchSize) { const batch = ips.slice(i, i + batchSize); const batchPromises = batch.map(async (ip) => { // First check if device responds to ping const isAlive = await this.pingHost(ip); if (!isAlive) return null; console.error(`[DEBUG] Device found at ${ip}, checking ports...`); // Check Tuya/Eufy ports const portResults = await Promise.all( this.TUYA_PORTS.map((port) => this.scanPort(ip, port, 500)) ); const openPorts = this.TUYA_PORTS.filter( (port, index) => portResults[index] ); if (openPorts.length === 0) return null; const mac = arpTable.get(ip); const isAnkerDevice = mac ? this.isAnkerEufyDevice(mac) : false; const device: NetworkDevice = { ip, mac, vendor: isAnkerDevice ? "Anker/Eufy" : undefined, ports: openPorts, isLikelyRoboVac: isAnkerDevice && openPorts.includes(6668), }; console.error(`[DEBUG] Potential device: ${JSON.stringify(device)}`); return device; }); const batchResults = await Promise.all(batchPromises); const validDevices = batchResults.filter( (device): device is NetworkDevice => device !== null ); devices.push(...validDevices); // Progress indicator console.error( `[DEBUG] Scanned ${Math.min(i + batchSize, ips.length)}/${ ips.length } IPs...` ); } // Sort by likelihood of being a RoboVac devices.sort((a, b) => { if (a.isLikelyRoboVac && !b.isLikelyRoboVac) return -1; if (!a.isLikelyRoboVac && b.isLikelyRoboVac) return 1; return 0; }); console.error( `[DEBUG] Network discovery complete. Found ${devices.length} potential devices` ); return devices; }