bwssytems / ha-bridge

Home automation bridge that emulates a Philips Hue light system and can control other systems such as a Vera, Harmony Hub, Nest, MiLight bulbs or any other system that has an http/https/tcp/udp interface. This is a compact impl to run on small format computers. This is impl started from this project https://github.com/armzilla/amazon-echo-ha-bridge.
Apache License 2.0
1.45k stars 198 forks source link

how to use "${intensity.math(X/4)}" #124

Closed painkillerde closed 7 years ago

painkillerde commented 8 years ago

Hi I need a value between 0.0 and 1.0 for my Homematic LED-Dim-Device but cant get it.

Can u please help.

Thx alot -> great work!!!!

Daniel

audiofreak9 commented 8 years ago

Divide by 100, ${intensity.math(X/100)}

bwssytems commented 8 years ago

Currently, the math function will only return integer values. So that calculation will return 0 or 1

audiofreak9 commented 8 years ago

Actually I had a brain fart, you'd need to divide by 255 not 100, since the intensity.math is 0 to 255.

How about adding a leading "0." to the URL, and never ask to "Dim to 100%". I don't know your Dim Url structure, but it could be like the following: http://SomeUrlToCall/dim=0.${intensity.math(X/255)}

bwssytems commented 8 years ago

That would work but it looks like he needs 10ths and we would divide by 10 to get an integer be between 0.0 and 0.9, but you would not get 1.0 though.

painkillerde commented 8 years ago

at first thanks for the tips.

X/255 just turns on and under the half it turns the light off. the url is

http://192.168.178.37/addons/xmlapi/statechange.cgi?ise_id=11934&new_value=1

where 1 is 100 - 0 is off and anything between is dimmed. sample: http://192.168.178.37/addons/xmlapi/statechange.cgi?ise_id=11934&new_value=0.50 or http://192.168.178.37/addons/xmlapi/statechange.cgi?ise_id=11934&new_value=0.135

Also tried http://SomeUrlToCall/dim=0.${intensity.math(X/255)} dont works for me.

0.${intensity.percent} works except 100% but i can do this with power on i would need percent with math funktion to get it perfect.

If we could get this i can also use it for the shutters - its working the same way.

THX!!!

bwssytems commented 8 years ago

If you need to get percentage and do something else with it you can use the math function:

${intensity.math((X/255.0_100)_do something else)}

It.s just that it will only return values at the integer level. The math internally is done to a double.

Nauttor commented 8 years ago

Hi,

I have a question related to the intensity.math.

I´m trying to make it work with my limitlessLed bulbs. As they describe on their web the brightness control is set by a decimal value in between the range: (2 to 27), where full brightness is 0x1B (decimal 27). How can I set the bridge intensity.math rule to fit that range? I´m not sure if it´s possible with the current implementation.

Thanks in advance.

audiofreak9 commented 8 years ago

@Nauttor, Not sure if you need numerical or hex returned? If it's numerical and you don't request a dim level below 10% then ${intensity.math((X*27)/255)} will return a numerical range between 2 and 27.

Nauttor commented 8 years ago

I check the limitlessled doc and i must send it in hex.

For example i pass the following to set all the lights to 100% brigthness {"item":"udp://192.168.77.212:8899/0x420066"}, ##id to identify that it apply to all the lights {"item":"udp://192.168.77.212:8899/0x4E1B55"},## second byte set brightness to 1B hex/27dec/100%

It could be posible to do it in hex? And the answer to your question would be no, the inferior level would be always 10% as 0 would be switch off.

Thanks for your help.

audiofreak9 commented 8 years ago

Looks like you need a new function ${intensity.hex()}

Nauttor commented 8 years ago

mmm, what a pity, i´ll send it as a feature request, maybe for the next release...

Thank you audiofreak9.

@bwssytems may you consider ${intensity.hex()} as an enhance to fully support the limitlessled brightness options in the math functions? Thanks.

bwssytems commented 8 years ago

I already have this. If you use the construct "0x" any $intensity will be converted to hex. On Jun 21, 2016 2:37 AM, "audiofreak9" notifications@github.com wrote:

Looks like you need a new function ${intensity.hex()}

