#Dynamic cover button

1 messages ยท Page 1 of 1 (latest)

light tinsel
#

@tired comet Let's clean up your code a little bit. Post in here.

tired comet
#

which one?

#

Im gonna change it to add in the tap_action

light tinsel
#

Add something like yaml variables: var_entity: cover.hall_coverThen where you have 'cover.hall_cover', replace it with variables.var_entity (no quotation marks around it) for the icon and styles sections.

#

Do your blinds have "tilt" capabilies?

tired comet
#

no, they are just basic roller blinds

#

I cant post anymore code.. reach character limit ๐Ÿ˜ฆ

#

so the top part of my code should be:

#

type: custom:button-card variables: var_entity: cover.hall_cover show_state: true name: Hall Blind

light tinsel
#

What does the position attribute report if the blinds are closed? Is it 0?

tired comet
#

0

light tinsel
#

No, you still need to keep the entity in there. But... I'm stupid and over looked something way easier...

tired comet
#

so like this?

#

type: custom:button-card entity: cover.hall_cover variables: var_entity: cover.hall_cover show_state: true name: Hall Blind icon: |- [[[

light tinsel
#

custom:button-card has a built-in entity variable. Leave this the way it is yaml type: custom:button-card entity: cover.hall_cover show_state: true name: Hall Blindbut you can change,

(states['cover.hall_cover'].state == "open")``` to  ```yaml
(states[entity].state == "open")```
tired comet
#

ah yes, good eye there!

#

so I dont need to use the

#

variables: var_entity: cover.hall_cover

#

anymore?

light tinsel
#

No. Not at this point since you're going to use the card's entity variable.

tired comet
#

right great! this does make it easier to migrate to another blind

light tinsel
#

Yeah. That's going to be useful later, too, when (if) you migrate to a configuration template which will cut down on code and updating cards.

#

And actually, I'm going to copy all your code and use one of my demo entities at the same time.

tired comet
#

hmm doesnt work. its probably the square brackets.

light tinsel
#

The state can be returned with simple entity.state

tired comet
#

it has to be [entity.state]

light tinsel
#

Okay. Think I have everything copied on my side. The 90px card height messed me up and I wasn't getting an icon...

#

Do your icons work the way they're defined in the code?

#

Nvm. Figured it out. Your entity has both position and current_position. Mine only has current_position.

#

Bringing your logic into the thread:

yes thats what Im trying to do. control my blinds from 1 single button. so there is some logic to it. e.g. if the blind is fully opened> close the blind. If the blind is fully closed > open the blind. IF its in the middle somewhere then depending on whether it is above or below the mid point, then open/ close accordingly.

#

I think, to make the code easier, everything should be based around the position of the blinds and not consider the state (open/closed) because closed=0 but open= 1 to 100.

tired comet
#

cant seem to get the entity to work properly.. doing some troubleshooting now

light tinsel
#

I just about have it. Ran into a couple of snags but working through them. (I got it to open and close appropriately.)

tired comet
#

this is how mine looks like

#

changing ((states['cover.hall_cover'].state == "open") to ((states[entity].state == "open") doesn't work

light tinsel
#

if (entity.state == "opening"){

tired comet
#

type: custom:button-card entity: cover.hall_cover show_state: true name: Hall Blind icon: |- [[[ if ((entity.state == "open") & (entity.attributes.position > "99")){ return "mdi:blinds-open"; } else if ((entity.state == "open") & (entity.attributes.position < "100")){ return "mdi:blinds"; } else if ((entity.state == "closed") & (entity.attributes.position < "100")){ return "mdi:roller-shade-closed"; } else if (entity.state == "opening"){ return "mdi:arrow-up-bold-box"; } else if (entity.state == "closing"){ return "mdi:arrow-down-bold-box"; } ]]] styles: icon: - color: | [[[ if (entity.state == "opening"){ return "orange"; } else if (entity.state == "closing"){ return "orange"; } else if (entity.attributes.moving == "STOP"){ return "grey"; } else { return "grey"; } ]]] card: - height: 90px name: - padding-left: 3px - font-weight: bold - font-size: 13px - justify-self: middle state: - font-size: 12px - padding-top: 2px - padding-left: 3px - font-weight: bold - justify-self: middle - color: darkgrey tap_action: action: call-service service: script.hall_blinds_script hold_action: action: more-info

#

ok this is the working one. Now to work on tap_action

light tinsel
#

Need you to do a test for me. Add this line to you code (like under show_state: true:yaml state_display: '[[[return entity.attributes.current_position ]]]' and then move your blinds to a different position other than 100.

tired comet
#

yes it shows the position

light tinsel
#

super weird. this whole time I have been fighting with the code, I think I have a bug somewhere. Perhaps with the Demo entities but I cannot get it to report the current_position. Always shows 100. Did notice when moving the value would change but then return to 100 even though the attribute is at something else... ๐Ÿ˜•

#

If you would, keep that line in there for now. I'm going to finish the code assuming that it should work and then you'll have to test on your side to be certain.

tired comet
#

mine just shows a numerical value now instead of open or closede

light tinsel
#

Yeah. That's what I needed to see. At the end, you'll be able to get rid of that.

#

We're using it as a debug tool for the moment.

tired comet
#

yeah its nice to have for me to determine the mid point value of my blind

light tinsel
#

Yeah. That's the goal. I won't be able to test on my side though.

#

In theory, we might be able to expand this to add a hold_action for example and move it incrementally but that may take a bit more work...

tired comet
#

but mid point values are different when moving up and down ๐Ÿ˜ฆ

light tinsel
#

wouldn't 50 be the midpoint?

tired comet
#

that probably has to do with the calibration of my blind

#

the motors run for 60s each way until it is stopped by the limit which is hardware set

light tinsel
#

So, technically, your blinds only have an open or close? How to you stop them midway?

tired comet
#

cover.stop?

#

determining exactly midway is the issue. I have to deal with the calibration first

light tinsel
#

Okay. Well, I'll to you what. I have the code that can handle opening if it is closed, and closing if it is open. We can start with that and expand at some point.

tired comet
#

I will also use double_tab to change the direction if needed

light tinsel
#

With this code, I tried not to "step on" anything you've already written. The only change that it will need fixed is the entity:. I had to turn that into a variable in order to get it to pass in the action. I also used a double_tap_action to not interfere with your tap_ and hold_ actions that you already have. Just change the var_entity variable to your entity (cover.hall_cover).

#
variables:
  var_service: |
    [[[ 
      var pos = entity.attributes.current_position;
      if (pos == 0 ) return 'cover.open_cover';
      if (pos <= 100) return 'cover.close_cover';
    ]]]
double_tap_action:
  action: call-service
  service: '[[[ return variables.var_service ]]]'
  target:
    entity_id: '[[[ return entity.entity_id ]]]'
tired comet
#

I still dont understand entity: '[[[ return variables.var_entity ]]]'

#

wont I have to change that to fit my code?

#

since I already have entity defined in the beginnning>

#

type: custom:button-card entity: cover.hall_cover show_state: true

light tinsel
#

Yeah. Just remove your entity:, use my entity:, and set var_entity: cover.hall_cover.

#

This change was required to in order to make the entity_id in the target work because it would not pass as the built-in entity variable.

tired comet
#

ok understand now. Thanks!

gentle pulsar
#

You could just use entity.entity_id in the target instead of writing the entity into a variable

tired comet
#

where do use use this entity.entity_id?

light tinsel
#

That seems to work.

tired comet
#

type: custom:button-card entity: '[[[ return variables.var_entity ]]]' show_state: true name: Master Airwell Blind icon: |- [[[ if ((entity.state == "open") & (entity.attributes.position > "99")){ return "mdi:blinds-open"; } else if ((entity.state == "open") & (entity.attributes.position < "100")){ return "mdi:blinds"; } else if ((entity.state == "closed") & (entity.attributes.position < "100")){ return "mdi:roller-shade-closed"; } else if (entity.state == "opening"){ return "mdi:arrow-up-bold-box"; } else if (entity.state == "closing"){ return "mdi:arrow-down-bold-box"; } ]]] styles: icon: - color: | [[[ if (entity.state == "opening"){ return "orange"; } else if (entity.state == "closing"){ return "orange"; } else if (entity.attributes.moving == "STOP"){ return "grey"; } else { return "grey"; } ]]] card: - height: 90px name: - padding-left: 3px - font-weight: bold - font-size: 13px - justify-self: middle state: - font-size: 12px - padding-top: 2px - padding-left: 3px - font-weight: bold - justify-self: middle - color: darkgrey variables: var_entity: cover.master_inner_cover tap_action: action: call-service service: script.master_airwell_blinds_open hold_action: action: more-info

gentle pulsar
#

This btw far more cleaner and better optimized

entity: cover.hall_cover
double_tap_action:
  action: call-service
  service: >
    [[[ 
      var pos = entity.attributes.current_position
      if (pos == 0 ) {return 'cover.open_cover';}
      return 'cover.close_cover';
    ]]]
  target:
    entity_id: '[[[ return entity.entity_id ]]]'
light tinsel
#

I put them as variables for a reason for the time being. Both snippets of code work.

tired comet
tired comet
light tinsel
#

I normally just put them on separate lines but I think separated with a semi-colon would work in the actual JavaScript. If used in the variables: field, it has to be on separate lines.

tired comet
#

thats what really drives me nuts... not knowing these conventions=|

#

[[[ var pos = entity.attributes.current_position; if (pos == 0 ) return 'cover.open_cover'; if (pos <= 100) return 'cover.close_cover'; ]]]

#

how do you use Else if and else in javascript?

light tinsel
#

well, the card's code is handling the variables field but JavaScript within the [[[ ]]] is being processed by the browser (I think). When the card processes the variables field, it has to "follow" yaml rules.

#

just use else if and else.

#

Used in another project:yaml variables: humidity: | [[[ var humidity = states["sensor.bedroom_humidity"].state; if (humidity >= 60) return "high"; else if (humidity <= 30) return "low"; else return true ]]]

tired comet
#

or var pos = entity.attributes.position; var stt = entity.state?

light tinsel
#

I think you have to use the second one, but I could have swore that the first one would have worked too but I might be thinking of a different language.

tired comet
#

[[[ var pos = entity.attributes.position var stt = entity.state if ((stt == "closed") & (pos == 0 )) {return 'cover.open_cover';} return 'cover.close_cover'; ]]]

#

this works

gentle pulsar
#

If else with both a return can also be written with only the if like in the snippet I posted before

something: >
  [[[
    if(condition)
      return something
    return something_else
  ]]]
light tinsel
#

var pos = entity.attributes.position, stt = entity.state should work

#

So basically, the ELSE is assumed?

tired comet
#

something: > [[[ if(condition) return something else if(condition) return something return something_else ]]]

#

is this correct? I have multiple conditions

tired comet
gentle pulsar
# light tinsel So basically, the ELSE is assumed?

You could say it that way, but what it does is that each template stops rendering at the first return. If the condition is true, it reads the first one, when false it skips the condition statement and reads the second on

light tinsel
#

Okay. So return is also like "break" (break out of the code and be done)

gentle pulsar
tired comet
light tinsel
# tired comet I tried it but it didnt

This worked for me. Note that I defined pos and pos2 on the same line and used the pos2 variable for the IFs.yaml variables: var_service: | [[[ var pos = entity.attributes.current_position, pos2 = entity.attributes.current_position; if (pos2 == 0 ) return 'cover.open_cover'; if (pos2 <= 100) return 'cover.close_cover'; ]]]

light tinsel
#

But, if you're looking at incorporating the state to the service call variable, I do not think that is needed. That's why I mentioned working with just the position.

tired comet
#

I had an issue with multiple Ifs. because even if the 1st one is done. it will do the 2nd if. for nested if (if, elseif, else) it will stop when it finds a condition/or not

gentle pulsar
#

The use of return breaks the template, if you don't use a return then it will also evaluate the next condition even though the previous one was already true

light tinsel
#

Literally right there in the definition of return.

The return statement ends function execution and specifies a value to be returned to the function caller.

gentle pulsar
#

And therefore optimizes the computations needed

tired comet
#

thats a great reference!

#

thanks guys! learnt a lot๐Ÿ™

tired comet
gentle pulsar
#

Aren't the states not based on the position?

#

so closed is always 0 and open is between 1 and 100

tired comet
#

this is really for a 1 button operation. else, how would it determine whether to go up or down?

#

so for positions 1 to 99, depending on whether it is above 51 or below 52, it will close and open the blinds respectively

gentle pulsar
#

I guess this does exactly the same

service: |
  [[[
    var pos = entity.attributes.position
    var stt = entity.state

    if (stt == "closing" || stt == "opening"){
      return 'cover.stop_cover';}
    if (pos < 52){
      return 'cover.open_cover';}
    if(pos > 51 ){
      return 'cover.close_cover';}
    return 'cover.stop_cover';
  ]]]
#

And the icon can also be optimized

icon: |-
  [[[
    var attr = entity.attributes.position 

    if(entity.state =='open'){
      if(attr < 100){
        return "mdi:blinds";
      }
      return "mdi:blinds-open"
    }

    if (entity.state == "opening"){ 
      return "mdi:arrow-up-bold-box";
    }
    if (entity.state == "closing"){ 
      return "mdi:arrow-down-bold-box";
    }
    return "mdi:roller-shade-closed"
  ]]]