Nest API Query - Control of system from Intruder Alarm - nest-api

I'm considering the purchase of a Nest and have some thoughts in relation to the API capabilities. I have a intruder/security alarm with PIRs around the house. What I intend to do is to develop an interface between this system and Nest via the API.
My reasoning for this is to use the motion detection from the alarms PIR sensors to 'inform' Nest that someone is still on the premises (due to their movement) and hence prevent Nest switching to its Auto-Away state when the house is inhabited.
Also when the house is armed in away-mode I would want Nest to enter Auto-Away state immediately.
So what I'd like to know is whether it's possible to do the following via the API:
1) Keep/switch Nest in/to the Home
2) Place Nest in the Auto-Away state
Cheers Ian

You can switch Nest to Away, or to Home, but you cannot control Auto-Away. In my experience Auto-Away is probably not what you want anyway, as Nest seems to drop out of Auto-Away mode every time it crosses a scheduled heating/cooling etc event.
This is exactly how I use the API - to set the Nest to Away whenever the alarm is set, and to Home whenever the alarm is unset.

I came across this with the same question about using my security alarm motion detector (which I already have a monitor for) to let the Nest know someone is home. It seems Nest partners with other companies which can feed Nest activity data but there is nothing about this in the API.
I also have a script which sets Nest to away mode as soon as the alarm is armed, it is easily doable with the published API.
Here is my REST JavaScript function to set Nest to home/away mode, excuse my poor JavaScript (I'm a noob).
// Turn on/off away mode based on true/false parameter
function setAway(doAway) {
var url = "https://developer-api.nest.com/structures/"+myNest.struct+"?auth="+myNest.auth;
if (doAway) {
var newState = "away";
} else {
var newState = "home";
}
var nowAway = isAway();
var options = {
method: "put",
contentType: "application/json",
accept: "application/json",
payload: '{"away":"'+newState+'"}'
};
// only update if state changed
if (doAway != nowAway) {
var response = UrlFetchApp.fetch(url, options);
var data = JSON.parse(response);
}
}

Related

How to add a custom dimension to request telemetry in a Nodejs/typescript azure function?

Goal
A request comes in and is handled by the Azure Functions run-time. By default it creates a Request entry, and a bunch of Trace entries in Application Insights. I want to add a custom dimension to that top level request item (on a per-request basis) so I can use it for filtering/analysis later.
Query for -requests- on Application Insights
Resulting list of requests including custom dimensions column
The Azure Functions runtime adds a few custom dimensions already. I want to add a few of my own.
Approach
The most promising approach I've found is show below (taken from here https://github.com/microsoft/ApplicationInsights-node.js/issues/392)
appInsights.defaultClient.addTelemetryProcessor(( envelope, context ) => {
var data = envelope.data.baseData;
data.properties['mykey'] = 'myvalue';
return true;
});
However, I find that this processor is only called for requests that I initialise within my function. For example, if I make an HTTP request to another service, then details of that request will be passed thru the processor and I can add custom properties to it. But the main function does not seem to pass thru here. So I can't add my custom property.
I also tried this
defaultClient.commonProperties['anotherCustomProp'] = 'bespokeProp2'
Same problem. The custom property doesn't arrive in application insights. I've played with many variations on this and it appears that the logging done by azure-functions is walled off from anything I can do within my code.
The best workaround I have right now, is to call trackRequest manually. This is okay, except I end up with each request logged twice in application insights, one by the framework and one by me. And both need to have the same operation_id otherwise I can't find the associated trace/error items. So I'm having to extract the operationId in a slightly hacky way. This may be fine, my knowledge of application insights is pretty naive at this point.
import { setup, defaultClient } from 'applicationinsights' // i have to import the specific functions, because "import ai from applicationinsights" returns null
// call this because otherwise defaultClient is null.
// Some examples call start(), I've tried with and without this.
// I think the start() function must be useful when you're adding application-insights to a project fresh, whereas I think the azure-functions run-time must be doing this already.
setup()
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
// Extract the operation id from the traceparent as per w3 standard https://www.w3.org/TR/trace-context/.
const operationId = context.traceContext.traceparent.split('-')[1]
var operationIdOverride = { 'ai.operation.id': operationId }
// Create my own trackRequest entry
defaultClient.trackRequest({
name: 'my func name',
url: context.req.url.split('?')[0],
duration: 123,
resultCode: 200,
success: true,
tagOverrides: operationIdOverride,
properties: {
customProp: 'bespokeProp'
}
})
The Dream
Our C# cousins seem to have an array of options, like Activity.Current.tags and the ability to add TelemetryInitializer. However it looks like what I'm trying to do is supported, I'm just not finding the right combination of commands! Is there something similar for javascript/typescript/nodejs, where I can just add a tag on a per-request basis? Along the lines of context.traceContext.attributes['myprop'] = 'myValue'
Alternative
Alternatively, instrumenting my code using my own TelemetryClient (rather than the defaultClient) using trackRequest, trackTrace, trackError etc, is not a very big job and should work well - that would be more explicit. Should I just do that? Is there a way to disable the azure functions tracking - or perhaps I just leave that as something running side-by-side.

Fluid clients get out of sync when server is rebooted

I got the HelloWorld example to run fine. But once I stopped & restarted the server the clients got out of sync--even when I set a consistent document (i.e. location.hash = "12345").
Setting createNew=false broke the app (no dice--literally).
And I get a lot of repeating errors:
[start:server] error: Connect Document error: {} {"messageMetaData":{"documentId":"1608237690408","tenantId":"tinylicious"},"label":"winston","timestamp":"2020-12-17T20:45:13.160Z"}
[start:server] info: Disconnect of 60c72737-3e05-4bc7-bf9b-f7ca6439a431 from room {"messageMetaData":{"documentId":"1608237690408","tenantId":"tinylicious"},"label":"winston","timestamp":"2020-12-17T20:45:13.161Z"}
Does Fluid support this scenario? Or am I doing something wrong?
The tinylicious service could support turning off & on with durable data, but it's really meant to be a test service. When you restart the service, you'll probably want to pick a new documentID.
createNew is a more interesting story. The Hello World application is somewhat contrived example. In general, the app developer will get a signal from the user that a new document should be created. Think about Google Docs.
"Create New Google Doc" -> createNew === true
"Open existing Google Doc" -> createNew === false
However, for the Hello World scenario, we want to have as little code as possible. We certainly don't want to write out a whole document management schema. So we rely on a nifty little trick: If you paste in a URL with a specific documentID we assume you are loading an existing document, otherwise we will make a new one for you.
That's what the below is doing!
You'll see the effects in the URLs, which look something like this: http://localhost:8080/#1608592296522
let createNew = false;
if (location.hash.length === 0) {
createNew = true;
location.hash = Date.now().toString();
}
const documentId = location.hash.substring(1);
document.title = documentId;

Can I trigger the Hololens Calibration sequence from inside my application?

I have a hololens app I am creating that requires the best accuracy possible for hologram placement. This application will be used by numerous individuals. Whenever I try to show the application progress, I have to have the user go through the calibration process, otherwise the holograms appear to have way too much drift.
I would like to be able to call the hololens calibration process automatically when the application opens. Later, after I set up user authentication and id management, I will call the calibration process when a new user is found.
https://learn.microsoft.com/en-us/windows/mixed-reality/calibration
I have looked into the calibration (via the above documentation and elsewhere) and it seems that all it is setting is IPD. However the alternative solutions I have found that allow for dynamic ipd adjustment appear to be invalid for UWP Store apps. This makes them unusable for me.
I am looking for any help or direction, or if this is even possible. Thank you.
Yes, it is possible to to this, you need to use the LaunchUriAsync protocol to launch the following URI: ms-hololenssetup://EyeTracking
Here is an example implementation, obtained from the LaunchUri example in MRTK
public void LaunchEyeTracking()
{
#if WINDOWS_UWP
UnityEngine.WSA.Application.InvokeOnUIThread(async () =>
{
bool result = await global::Windows.System.Launcher.LaunchUriAsync(new System.Uri("ms-hololenssetup://EyeTracking"));
if (!result)
{
Debug.LogError("Launching URI failed to launch.");
}
}, false);
#else
Debug.LogError("Launching eye tracking not supported Windows UWP");
#endif
}

Potentially vulnerability using setInterval in Firefox addon?

I've written a Firefox addon for the first time and it was reviewed and accepted a few month ago. This add-on calls frequently a third-party API. Meanwhile it was reviewed again and now the way it calls setInterval is criticized:
setInterval called in potentially dangerous manner. In order to prevent vulnerabilities, the setTimeout and setInterval functions should be called only with function expressions as their first argument. Variables referencing function names are acceptable but deprecated as they are not amenable to static source validation.
Here's some background about the »architecture« of my addon. It uses a global Object which is not much more than a namespace:
if ( 'undefined' == typeof myPlugin ) {
var myPlugin = {
//settings
settings : {},
intervalID : null,
//called once on window.addEventlistener( 'load' )
init : function() {
//load settings
//load remote data from cache (file)
},
//get the data from the API
getRemoteData : function() {
// XMLHttpRequest to the API
// retreve data (application/json)
// write it to a cache file
}
}
//start
window.addEventListener(
'load',
function load( event ) {
window.removeEventListener( 'load', load, false ); needed
myPlugin.init();
},
false
);
}
So this may be not the best practice, but I keep on learning. The interval itself is called inside the init() method like so:
myPlugin.intervalID = window.setInterval(
myPlugin.getRemoteData,
myPlugin.settings.updateMinInterval * 1000 //milliseconds!
);
There's another point setting the interval: an observer to the settings (preferences) clears the current interval and set it exactly the same way like mentioned above when a change to the updateMinInterval setting occures.
As I get this right, a solution using »function expressions« should look like:
myPlugin.intervalID = window.setInterval(
function() {
myPlugin.getRemoteData();
},
myPlugin.settings.updateMinInterval * 1000 //milliseconds!
);
Am I right?
What is a possible scenario of »attacking« this code, I've overlooked so far?
Should setInterval and setTimeout basically used in another way in Firefox addons then in »normal« frontend javascripts? Because the documentation of setInterval exactly shows the way using declared functions in some examples.
Am I right?
Yes, although I imagine by now you've tried it and found it works.
As for why you are asked to change the code, it's because of the part of the warning message saying "Variables referencing function names are acceptable but deprecated as they are not amenable to static source validation".
This means that unless you follow the recommended pattern for the first parameter it is impossible to automatically calculate the outcome of executing the setInterval call.
Since setInterval is susceptible to the same kind of security risks as eval() it is important to check that the call is safe, even more so in privileged code such as an add-on so this warning serves as a red flag to the add-on reviewer to ensure that they carefully evaluate the safety of this line of code.
Your initial code should be accepted and cause no security issues but the add-on reviewer will appreciate having one less red flag to consider.
Given that the ability to automatically determine the outcome of executing JavaScript is useful for performance optimisation as well as automatic security checks I would wager that a function expression is also going to execute more quickly.

node-cloudfiles module - Is there a way to track upload progress

If anyone here is familiar with the node-cloudfiles module for node.js, I could use some help in several different areas. Unfortunately, is seems the authors are nearly impossible to reach via their github repo (EDIT: nevermind, someone did reach out to me, I'll send an update when I have an answer of some sort prepared.)
I'll start with my most basic challenge: is there a way to track the progress of the upload? I have tried many things, but the object returned from the .addFile command does not seem to hold any sort of progress stats.
Here is a basic outline of what I am working with.
var readStream = fs.createReadStream(path+'.'+extension, streamopts);
var upOpts = {
headers: {
'content-type': 'video/'+extension,
'content-length': totalBytes
},
remote: CDNfilename,
stream: readStream
};
//reqStream is the object returned from the 'request' module,
//which is used by the 'cloudfiles' module.
var reqStream = cloudClient.addFile(Container.name, upOpts, function (err, uploaded) {
if (err) { console.log(err); }
});
At first I thought I could just use the .bytesWritten property connected to an interval timer, but the object is not a normal node writeStream, so there is no such property.
Charlie (the author of the module) told me that this is possible because it's using a pipe and you just check the data events from the object returned from .addFile, like so:
reqStream.on('data', function () {
/* track progress /*
});
Whenever you need to contact somebody from the nodejitsu team, join the #nodejitsu channel on IRC, they're really active.
At the time of writing this answer, there isn't really a good way to get upload progress for files being sent to cloudfiles. However, one of the nodejitsu geniuses implemented chunked uploading, which in my case, eliminates the need for progress reports. Thanks Bradley.

Resources