Hi, I have an issue that’s been bothering me for a while, and I can’t figure out where the problem might be. I have a Homey Script for controlling the ventilation system. The script works perfectly fine, but when I call the same logic via a method in the Homey app, it returns a 400 error.
Here is the script:
// Test script for ventilation level
const ip = '192.168.68.64';
const minutes = 15;
const level = 2;
async function setVentilationLevel(minutes, level) {
try {
const url = `http://${ip}/JSON/Vars/Ventilation%20timer?index0=0&index1=0&index2=0`;
console.log(`Setting ventilation level: ${level} for ${minutes} minutes`);
console.log(url);
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8',
'Accept': 'application/json, text/plain, */*',
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
'Origin': 'file://',
'Connection': 'keep-alive',
'Accept-Language': 'cs-CZ,cs;q=0.9',
'Accept-Encoding': 'gzip, deflate'
},
body: JSON.stringify({ "Value": `${minutes} min Level${level}` })
});
if (!response.ok) {
throw new Error(`Failed to set ventilation level: ${response.statusText}`);
}
const data = await response.json();
console.log('Ventilation level set successfully:', data);
return data;
} catch (error) {
console.error('Error setting ventilation level:', error);
throw error;
}
}
// Execute the function
setVentilationLevel(minutes, level).catch(err => console.error(err));
Here is the method:
async setVentilationTimer(minutes, level) {
try {
if (minutes < 0 || minutes > 180) {
throw new Error('Minutes must be between 0 and 180');
}
if (level < 1 || level > 4) {
throw new Error('Level must be between 1 and 4');
}
const url = `http://${this.ip}/JSON/Vars/Ventilation%20timer?index0=0&index1=0&index2=0`;
// Exactly the same body construction as in the working script:
const body = JSON.stringify({ "Value": `${minutes} min Level${level}` });
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8',
'Accept': 'application/json, text/plain, */*',
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
'Origin': 'file://',
'Connection': 'keep-alive',
'Accept-Language': 'cs-CZ,cs;q=0.9',
'Accept-Encoding': 'gzip, deflate'
},
body: body // Using the same stringified value
});
if (!response.ok) {
let errorBody = '';
try {
errorBody = await response.text();
} catch (e) {}
console.error('Request details:', {
url,
method: 'POST',
headers: response.headers,
rawBody: body,
error: {
status: response.status,
statusText: response.statusText,
body: errorBody
}
});
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('Success response:', data);
return data;
} catch (error) {
throw error;
}
}
The method is called via a flow card defined in device.js
like this:
// Register Flow Card Ventilation level
this.setVentilationTimerAction = this.homey.flow.getActionCard('set_ventilation_timer');
this.setVentilationTimerAction.registerRunListener(async (args, state) => {
console.log('Flow card triggered with args:', args);
const ip = this.homey.settings.get('endura_ip');
console.log('Using IP:', ip);
const enduraApi = new EnduraApi(ip);
try {
// Log exactly what we're sending
console.log('Calling API with:', {
duration: args.duration,
level: parseInt(args.level),
rawLevel: args.level
});
// Try direct value construction first
const result = await enduraApi.setVentilationTimer(
Number(args.duration), // Ensure it's a number
parseInt(args.level) // Ensure it's a number
);
console.log('API call result:', result);
return true;
} catch (error) {
this.error('Failed to set ventilation timer. Args:', args, 'Error:', error);
throw error;
}
});
Can you help me identify why this works in the script but fails with a 400 error when called through the method?