— You are receiving this because you were assigned. Reply to this email directly, view it on GitHub https://github.com/bwssytems/ha-bridge/issues/124#issuecomment-227310129, or mute the thread https://github.com/notifications/unsubscribe/AM5s-nskOaY-1lttX9kyVvZTyGmEkoWcks5qNzJlgaJpZM4IuHUC .

Nauttor commented 8 years ago

@bwssytems
I´m not sure if you refer to something like that below...it´s the correct syntax?

udp://192.168.77.212:8899/0x4E0x${intensity.math((X*27)/255)}55

bwssytems commented 8 years ago

That would be totally correct.

Nauttor commented 8 years ago

Thanks, i´ll report back with my tests results. :)

cykew commented 8 years ago

i tried, it work without 0x like:

udp://192.168.77.212:8899/0x4E${intensity.math((X*27)/255)}55

Nauttor commented 8 years ago

I have some concerns about how to setup it to work as expected.

As described on limitlessled sdk, you need first to send the group id to which you want to apply the brigthness value. 100 ms later you must sent the brightness value. I have done it before with statics values via scenes modes, as below, and it works.

{"item":"udp://192.168.77.212:8899/0x420066"}, {"item":"udp://192.168.77.212:8899/0x4E1B55"},

The problem comes if for example I tell alexa: dim to 20% the living.

I need to write it all on the DIM field, or part on the ON field and the brightness part on the DIM field?

{"item":"udp://192.168.77.212:8899/0x420066"}, {"item":"udp://192.168.77.212:8899/0x4E${intensity.math((X*27)/255)}55"},

cykew commented 8 years ago

I write all in DIM field. It works

bwssytems commented 8 years ago

Great, glad this is resolved.

chross commented 7 years ago

I have a similar issue regarding MiLight control. I want to abuse the dimming feature to select the color of one of my lights. On/Off switching is working, now I need the UDP request to be constructed to include the hex represenation of 0...255:

udp://192.168.77.212:8899/0x4EYY55 where YY should be values from 00 to FF.

I tried ${intensity.byte} as well as ${intensity.percent}. When using udp://192.168.178.30:8899/0x40${intensity.byte}55 the color changing stops at 50%. ("Alexa dim to 50%"). After 50% there is no further color change. When using udp://192.168.178.30:8899/0x40${intensity.percent}55 the color at 100% equals 1/3 of all possible colors. When using udp://192.168.178.30:8899/0x40${intensity.math(X*1)}55 color changing stops at 50%.

When using udp://192.168.178.30:8899/0x40${intensity.math(X/16)}855 Alexa tells me that the Hub does not respond.

How can I resolve this?

bwssytems commented 7 years ago

intensity byte should be correct, will take a look

chross commented 7 years ago

I sniffed some packets with Wireshark and found the following:

When using intensity byte, the following UDP packets get sent (spaces added for ease of reading) when using the Test Dim button in HA-Bridge: Brightness 100% (255 is sent as shown in the HA-Bridge success popup) 40 00ff 55 (00ff = 255) Brightness 1% (3 is sent) 40 03 55 (03 = 3) Brightness 50% (128 is sent) 40 0080 55 (0080 = 128) Raw Value 254 (254 is sent) 40 00fe 55 (00fe = 254) Raw Value 1 (1 is sent) 40 01 55 (01 = 1) Raw Value 128 (128 is sent) 40 0080 55 (0080 = 128)

So it seems to be a problem with those heading 00 zeroes.

chross commented 7 years ago

I have checked the range around Raw Values of 128 and it seems as if the conversion from dec to hex adds some leading 00 when the raw value is over or equal to 128. Raw Value 126 40 7e 55 Raw Value 127 40 7f 55 Raw Value 128 40 0080 55 Raw Value 129 40 0081 55

bwssytems commented 7 years ago

Will take a look

chross commented 7 years ago

