General Code Questions - Example with Blinds


#1

I have a number of blinds running connected with the same device, a Zipato Micro Module Motor Controller. Essentially, it is a rebranded Philio Roller Shutter Controller (PHI_PAN08-1B-525). Now these devices are working nicely, on the whole… But they have this quirk where they do not show the exact Level - rather they update the level as the blind passes every “10% mark”… E.g. if the blind is at 0% and you wanted to take it to 43%, then on the app, when it settles, it will show you 40%. If the starting point is 70% and you take it to 43%, when it settles the app will show you 50% - even though on both occasions it would have actually stopped at 43%.

It’s a bit of an issue as I have 8 blinds on the ground floor, floor to ceiling - these are zebra blinds and I keep them at 1% which gives a perfect zerba effect, but they show as 0% all the time - which means I am unable to actually move the slider to 0% on the app. Consequently, I wrote 2 pistons: one to refresh the Level from the device from WebCoRE (can’t do it from DTH as it is a stock DTH), and another piston to refresh every blind where the level is a round number, meaning that possibly its Level is incorrect and is just what the device reported to ST. The latter piston is necessary because sometimes the device does not even report there was a movement. E.g. if the blinds are at 0% and I take them all to 1%, literally none of them will register a change in Level at any point and the first piston that is subscribed to Level change events never fires…

The question I have is about the second piston - a fairly simple one, but I am a beginner and seeking to optimise stuff as much as possible and check whether i can do things in a simpler way.

My 3 questions are:

  1. Is there any way to say “If $device.level = 0%, 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90%, or 100%” all on the same line? Or do I have to construct the cindition in this long-winded manner?
    Why is

  2. Is there any other way of capturing an event happening on a blind, other than looking at whether the level changed?

  3. I am aware that the maximum a piston can run for is 20 seconds, however device refreshes sometimes take notoriously long and I have 15 such blinds. most take half a second, but you find the occasional one that takes rather long (e.g. 3 seconds). What would happen in this case? Would the piston be abandoned halfway through?

  4. As you can see I split the log into 2 lines… I tried joining them in an Expression, but couldn’t (I tried using $device.location, but that would not work). Is there a way to join these on one line, to make it more human readable?

**4) Post a Green Snapshot of the piston![image|45x37]

5) Attach logs after turning logging level to Full
3/11/2021, 3:30:08 PM +101ms
+1ms ╔Received event [Home].time = 1615473008232 with a delay of -131ms
+73ms ║RunTime Analysis CS > 26ms > PS > 8ms > PE > 39ms > CE
+76ms ║Runtime (44422 bytes) successfully initialized in 8ms (v0.3.113.20210203) (75ms)
+77ms ║╔Execution stage started
+99ms ║║Comparison (integer) 1 is_equal_to (integer) 0 = false (1ms)
+100ms ║║Cancelling condition #6’s schedules…
+101ms ║║Condition #6 evaluated false (11ms)
+110ms ║║Comparison (integer) 1 is_equal_to (integer) 10 = false (2ms)
+112ms ║║Condition #22 evaluated false (9ms)
+120ms ║║Comparison (integer) 1 is_equal_to (integer) 20 = false (1ms)
+122ms ║║Condition #23 evaluated false (9ms)
+129ms ║║Comparison (integer) 1 is_equal_to (integer) 30 = false (1ms)
+131ms ║║Condition #24 evaluated false (8ms)
+139ms ║║Comparison (integer) 1 is_equal_to (integer) 40 = false (1ms)
+141ms ║║Condition #25 evaluated false (9ms)
+150ms ║║Comparison (integer) 1 is_equal_to (integer) 50 = false (2ms)
+152ms ║║Condition #26 evaluated false (10ms)
+160ms ║║Comparison (integer) 1 is_equal_to (integer) 60 = false (2ms)
+161ms ║║Condition #27 evaluated false (8ms)
+170ms ║║Comparison (integer) 1 is_equal_to (integer) 70 = false (2ms)
+172ms ║║Condition #28 evaluated false (9ms)
+180ms ║║Comparison (integer) 1 is_equal_to (integer) 80 = false (2ms)
+182ms ║║Condition #29 evaluated false (9ms)
+190ms ║║Comparison (integer) 1 is_equal_to (integer) 90 = false (1ms)
+192ms ║║Condition #30 evaluated false (8ms)
+200ms ║║Comparison (integer) 1 is_equal_to (integer) 100 = false (1ms)
+201ms ║║Condition #31 evaluated false (8ms)
+203ms ║║Cancelling condition #5’s schedules…
+203ms ║║Condition group #5 evaluated false (state changed) (113ms)
+206ms ║║Cancelling statement #7’s schedules…
+214ms ║║Calculating (string) Blind level of + (string) Living Room Blind 7 >> (string) Blind level of Living Room Blind 7
+216ms ║║Calculating (string) Blind level of Living Room Blind 7 + (string) is: >> (string) Blind level of Living Room Blind 7 is:
+220ms ║║Blind level of Living Room Blind 7 is:
+221ms ║║Executed virtual command [Living Room Blind 7].log (1ms)
+230ms ║║1
+231ms ║║Executed virtual command [Living Room Blind 7].log (1ms)
+245ms ║║Comparison (integer) 0 is_equal_to (integer) 0 = true (1ms)
+246ms ║║Cancelling condition #6’s schedules…
+247ms ║║Condition #6 evaluated true (10ms)
+248ms ║║Cancelling condition #5’s schedules…
+249ms ║║Condition group #5 evaluated true (state changed) (13ms)
+251ms ║║Cancelling statement #32’s schedules…
+259ms ║║Calculating (string) Blind level of + (string) Main Bedroom Blind 1 >> (string) Blind level of Main Bedroom Blind 1
+262ms ║║Calculating (string) Blind level of Main Bedroom Blind 1 + (string) is: >> (string) Blind level of Main Bedroom Blind 1 is:
+266ms ║║Blind level of Main Bedroom Blind 1 is:
+267ms ║║Executed virtual command [Main Bedroom Blind 1].log (2ms)
+277ms ║║0
+278ms ║║Executed virtual command [Main Bedroom Blind 1].log (1ms)
+1515ms ║║Executed physical command [Main Bedroom Blind 1].refresh() (1236ms)
+1516ms ║║Executed [Main Bedroom Blind 1].refresh (1237ms)
+1529ms ║║Comparison (integer) 0 is_equal_to (integer) 0 = true (1ms)
+1531ms ║║Condition #6 evaluated true (9ms)
+1532ms ║║Condition group #5 evaluated true (state did not change) (11ms)
+1534ms ║║Cancelling statement #32’s schedules…
+1542ms ║║Calculating (string) Blind level of + (string) Main Bedroom Blind 2 >> (string) Blind level of Main Bedroom Blind 2
+1545ms ║║Calculating (string) Blind level of Main Bedroom Blind 2 + (string) is: >> (string) Blind level of Main Bedroom Blind 2 is:
+1549ms ║║Blind level of Main Bedroom Blind 2 is:
+1550ms ║║Executed virtual command [Main Bedroom Blind 2].log (2ms)
+1560ms ║║0
+1561ms ║║Executed virtual command [Main Bedroom Blind 2].log (1ms)
+1575ms ║║Executed physical command [Main Bedroom Blind 2].refresh() (12ms)
+1576ms ║║Executed [Main Bedroom Blind 2].refresh (14ms)
+1590ms ║║Comparison (integer) 0 is_equal_to (integer) 0 = true (1ms)
+1591ms ║║Condition #6 evaluated true (9ms)
+1592ms ║║Condition group #5 evaluated true (state did not change) (11ms)
+1595ms ║║Cancelling statement #32’s schedules…
+1603ms ║║Calculating (string) Blind level of + (string) Main Bedroom Blind 3 >> (string) Blind level of Main Bedroom Blind 3
+1606ms ║║Calculating (string) Blind level of Main Bedroom Blind 3 + (string) is: >> (string) Blind level of Main Bedroom Blind 3 is:
+1610ms ║║Blind level of Main Bedroom Blind 3 is:
+1611ms ║║Executed virtual command [Main Bedroom Blind 3].log (1ms)
+1621ms ║║0
+1622ms ║║Executed virtual command [Main Bedroom Blind 3].log (2ms)
+1635ms ║║Executed physical command [Main Bedroom Blind 3].refresh() (11ms)
+1636ms ║║Executed [Main Bedroom Blind 3].refresh (13ms)
+1640ms ║╚Execution stage complete. (1563ms)
+1642ms ║Setting up scheduled job for Thu, Mar 11 2021 @ 3:31:08 PM CET (in 58s)
+1650ms ╚Event processed successfully (1649ms)


