How can I pass parameters into openhab2 transformations? - openhab

I have a openhab 2.1 setup, and I am using the http binding to get the additional data from my hue bridge that is not available in the hue binding (yet). I am mostly interested in the light- and temperature sensors built into the motion sensors, but I also want to be able to react to button presses (and, since this is interactive, with as little delay as possible).
So i chose to go with polling the bridge using the http binding.
I have:
hue.url=http://192.168.61.21/api/[KEY]/sensors/
hue.updateInterval=500
and I am using JS or JSONPATH transformations to extract values.
the problem I am having is this:
I can easily do:
Number hue_dimmer_buttons_study_1 "Study Dimmer (last button)" { http="<[hue:500:JSONPATH($.16.state.buttonevent)]" }
Number hue_dimmer_scene_study_1 "Study Dimmer (current scene)" { http="<[hue:500:JSONPATH($.17.state.status)]" }
and get the values from entire list. But I can only do EITHER a transformation like this and get the raw value from the JSON, OR I can do additional transformations (such as mapping "true" to "ON" and 1995 to 19.95) - I cannot do both.
Also, if I retrieve all sensor states anyways, I might as well retrieve all values from the same string - for this, my only option is to write one (for example) getHueTemperature.js for EACH SENSOR, i.e.:
getHueTemperature14.js:
(function(i) {
return JSON.parse(input).14.state.temperature / 100;
})(input)
and then do:
[...] { http="<[hue:500:JS(getHueTemperature14.js)]" }
I cannot pass in which element I want to extract from and then use one transformation for all sensors, such as:
getHueTemperature.js:
(function(i) {
return JSON.parse(input)[element].state.temperature / 100;
})(input, element)
and then:
[...] { http="<[hue:500:JS(getHueTemperature.js,14)]" }
... or can i? any help would be very much appreciated.
thanks
.rm

Related

Errors When Calculating Distance Between Two Addresses

I have the following script which is being used in a spreadsheet to calculate the driving distance between two cities or a city and a zip code of another city. It is being run for approximately 25 locations simultaneously. To better explain, I have cell B3 in which I enter a new city every time. The script is then used in cells adjacent to my 25 plant locations to calculate the distance from each of my plants to the variable city.
It uses google sheets built in mapping api and works on 80% of the calculations but returns "TypeError: Can Not Read Property "legs" from undefined. (line 16). The plants that it fails on vary with every new city so its not like it is for certain locations. It is almost like the api times out before it completes some of them. I split it into two separate scripts with a varied name and that worked for a day but then 20% fail again.
To make things slightly more odd, I have another script that sorts the plants based on closest distance to the variable address. When you sort the plants, even the ones with errors go to their correct location based on distance. So it is like the distance script is obtaining the correct disance but displaying the error anyways.
Clear as mud? Would love any input I could get on how to correct the issue or an alternate mapping api that could solve my problems.
function distancecalcone(origin,destination) {
var directions = Maps.newDirectionFinder()
//Set the Method of Transporation. The available "modes" are WALKING, DRIVING, BICYCLING, TRANSIT.
.setMode(Maps.DirectionFinder.Mode.DRIVING)
//Set the Orgin
.setOrigin(origin)
//Set the Destination
.setDestination(destination)
//Retrieve the Distance
.getDirections();
return directions.routes[0].legs[0].distance.value/1609.34;
}
Have you tried using a try-catch block around directions.routes[0].legs[0].distance.value ?
try{
return directions.routes[0].legs[0].distance.value/1609.34;
}
catch (e){
console.log("error",e)
}
or you could try something like this
alert(directions);
alert(directions.routes[0]);
alert(directions.routes[0].legs[0]);
alert(directions.routes[0].legs[0].distance);
alert(directions.routes[0].legs[0].distance.value);
and so on...to find out which one comes up as undefined the first. That might help you to debug the issue.
Enable Direction Api
1)Go to "google cloud platform"
2)go to "Api and services"
3)search for "direction api" and enable it
The directions service is subject to a quota and a rate limit. Check the return status before parsing the result.
For lots of distances (or at least more than 10), look at the DistanceMatrix.
I'm able to run the script from the Script editor, but not from spreadsheet. The error is "unable to read property legs" when the function is called from spreadsheet. But the property is in place when called from Script editor and contain correct values.
You probably need to use WEB API and have API KEY:
Google Apps Script - How to get driving distance from Maps for two points in spreadsheet