The bug seems to be in BrightnessDecode.java public static String replaceIntensityValue(String request, int intensity, boolean isHex) {

if (request.contains(INTENSITY_BYTE)) { if (isHex) { BigInteger bigInt = BigInteger.valueOf(intensity); byte[] theBytes = bigInt.toByteArray(); String hexValue = DatatypeConverter.printHexBinary(theBytes); request = request.replace(INTENSITY_BYTE, hexValue); } else { String intensityByte = String.valueOf(intensity); request = request.replace(INTENSITY_BYTE, intensityByte); } }

Why not use .toHexString like so:

BigInteger bigInt = BigInteger.valueOf(intensity); String hexValue = bigInt.toHexString(); request = request.replace(INTENSITY_BYTE, hexValue);

bwssytems commented 7 years ago

Fixed already for the release. Cannot use BigInt as it will always give you pack 2 bytes. Using Integer.toHexString fixes it.

shoonoise commented 7 years ago

Seems like fix doesn't work for me.

I need send payload for dim: from int(1) to int(27) in hex

I try to do it like: udp://192.168.1.11:8899/0x4E${intensity.math((X*27)/255)}55

but if intensity < 128. For example, for intensity = 102 I've got:

java.lang.IllegalArgumentException: hexBinary needs to be even-length: 4Eb55
...

As I see there is no leading 0. But if add it:

udp://192.168.1.11:8899/0x4E0${intensity.math((X*27)/255)}55

I've got the same error when intensity > 128. Cause of leading 0 :) For intensity = 196:

java.lang.IllegalArgumentException: hexBinary needs to be even-length: 4E01555
...

Version 4.2.0.

bwssytems commented 7 years ago

yep, this seems opposite of what was just fixed

bwssytems commented 7 years ago

Yep, stupid converter.... fixed for the next release.

matena commented 7 years ago

Thanks for above posts. Helped me to solve how to make false dimming using light scenes from Loxone RGBW Air (I reserved first 4 scenes for colors): http://example:example@192.168.88.246/dev/sps/io/Lights/${intensity.math(5+((255-X)/255)*4)}

vaderag commented 6 years ago

Can someone here give me a hand... I've been using {"dim": ${intensity.decimal_percent}} which works for the most part, but 100% (which is a fairly common request for me) seems to fail on my LightwaveRF switch...

So, my thought was to do -5% which would mean that 100% = 95% etc

I'm obvioulsy not really getting this, but tried a few different variants: e.g. ${intensity.math(X-0.05)} ${intensity.math(X-160)} (based on the 255 mentioned above should give 95) ${intensity.math((X-160)/100)} (based on 255 should give 0.95 etc)

I'm clearly missing something - any help appreciated!

audiofreak9 commented 6 years ago

@vaderag Try ${intensity.math(((X/255)*100)-5)}, this first divides by 255 to get the percentage as a decimal, then multiply by 100 to get the whole number percentage, then subtract 5.

vaderag commented 6 years ago

Thanks @audiofreak9

Just tried that and sadly doesnt seem to work either... Checking the logs i'm getting "HTTP response code was not an expected successful response of between 200 - 299, the code was: HTTP/1.1 400 Bad Request"

I'm wondering if the x% is coming across from Alexa as a decimal maybe? So 100% = 1 from Alexa, 95%=0.95? I cant see this in the log so not sure...

Also, thinking about it, it's possible that my hub needs a decimal too... (hence why it was working with the decimal_percent out)?

With all that in mind I also tried ${intensity.math((((X/255)*100)-5)/100)} (with the extra div by 100 to give a 0.x percentage), but that didn't work either :(

Any other thoughts?!

FloFoer commented 6 years ago

I don't know LightwaveRF but looking at their API documentation regarding dimming you need values between 1 and 32? That would be ${intensity.math((X/255)*32)} or ${intensity.math(X/8)}

vaderag commented 6 years ago

@FloFoer thanks - I should probably have confirmed that I am controlling the Lightwave via a different device (Athom Homey). The 0-100% scale seemed to work there with the decimal option (apart from the 100 which is what i'm trying to solve :)

Is it possible to combine math and ${intensity.decimal_percent}? something like $intensity.math($intensity.decimal_percent-0.05) ? (i'm kinda guessing now ;)

FloFoer commented 6 years ago

Ok so then what values does Athom Homey expect for dimming? There must be an exact definition somewhere in a documentation. Because apparently it's not quite what you're sending, otherwise 100% should work too. Did you try just ${intensity.percent} ? How does your entire command in HA-Bridge look like? Never heard of the Homey to be honest.

vaderag commented 6 years ago

So the full command is: HTTP Device Target Item: http://[homeyip]/api/manager/devices/device/[deviceid]/state HTTP Verb: Put Body as we've been discussing Header: [{"name":"Authorization","value":"bearer [homeyid]"}] application/json

I tried ${intensity.percent} (just tried it again too) and it does nothing... seems it needs to be the decimal variant

EDIT: I think the third comment on this thread might be highlighting my issue "Currently, the math function will only return integer values. So that calculation will return 0 or 1" - I need a decimal, but the math function is only returning 0 or 1

FloFoer commented 6 years ago

This sounds more like an error in Homey to me. HA-Bridge is delivering values between 0.0 - 1.0 with decimal_percent so apparently Homey has a problem with the 1.00 although everything below that works which doesn't sound right to me (without knowing Homey). And yes, i checked the code, the result of intensity.math is still an integer so you can't remap 1.0 to 0.95 with that.
If you really have to do the remap you could

  1. Make the HTTP call inside a script instead of directly in an HTTP item and make the conversion there.
  2. Implement a ${intensity.math().decimal} placeholder in ha-bridge (should be very easy, because the calculation is already done decimal and simply rounded afterwards. Just don't do that in your variant and format it like decimal_percent does.) This is the only file that would need a change.
vaderag commented 6 years ago

@FloFoer I'm pretty certain the issue IS with Homey (or at least in the Lightwave App in Homey), but I think it would be easier to fix it on this end... sadly, despite your excellent direction, my java is very very rusty and I'm not really sure where to go from here...

I'm guessing the change happens somewhere around here or perhaps at the definition?: } else if (request.contains(INTENSITY_DECIMAL_PERCENT)) { replaceValue = String.format(Locale.ROOT, "%1.2f", decimalBrightness); replaceTarget = INTENSITY_DECIMAL_PERCENT; notDone = true;

FloFoer commented 6 years ago

I have created a super quick implementation: (rename .txt to .java) BrightnessDecode.txt Works the same way as the normal intensity.math but result is a double.
You can use it with the above mentioned formula like that: ${intensity.math((((X/255)*100)-5)/100).decimal} . This formula has the downside of returning negative values for <= 5%. An alternative would be something like {intensity.math((X/255)*0.95).decimal}

For your reference the lines 22, 123-134, 171-182 are new.

vaderag commented 6 years ago

Thanks @FloFoer Realised that my java is so rusty that I don't even have the jdk installed, so this is going to need to wait til tomorrow to test, but fingers crossed :) I'll report back once tested!!

vaderag commented 6 years ago

@FloFoer double thanks - complied that this morning and works great!

That said, in both options I now realise the issue exists at the bottom end too :( 5% seems to set the light to off now, where as 6% works as expected...

I tried playing with your formula in{intensity.math((X/255)*0.95).decimal} but it seems that no matter what values I use I can't quite tweak it to be 5%=6% and 100%=95%

FloFoer commented 6 years ago

I looked into what is possible with the math evaluator and found out that you could do something like this ${intensity.math((X/255)==1.0 ? 0.95 : (X/255)).decimal} Which would mean to replace a 1.0 with a 0.95 and otherwise keep the said value. You could of course change that and use more nesting, all common comparison operators work, so you could for example use different scaling factors for different percentage ranges.

vaderag commented 6 years ago

Awesome - can it use greater than and multiple arguments?

So something like ${intensity.math((X/255)>=0.95 ? 0.95 : (X/255)<=0.06 ? 0.06 : (X/255)).decimal}

FloFoer commented 6 years ago

Yes. This function seems to work ;)

INTENSITY: 255 DECIMAL: 1.0 NEWVAL: 0.95  
INTENSITY: 247 DECIMAL: 0.96862745 NEWVAL: 0.95  
INTENSITY: 117 DECIMAL: 0.45882353 NEWVAL: 0.46  
INTENSITY: 8 DECIMAL: 0.03137255 NEWVAL: 0.06  
vaderag commented 6 years ago

@FloFoer thank you so much for your help - seems to be working a dream now 👍