How to create and call global functions?

Hello,

I probably didn’t yet fully get the philosophy of Homey… but I want to write a function XYtoRGB and don’t really find how to do this properly with Homey.

The function will to convert into an RGB string any input ‘Philips hue scene’ (represented by it’s x, y colors and brillance). Obviously, I don’t want to type its code in all my flows.

So far, I found that I could probably use an HomeyScript like this:

//args[0] = '{ "x":0.5019, "y":0.4152, "bri":143 }';

if (args[0] === '' || args[0] === undefined)  {
  throw new Error('This script needs a json as parameter: { "x":0.561, "y":0.4042, "bri":90 }');
}


const flow_args = JSON.parse(args[0]);
if (Object.keys( flow_args).length != 3) {
  throw new Error('This script has only ' + Object.keys( flow_args).length + ' parameters and needs 3. Ex.: { "x":0.561, "y":0.4042, "bri":90 } ');
}

console.log('x:' + flow_args.x );
console.log('y:' + flow_args.y );
console.log('bri:' + flow_args.bri );

const x = (typeof flow_args.x === 'number')
  ? flow_args.x
  : 0.561;
const y = (typeof flow_args.y === 'number')
  ? flow_args.y
  : 0.4042;
const bri = (typeof flow_args.bri === 'number')
  ? flow_args.bri
  : 90;

z = 1.0 - x - y;

Y = bri / 255.0; // Brightness of lamp
X = (Y / y) * x;
Z = (Y / y) * z;
r = X * 1.612 - Y * 0.203 - Z * 0.302;
g = -X * 0.509 + Y * 1.412 + Z * 0.066;
b = X * 0.026 - Y * 0.072 + Z * 0.962;
r = r <= 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math.pow(r, (1.0 / 2.4)) - 0.055;
g = g <= 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math.pow(g, (1.0 / 2.4)) - 0.055;
b = b <= 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math.pow(b, (1.0 / 2.4)) - 0.055;
maxValue = Math.max(r,g,b);
r /= maxValue;
g /= maxValue;
b /= maxValue;
r = r * 255;   if (r < 0) { r = 255 };
g = g * 255;   if (g < 0) { g = 255 };
b = b * 255;   if (b < 0) { b = 255 };

r = Math.round(r).toString(16);
g = Math.round(g).toString(16);
b = Math.round(b).toString(16);

if (r.length < 2)
    r="0"+r;        
if (g.length < 2)
    g="0"+g;        
if (b.length < 2)
    b="0"+r;        
rgb = "#"+r+g+b;

console.log(args[0] + ' = ' + rgb);
return rgb;

Unfortunately, I don’t see how to call it properly from a flow.
I tried with a HomeScript’s card "Run … with argument’

image

But first, I struggled to pass an array of parameters. I read on this forum that people recommend using splitting the single input argument or use a json string… Really no other way ? I guess there is some trick with the notation (ex.: {{ [0.40, 0.3605, 80] }]) ? indeed, the HomeScript documentation is clearly mentioning an array :

image

And next, I can’t find how to retrieve the result. I read also on this forum that one could create and set a tag with the output value. But I don’t want to define one distinct tag per flow where I use this script :confused: Maybe I am not using/calling correctly my HomeyScript ??

Any advice for me to achieve my purpose ?
Thx a lot in adv for any tip !

V.

I’m finding a way to create something simular; a formula (HomeyScript?) which calculates a value on given parameters. Maybe you (@vletroye) did find a way, or someone else here has good ideas?

I would appreciate. Thanks in advance.

A somewhat ambiguous question. What exactly do you want to calculate? If it’s a simple calculation, the “Calculate Number Variable as Text” logic card might work in a flow. If it’s more complex, you could do it in HomeyScript, but then the question is: do you have any JavaScript skills?

Hi Ben,

It is a simple formula to calculate value in a transition flow. Like setting dim- or volume values in a fading flow.

x=start value
y=end value
z1=current second
z2=total of seconds

result=x+(ABS(z2-z1)*((y-x)/z2)

I’m finding a way to do this with Homeyscript, like vletroye is trying to do.

Of course, I don’t know in which context/flow you want to use this calculation, but this might help.

This is the calculation in the form of a Homeyscript function that returns the result.

// Async HomeyScript function to calculate progress value
async function calculateProgress(startValue, endValue, currentSecond, totalSeconds) {
// Ensure inputs are numbers
const x = Number(startValue);
const y = Number(endValue);
const z1 = Number(currentSecond);
const z2 = Number(totalSeconds);
const result = x + (Math.abs(z2 - z1) * ((y - x) / z2));
return result;
}

Usage: const myVar = await calculateProgress(10, 100, 30, 60);

You could also, of course, use the “calculate variable as text” logic card in a flow and paste the formula within the {{ }} brackets. This would result in this:

The parameters used must offcourse already exist in the flow as tags, and you must have a named variable to store the result.

What’s the purpose of marking the function as being async when it does nothing asynchronous?

Right, Robert, it’s a bit of a habit, as an await statement is often needed within a function. But it doesn’t hurt here, it’s just an example. I also haven’t fully understood the context in which it should be used.

If await is being used inside a function (or you want to use it), it should be marked async :slight_smile:

I know. Async isn’t necessary here. But it doesn’t hinder anything. The point is the calculation example within a function. If it’s even necessary to use HomeyScript at all. Depends on the context.