APIGEE querying data that DOESN'T match condition

I need to fetch from BaaS data store all records that doesn't match condition
I use query string like:
https://api.usergrid.com/<org>/<app>/<collection>?ql=location within 10 of 30.494697,50.463509 and Partnership eq 'Reject'
that works right (i don't url encode string after ql).
But any attempt to put "not" in this query cause "The query cannot be parsed".
Also i try to use <>, !=, NE, and some variation of "not"
How to configure query to fetch all records in the range but Partnership NOT Equal 'Reject' ?
Not operations are supported, but are not performant because it requires a full scan. When coupled with a geolocation call, it could be quite slow. We are working on improving this in the Usergrid core.
Having said that, in general, it is much better to inverse the call if possible. For example, instead of adding the property when the case is true, always write the property to every new entity (even when false), then edit the property when the case is true.
Instead of doing this:
POST
{
'name':'fred'
}
PUT
{
'name':'fred'
'had_cactus_cooler':true
}
Do this:
POST
{
'name':'fred'
'had_cactus_cooler':'no'
}
PUT
{
'name':'fred'
'had_cactus_cooler':'yes'
}
In general, try to put your data in the way you want to get it out. Since you know upfront that you want to query on whether this property exists, simply add it, but with a negative value. The update it when the condition becomes true.
You should be able to use this syntax:
https://api.usergrid.com/<org>/<app>/<collection>?ql=location within 10 of 30.494697,50.463509 and not Partnership eq 'Reject'
Notice that the not operator comes before the expression (as indicated in the docs).

different array for more google map on same page

I have a problem with google map, delivery from this example: `Click here
I would like to create two maps, with different makers, and different paths on the same page that just does not seem to be able to pass new values ​​to google map for a different canvas-map based on the values ​​passed to the function.
In the my example: Click here clarifies my problem.
<p class="openmap" data-id="map">click here for map<p>
<p class="openmap" data-id="map1">click here for map1<p>
....
In the real script, the variable 'posts', is more complex and generates coordinates from html tables (two or more).
Someone has an idea how to fix?
The problem starts here:
function Tour_startUp(stops) {
if (!window.tour) window.tour = {
//code
}
}
It's obvious that Tour_startUp will do nothing when you call it the 2nd time, because on further calls the condition if (!window.tour) will be false. The result: both maps will use the same stops-argument that has been supplied at the first call.
Rethink the design of your application, avoid global variables and use OOP.

After Effects Expressions - controling comps from main comp using an "Expressions Layer"

THE GOAL I WANT TO ACHEIVE:
Control AE timelines using ONE EXPRESSION LAYER (much like using Actionscript) to trigger frequently used comps such as blinking, walking, flying etc... for cartoon animation.
I want animate a the blinking of a cartoon character. (and other actions, explained below) Rather than "re posting" the comp or key frames movements every time I want a blink or a particular action, I want to create a script where I can trigger the Blink comp to play. Is this possible? (Sidenote: A random blink through entire movie would be nice) but I still want to know how to do this for the reasons below.
Ideally: I would like to create an "Expressions layer" in the main comp to TRIGGER other comps to play. At certain points I would like to add triggers to call frequently used comps that contain actions like.. Blinking, Walking, Flying, Look Left and Right etc...
IT WOULD BE AMAZING IF somehow we could trigger other comps to begin, repeat, stop, maybe reverse, and do this all from one Main Comp using an expression layer.
WHY DO IT THIS WAY?
Why not just paste a comp in the spot you want it to play every time you want such action? Well in after effects if you wanted a "blink comp" to play 40 times in two minutes you would have to create 40 layers, or pate the key frames on that comp 40 times. Wouldn't it be awesome to trigger or call it from one one layer when you wanted it from one expressions layer?
We do something like this in Flash using Actionscript all the time. It would be awesome if there was a method out there to achieve this effect. This would be an OUTSTANDING tutorial and I believe it would be very popular if someone did it. It could be used for a MULTITUDE of amazing effects and could save a ton of time for everyone. Heck, help me figure this out and perhaps I will make a tutorial.
Thank you all ye "overflowing Stackers" who contribute! :)
I found the answer and that is...
IT'S NOT POSSIBLE.
After Effects expressions can not control other timelines. Unfortunately you have to put an expression on each layer you want to affect.
The next best solution, and to achieve something close to what I was asking can be found on this link: motionscript.com/design-guide/marker-sync.html
We can only hope that Adobe will someday give the power to expressions like they did with action-script.
HOPEFULLY SOON! Anyone reading this who works for Adobe please plead our case. Thanks
Part 1: Reference other layers in pre-Comps
Simply replace "thisComp" with "comp("ComName")"
To reference Effect-Controllers between compositions, follow the below formula:
comp("ComName").layer("LayerWithExpression").effect("EffectControlerName")("EffectControllerType")
More In-depth Answer: Adobe's Docs - Skip to the Layer Sub-objects part
As I understand the Adobe documentation, only Layers can be accessed,
not footage. What this means is that you will need to create your
expression link utilizing a pre-Comp. Footage can not access this so
that also means no nulls, adjustment layers, etc.
As an added bonus, if you use the essential graphics panel, you can put all the controllers in one pre-comp, but have the controls available no matter which comp you are in. Just select it in the Essential-Graphics dropdown.
Part 2: Start/End based on other layers within pre-comps:
Regarding the next part where you want the expressions to activate based on other compositions, I recommend using the in-out Point expression.
inPoint | Return type: Number. Returns the In point of the layer, in seconds.
outPoint | Return type: Number. Returns the Out point of the layer, in seconds.
If you utilize the start time overrides you can pull this from:
startTime | Return type: Number. Returns the start time of the layer, in seconds.
Alternate Option:
I would recommend avoiding this as the keyframes are basically referenced as an index, so things can get messed up if you add one ahead of a keyframe you were already using - def incorporate some error handling.
Refer to the Key attributes and methods (expression reference) Here
Part 3: Interpolation & Time Reversal
You can time reverse the layer in the rightclick->time, otherwise this is all interpolation expressions like loop out etc - you can loopOut("FOO") a pre-comp if you not only cut it correctly, but also enable time remapping.
then use this to loop those keyframes;
try{ timeStart = thisProperty.key(1).time; duration = thisProperty.key(thisProperty.numKeys).time-timeStart; pingPong =
false; //change to true value if you want to loop animationn back &
forth quant=Math.floor((time-timeStart)/duration);
if(quant<0) quant = 0
if(quant%2 == 1 && pingPong == true){
t = 2*timeStart+ (quant+1)*duration - time;
}
else{
t = time-quant*duration;
}
}
catch(err){
t = time;
}
thisProperty.valueAtTime(t)

audio playback in c4 framework (c4iOS

new user to c4iOS framework. Working my way thru the tutorials/examples - wondering how one goes about playing back audio (as opposed to video, which is covered in the example texts).
thanks in advance for answering my less-than-advance 'n00b' question
-jf
Audio samples are fairly similar to movie objects, albeit they don't have an option like shouldAutoplay that will get them running as soon as the application loads.
The easiest way to construct a sample is like this:
#implementation C4WorkSpace {
C4Sample *audioSample;
}
-(void)setup {
audioSample = [C4Sample sampleNamed:#"C4Loop.aif"];
}
Which builds the audio sample object as a variable that you can then reference in other methods. For instance, if you want to play a sound clip when you first touch the screen you would do the following:
-(void)touchesBegan {
[audioSample play];
}
To toggle the playback for each touch, you would do something like:
-(void)touchesBegan {
if(audioSample.isPlaying) {
[audioSample stop];
} else {
[audioSample play];
}
}
A working copy of a C4 app that toggles playback can be found HERE.
There are also a lot of properties for audio samples that let you control things like playback rate, volume, panning and so on.
An example of changing the volume is like this:
audioSample.volume = 0.5; //0 = mute, 1 = full volume
An example of skipping to a specific time in a sample would be like:
audioSample.currentTime = 1.0f; //this will put the "playhead" to 1.0 second
You can have a look at the C4Sample documentation to see more properties and other aspects of the class. The documentation is also available via the Xcode organizer.

Resources