#2

For #1, you can try something like this…
image

For #2, maybe an On Events will work for you
image

If you don’t have On Events available, you will need to turn on Advanced Statements under Options.
image

#3. not sure about this one.

#4 In the value field… try
Blind level of {$device} is {[$device:level]}


#3

Thanks a lot! Tried the first part and it worked brilliantly, but if you don’t mind my asking, what does this part mean:

[$device:level] %10 == 0

I am not familiar with the syntax of WebCoRE yet, trying to get there…


#4

The second part - On Events - did not work for me… The device (and possibly the DTH) do(es) a very good job of hiding small increments in percentage (1 or 2%) from the hub, so the level never changes (on the hub) and the hub is never aware of the change. Indeed, even if I start the blind move from the app, and take the slider manually up from 0% to 1%, the blind will go up by a little, but the slider will snap right back to 0 on the app, showing you an incorrect number. Essentially, what you see on the app is $device:level on the hub.

So - in any case, thank you for this part nonetheless. Seems like I will have to make do with a refresh every 5 minutes or so.


#5

[$device:level] %10 == 0 pulls the $device level and compares the remainder of the level divided by 10.


#6

Ok - I’ll take your word for it… It is obvious that this is what it meant but I thought I was jumping to conclusions as there’s no way I could hav imagined that “%10” would mean the remainder when divided by 10. So thanks, very good to know.


#7

It just happened I guess that your level requirements were all divisible by 10. In other cases, you’d probably have to go the long way around but still in one line like…

(([$devicel:level] ==10) || ([$devicel:level] ==15) || ([$devicel:level] ==32))


#8

Ok this works like a charm - many thanks…

I am old school - I wish I could just read a book or follow tutorials online, I would be done by now instead of looking through the community for answers I cannot find… It looks like there’s some assumption of a knowledge of coding, also in a specific language - more oriented to open source type languages which frankly I am not familiar with…

So ind if I ask another: In this expression I put in Value, why the curly brackets around $device, and the curly and square brackets around $device.location? What do the different brackets denote please?


#9

I also just learn from reading and looking at examples and some basic if/then/else knowledge.

If you use the value field, you wrap variables (system, local or global) in curly braces, and if you’re referring to a device and it’s attribute, you’ll have to enclose it in a square bracket and curly braces. Now if you use an Expression field, you don’t need to but you’ll need to enclose regular text in quotes, single or double doesn’t matter as long as they match.


#10

Brilliant - that’s extremely useful information for me… Appreciate your help!


#11

So, in my quest to understand | | more, what is the above doing?


#12

In that example I’m just checking if the device level is 10, 15 or 32, return true if it is.