I'm trying to execute a Webcore piston from a Gmail script, but I'm getting a:
Status Code 500
which Google says means an Internal Server Error. Here is the url that I'm trying to execute.
https://cloud.hubitat.com/api/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/apps/469/execute/:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:?access_token=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&command=AtTheRoadMotion
What do I need to do to eliminate the error and to get this piston to run from a Gmail script?
BTW, this url executes fine if I paste it into a browser address line.
I'd turn on Full Logging in webCoRE and see if that gives you anything to work with
I did not see anything in the logs when that call should have happened.
Do I need to do anything in Hubitat and/or Webcore to authorize an external app to run a Webcore piston?
The access_token is the authorization, so that's already there. If you're not seeing anything on the hub, are you sure that it is getting out of GMail?
I agree with thebearmay. It looks like an issue with your Gmail Script. What exactly are you trying to do with that script?
I'm trying to run the piston to indicate to Webcore that I received an email from my security system that a camera detected motion with the arg saying which camera.
You may be right about it being a Gmail problem, although the error that I'm getting says its a error 500 Server Error.
Does your security system allow you make an api call instead of just sending an email? There may be some place where you can put in a URL for the web request. If you had that option you could use Maker API and set a virtual motion sensor active for each camera. I do that now with my camera software when it detects motion.
If you can get the script working, you can also just have your Gmail script send to the api for each virtual motion sensor to go active, but each camera would need to send to a unique device api, but you could probably sort that out in the script.
I finally got the Gmail script to work thanks to Brave's Leo's AI help. The magic was finding the right combination of options to add to the piston's url to get Hubitat and Webcore to accept it. Now, when a motion event is detected by the camera, the NAS does a recording as part of my security system, and it sends an email to a unique GMail address with a Subject that has the camera's name. Then the now-working Gmail script scans the inbox, and when it finds a new email, does a push to the Webcore piston with the camera name as an arg. The piston then processes the push by setting a virtual switch for that camera to indicate motion. This is all based on a Webcore thread from 2020 where Robin detailed the steps to do the Gmail script. Some of the details changed, but the overall structure was his. Thanks Robin!!!
1 Like
Nice! I've never had a situation where email was the only way to send a trigger, but that is a good one for the toolbox. Can you post your Gmail Script?
Just curious, why is the piston setting a virtual switch instead of a virtual motion sensor to indicate motion? There is even an auto-inactive preference in the Hubitat virtual motion sensor.
A virtual motion sensor is probably a better choice. That would eliminate my 2nd piston of causing the switch to go inactive.
As an update, I have moved away from this technique of using email to indicate motion. GMail has a daily limit of 1000 calls to their app. That may sound like a lot, but that's about 42/hour or less than 1 per minute. On a 6 camera system, that is much too low a number. I found on my QNAP NAS that it is just as easy to do a push notification to the Webcore piston as it was to send an email to GMail. So I changed it all to do pushes instead. That technique works just as well as the email technique but without the restriction of the daily limit.
Still, if you wanted to use the email approach, here is the GMail script I used. I use the Subject line of the email to indicate the camera that detected the motion. Additionally, you do need to follow Robin's post on creating the GMail triggers, etc.
function processEmails() {
var maxRetries = 3;
var retryDelay = 1000; // 1 second
var refreshDelay = 5000; // 5 sec
var labeled = GmailApp.getUserLabelByName("Need To Process");
var processedLabel = GmailApp.getUserLabelByName("Processed");
var pistonURL = "ENTER YOUR PISTON'S URL HERE"
if (processedLabel === null) {
GmailApp.createLabel("Processed");
processedLabel = GmailApp.getUserLabelByName("Processed");
}
var threads = labeled.getThreads();
var fetch = UrlFetchApp.fetch;
if (threads.length === 0) {return};
Logger.log('# Threads = ' + threads.length);
var message = threads[0].getMessages()[0];
for (var i = threads.length - 1; i >= 0; i--) {
var command = message.getSubject().trim();
var url = pistonURL + "&command=" +command;
Logger.log('URL: ' + url);
var options = {
"method": "post",
"followRedirects" : false,
"muteHttpExceptions": true,
"headers": {
"Content-Type": "application/json"
},
"payload": JSON.stringify({
"command": command
})
};
var retries = 0;
while (retries < maxRetries) {
var response = UrlFetchApp.fetch(url, options);
Logger.log('Status code: ' + response.getResponseCode());
if (response.getResponseCode() === 200) {
threads[i].addLabel(processedLabel);
threads[i].removeLabel(labeled);
Logger.log('After Add and Remove Labels');
break;
} else {
Logger.log('Error: ' + response.getContentText());
Utilities.sleep(refreshDelay);
retries++;
}
}
if (retries === maxRetries) {
Logger.log('Failed to fetch URL after ' + maxRetries + ' retries.');
} else {
if (retries > 0) {
Logger.log('Number of Retries = ' +retries);
}
}
}
}
Yeah, the push is much better way, glad you got it working!
I'm not sure it is any concern, but after the push to Webcore cloud, it must then push to Hubitat cloud for the switch (or motion) event after that, but one extra hop before getting to the local hub probably isn't doing much. I was thinking you could go direct to the Hubitat API by using a hub variable device, and pushing the camera number to that once it is shared with makerAPI. Then in a Webcore Piston (which is running locally already) , take the camera number in the variable when it changes, and activate the proper virtual switch or motion device. You would have to reset the variable to zero after each push update for it to see repeated motion from the same number camera, but it would all be through Hubitat cloud directly, and then to your hub, without the Webcore cloud in the middle.
There is no push to a webCoRE cloud, goes directly to the Hubitat cloud and is then passed to the webCoRE endpoint requested. (You can also avoid the cloud altogether if all elements are on the local LAN.)
All my devices are local. How would I avoid the cloud?
Use http://<HubIPAddress>/api/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/apps/469/execute/:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:?access_token=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&command=AtTheRoadMotion
instead of the https://cloud.hubitat.com
version.
Thanks for this idea. It's something to play with if this breaks.
BTW, I too started with x10, in around '85 or so, when my wife wanted our outside lite to go on and off while we were traveling. I could have done a mechanical timer but there would have been no fun in that. If you need or want some x10 devices, let me know. I still have my devices that I may try to sell on ebay but would much prefer to part with them to a fellow ex-x10'er.
Ah, I guess it has been a long time since I used a Webcore API link, it does say Hubitat in the link now. My Bad.
Same here. I started with a Radio Shack X10 alarm clock I got for Christmas around '85 or so. The alarm clock would control eight devices. I bought switches, then moved up to the old serial port "hub", then finally to the Active Home USB Hub. Active Home software was amazing to me at the time, I could do so much with those eight boolean flags. Being able to do more complex if-then-else logic. But it was all so slow, so very slow.
I still have two boxes full of X10 stuff, tons of motion sensors, lamp dimmers, switches, two USB hubs, an IR blaster type thing, wireless keychain remotes, wireless wall stick-on switches, and in-wall dimmer switches.
Are the 2 strings the same except for:
http://HubIPAddress/
or
http://cloud.hubitat.com/
For me, the cloud version works but the local version does not, either in my NAS or in a browser.
Also, should there be a port number after the IP address? I tried :8080 but that did not work.
Been a while, but I'm guessing that I forgot a small format change... Let me find it.
Edit : Remember it was similar to the changes in format that MakerAPI needed, try:
http://<HubIPAddress>/apps/api/<appID>/execute/:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:?access_token=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&command=AtTheRoadMotion