OH2TH
August 12, 2024, 9:58am
1
I’m in the process of improving syntax checking in my app and eas planning to call the backend to wih Homey.emit() to verify crontab syntax of the input from user while adding new device.
main-driver has:
// Received event for testCronTime
session.setHandler('testCronTime', async (cronTime) => {
this.log(`testCronTime: ${cronTime}`);
// Test cronTime with cron-parser if valid or not
try {
cronParser.parseExpression(cronTime);
this.log(`onPair - testCronTime - pass: ${cronTime}`);
return { success: true };
} catch (err) {
this.error(`onPair - testCronTime - error: ${err.message}`);
return { success: false, error: err.message };
}
});
which is called perfectly from the custom pairing view:
Homey.emit('testCronTime', time)
.then(function (result) {
console.log("Result received:", result);
if (result.success == false) {
Homey.alert(`${Homey.__('settings.error.crontime_invalid')} ${time}: ${result.error}`);
document.getElementById('function_add').classList.remove('is-loading');
return;
}
});
The problem is, that the result is not returned. There is nothing output to the browser developer console.
There is propably something obvious I’m not seeing anymore.
On an side note. Homey.done at
data: {
id: uuid
},
store: {},
settings: {
time,
timezone,
runonce: document.getElementsByName('runonce')[0].checked
}
}).then(function (result) {
Homey.done();
}).catch(function (error) {
Homey.alert(error);
document.getElementById('function_add').classList.remove('is-loading');
});
});
});
</script>
<header class="homey-header">
<h1 class="homey-title" data-i18n="settings.title"><!--settings.title--></h1>
doesn’t seem to get called as it should. At last how Homey SDK documentations says it should. What I get, is that the “configure” view is just loaded again and doesn’t close the pairing session.
Works fine for me:
I assume that the log line is executed?
this.log(`testCronTime: ${cronTime}`);
OH2TH
August 12, 2024, 1:30pm
3
Yep, the log entry is executed.
Need to test with firefox then. Chrome on MacOS is giving me headaches.
I use Brave on macOS, so basically Chrome.
1 Like
OH2TH
August 12, 2024, 2:20pm
5
First time with “bad crontime” string fails as expected an doesn’t proceed to createDevice
2024-08-12T14:06:51.423Z [log] [ManagerDrivers] [Driver:crontime] onPair - new session.
2024-08-12T14:06:52.220Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-12T14:06:57.032Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *adgdfg
2024-08-12T14:06:57.038Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "adg"
Though Homey.alert and the console.log are not executed.
Second test with “bad crontime” fails also, but the device is created:
2024-08-12T14:06:57.601Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-12T14:10:04.979Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *cgkghk
2024-08-12T14:10:04.982Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "cgk"
2024-08-12T14:10:05.131Z [log] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - onInit
2024-08-12T14:10:05.132Z [log] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - setCronTimePattern - not used in this driver!
2024-08-12T14:10:05.132Z [log] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - checkCapabilities for crontime
2024-08-12T14:10:05.133Z [log] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - Found capabilities => [
'is_enabled',
'text_schedule_next',
'text_schedule_date',
'text_schedule_time'
]
2024-08-12T14:10:05.134Z [log] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - Got old capabilities => []
2024-08-12T14:10:05.134Z [log] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - Got new capabilities => []
2024-08-12T14:10:05.134Z [log] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - initCapabilityListeners
2024-08-12T14:10:05.137Z [err] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - getSettingsCronTime - Time = [0 13 * * *cgkghk], Timezone = [Europe/Helsinki] error: Error: Unknown alias: cgk
2024-08-12T14:10:05.138Z [log] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - initCronjob - cronTime: undefined, timeZone: undefined, runOnce: undefined
2024-08-12T14:10:05.139Z [log] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - onInit - done
2024-08-12T14:10:05.139Z [err] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - initCronJob - Time = [undefined], Timezone = [undefined] error: TypeError: Cannot read properties of undefined (reading 'toLowerCase')
2024-08-12T14:10:05.140Z [log] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - onAdded
2024-08-12T14:10:05.147Z [log] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - updateScheduleCapabilityValues - nextRun: object = null
2024-08-12T14:10:05.150Z [log] [ManagerDrivers] [Driver:crontime] [Device:48928246-86ef-45cb-addb-1feceefce465] Crontime 16PXMAk5 - onAdded - done
This should not happen as result.success == false.
There is something that I’m just not seeing now. Tests done now with Chrome and Firefox and same happens.
Backend works as expected, only the fronted drivers/crontime/pair/configure.html’s Homey.emit context is not working as expected.
I would advise rewriting your code so that it uses try/catch
and async/await
instead of .then().catch()
, or at least move this entire block of code to inside the then()
handler, right after this line .
OH2TH
August 13, 2024, 4:42am
7
Would you put both the backend and frontend in try/catch? Tried it already in the backend but couldn’t still get the frontend to behave.
The issue isn’t necessarily with try/catch
, the issue is with the wrong use of promises. Using async/await
would make the code easier to understand, but you’d then need to use try/catch
instead of .catch()
.
OH2TH
August 13, 2024, 6:04am
9
Ah, right. Just following the SDK sample in this one. Though the samples sometimes are also wrong.
So the try/catch in main-driver.js is fine, just need to adjust the pairing configure.html.
OH2TH
August 13, 2024, 7:25am
10
Changed to try/catch and moved createDevice into try-block.
Now I’m seeing random success when crontime passes the test afd the device is created. However Homey.done() is not closing the session / window as everyhting should be ready now.
2024-08-13T07:19:55.706Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *
2024-08-13T07:19:55.707Z [log] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - pass: 0 13 * * *
2024-08-13T07:19:56.257Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-13T07:19:57.138Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *
2024-08-13T07:19:57.138Z [log] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - pass: 0 13 * * *
2024-08-13T07:19:57.732Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-13T07:19:58.581Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *
2024-08-13T07:19:58.584Z [log] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - pass: 0 13 * * *
2024-08-13T07:19:58.774Z [log] [ManagerDrivers] [Driver:crontime] [Device:b3ddad9d-3dc9-4a82-b860-a69532f935e7] Crontime Ye914RyB - onInit
Several times testCronTime pass log entries, and then finally also create the device. only then is also console.log for Crontime is valid printed to Chrome devtools console.
When there is failed testCronTime, no error is reported either in dev console, nor the Homey.alert given. But Console is reporting:
I’m not sure if exceptions thrown inside the event handler in the backend are actually propagated to the frontend.
I would suggest something like this:
// backend
try {
cronParser.parseExpression(cronTime);
this.log(`onPair - testCronTime - pass: ${cronTime}`);
return { success : true, time : cronTime };
} catch (err) {
this.error(`onPair - testCronTime - error: ${err.message}`);
return { success : false };
}
// frontend
const response = await Homey.emit('testCronTime', time);
if (! response.success) { throw Error("...") }
Then when creating the device, you need to await
the call to createDevice
to wait until it’s finished before continuing:
await Homey.createDevice(...);
Homey.done();
OH2TH
August 14, 2024, 3:59am
12
Thank you for your kind help. The code logic kinda works now. However I’m still having an issue where:
// Validate input - Crontime
const time = document.getElementById('crontime').value;
if (time === undefined || time === null || time === '' || !time) {
Homey.alert(Homey.__('settings.error.crontime_invalid'));
document.getElementById('function_add').classList.remove('is-loading');
return;
}
// Test for crontime validity and create device and close session if valid
try {
const response = await Homey.emit('testCronTime', time);
console.log('Response:', response);
if (! response.success) {
throw Error(response.error);
}
console.log('Crontime is valid:', response.time);
// Create device
await Homey.createDevice({
name: name,
data: {
id: uuid
Executes perfectly everythime when “Add scheduler” is clicked. The backend repsonds correctly for pass/fail. But the next line
// Validate input - Crontime
const time = document.getElementById('crontime').value;
if (time === undefined || time === null || time === '' || !time) {
Homey.alert(Homey.__('settings.error.crontime_invalid'));
document.getElementById('function_add').classList.remove('is-loading');
return;
}
// Test for crontime validity and create device and close session if valid
try {
const response = await Homey.emit('testCronTime', time);
console.log('Response:', response);
if (! response.success) {
throw Error(response.error);
}
console.log('Crontime is valid:', response.time);
// Create device
await Homey.createDevice({
name: name,
data: {
id: uuid
},
Is mostly never executed and the code just returns back to the view.
2024-08-14T03:48:46.367Z [log] [ManagerDrivers] [Driver:crontime] onPair - new session.
2024-08-14T03:48:47.564Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:48:55.294Z [log] [ManagerDrivers] [Driver:crontime] onPair - new session.
2024-08-14T03:48:56.107Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:48:58.423Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *
2024-08-14T03:48:58.430Z [log] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - pass: 0 13 * * *
2024-08-14T03:48:59.079Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:07.145Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *
2024-08-14T03:49:07.149Z [log] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - pass: 0 13 * * *
2024-08-14T03:49:07.837Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:08.697Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *
2024-08-14T03:49:08.701Z [log] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - pass: 0 13 * * *
2024-08-14T03:49:09.293Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:10.062Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *
2024-08-14T03:49:10.066Z [log] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - pass: 0 13 * * *
2024-08-14T03:49:10.236Z [log] [ManagerDrivers] [Driver:crontime] [Device:80224e54-2ac4-4b91-8400-3329eb32f862] Crontime bDLmf3L9 - onInit
once the pair session is created it took four clicks until the device is created. And “Homey.done()” is not executed after it, as the window remains open.
Same goes with bad crontime entry, backend tells that the test fails, but frontend takes several tries until it finally does Homey.alert() as expected.
2024-08-14T03:49:10.903Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:18.560Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *dhjdhgj
2024-08-14T03:49:18.562Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "dhj"
2024-08-14T03:49:19.307Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:22.139Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *jhdj
2024-08-14T03:49:22.140Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "jhd"
2024-08-14T03:49:22.803Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:25.710Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *dhjdhgj
2024-08-14T03:49:25.711Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "dhj"
2024-08-14T03:49:26.344Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:29.188Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *djhdhgj
2024-08-14T03:49:29.190Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "djh"
2024-08-14T03:49:29.964Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:32.817Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *dhjgdghj
2024-08-14T03:49:32.818Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "dhj"
2024-08-14T03:49:33.480Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:36.733Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: djhdj0 13 * * *
2024-08-14T03:49:36.734Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Invalid characters, got value: djhdj0
2024-08-14T03:49:37.390Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:41.810Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *dhjdhj
2024-08-14T03:49:41.811Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "dhj"
2024-08-14T03:49:42.469Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:45.472Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *dhjdj
2024-08-14T03:49:45.473Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "dhj"
2024-08-14T03:49:46.144Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:49.346Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *dhgjdhgj
2024-08-14T03:49:49.349Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "dhg"
2024-08-14T03:49:50.061Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:53.340Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *dhjgdhgj
2024-08-14T03:49:53.341Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "dhj"
2024-08-14T03:49:53.984Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:49:57.052Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *dhgjdhgj
2024-08-14T03:49:57.053Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "dhg"
2024-08-14T03:49:57.692Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:50:00.863Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *dhgjdhgj
2024-08-14T03:50:00.864Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "dhg"
2024-08-14T03:50:01.566Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:50:04.654Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *dghjdghj
2024-08-14T03:50:04.655Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "dgh"
2024-08-14T03:50:05.504Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:50:08.285Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 13 * * *dhgjdhgj
2024-08-14T03:50:08.286Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "dhg"
2024-08-14T03:50:08.984Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:50:12.274Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: dgjh
2024-08-14T03:50:12.276Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Validation error, cannot resolve alias "dgj"
2024-08-14T03:50:12.926Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:50:16.552Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: 0 dghj13 * * *
2024-08-14T03:50:16.553Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Invalid characters, got value: dghj13
2024-08-14T03:50:17.198Z [log] [ManagerDrivers] [Driver:crontime] View: configure
2024-08-14T03:50:21.838Z [log] [ManagerDrivers] [Driver:crontime] testCronTime: dhgjjd0 13 * * *
2024-08-14T03:50:21.839Z [err] [ManagerDrivers] [Driver:crontime] onPair - testCronTime - error: Invalid characters, got value: dhgjjd0
2024-08-14T03:50:30.142Z [log] [ManagerDrivers] [Driver:crontime] View: configure
The last err was shown in the console log and Homey.alert() was given.
When I start the app I immediately get an error:
2024-08-14T07:12:57.819Z [log] [ManagerDrivers] [Driver:scheduler] onInit - Driver initialized
unhandledRejection:
TypeError: source.toLowerCase is not a function
at CronTime._parse (/app/node_modules/cron/dist/time.js:360:25)
at new CronTime (/app/node_modules/cron/dist/time.js:37:18)
at new CronJob (/app/node_modules/cron/dist/job.js:25:29)
at AlarmUtils.initAppCronJob (/app/app.js:37:23)
at AlarmUtils.onInit (/app/app.js:21:10)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async SDK._initApp (/node_modules/@athombv/homey-apps-sdk-v3/lib/SDK.js:250:7)
at async SDK.createClient (/node_modules/@athombv/homey-apps-sdk-v3/lib/SDK.js:132:7)
But the main issue is with the HTML of the pairing page: if you don’t set the type of a BUTTON
element, it defaults to being a submit button, and pressing it reloads the page (like submitting a form).
If you explicitly set the type to button
it will not do this:
<button
type="button"
class="homey-button-primary-full"
id="function_add"
data-i18n="settings.function_add"
>
OH2TH
August 14, 2024, 9:10am
14
Started seeing recently toLowerCase errors suddenly from the production version also. Since two days, until then it had been stable.
Updated homey cli and dependencies for the test release.
@robertklep , thank you for spotting the button issue, that was the main problem for all issued I has. As I said, I must be blind already to the code.
Can continue to release the new improved version of the app.