YES:
- Vercel Serverless Function: Homey Cloud API Proxy (FIXED v2)
- This version uses the ACTUAL homey-api library (same as setup-homey.js)
- but with optimizations for serverless environments
- Environment variables required in Vercel:
-
-
-
- HOMEY_USERNAME (your Homey account email)
-
- HOMEY_PASSWORD (your Homey account password)
-
- HOMEY_DEVICE_ID_TEMP (outdoor temperature sensor)
-
- HOMEY_DEVICE_ID_HUMIDITY (outdoor humidity sensor, optional)
*/
const AthomCloudAPI = require(‘homey-api/lib/AthomCloudAPI’);
// Cache for Homey API session (persists across function invocations in same container)
let cachedHomeyApi = null;
let cacheTimestamp = null;
const CACHE_DURATION = 30 * 60 * 1000; // 30 minutes (conservative for serverless)
/**
- Get authenticated Homey API with retry logic
*/
async function getHomeyApiWithRetry(maxRetries = 2) {
const now = Date.now();
// Return cached connection if still valid
if (cachedHomeyApi && cacheTimestamp && (now - cacheTimestamp) < CACHE_DURATION) {
console.log(‘
Using cached Homey API session’);
try {
// Quick test to ensure session is still valid
await cachedHomeyApi.system.getInfo();
return cachedHomeyApi;
} catch (error) {
console.warn(‘
Cached session invalid, re-authenticating…’);
cachedHomeyApi = null;
cacheTimestamp = null;
}
}
console.log(‘
Authenticating with Homey Cloud API…’);
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
// Create Cloud API instance (same as setup-homey.js)
const cloudApi = new AthomCloudAPI({
clientId: process.env.HOMEY_CLIENT_ID,
clientSecret: process.env.HOMEY_CLIENT_SECRET,
});
console.log(`Attempt ${attempt}/${maxRetries}: Calling authenticateWithPassword...`);
// Authenticate with username/password
// Wrap in a promise with timeout
await Promise.race([
cloudApi.authenticateWithPassword(
process.env.HOMEY_USERNAME,
process.env.HOMEY_PASSWORD
),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Authentication timeout after 25 seconds')), 25000)
)
]);
console.log('✅ Authentication successful, getting user...');
// Get user and Homey
const user = await Promise.race([
cloudApi.getAuthenticatedUser(),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Get user timeout after 10 seconds')), 10000)
)
]);
console.log('✅ User retrieved, getting Homey...');
const homey = await Promise.race([
user.getFirstHomey(),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Get Homey timeout after 10 seconds')), 10000)
)
]);
console.log('✅ Homey found, creating session...');
// Create session on Homey
const homeyApi = await Promise.race([
homey.authenticate(),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Session creation timeout after 15 seconds')), 15000)
)
]);
console.log('✅ Homey API session created successfully');
// Cache the session
cachedHomeyApi = homeyApi;
cacheTimestamp = now;
return homeyApi;
} catch (error) {
console.error(`❌ Attempt ${attempt}/${maxRetries} failed:`, error.message);
if (attempt === maxRetries) {
throw new Error(`Authentication failed after ${maxRetries} attempts: ${error.message}`);
}
// Wait before retry (exponential backoff)
const waitTime = Math.min(1000 * Math.pow(2, attempt - 1), 5000);
console.log(`⏳ Waiting ${waitTime}ms before retry...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
}
}
throw new Error(‘Authentication failed: Max retries exceeded’);
}