CoRE and Piston Rules Engine, first design steps

This SmartApps menu… Is it pressing the three line symbol upper right corner and then click SmartApps? If I do this, clicking done after setting up Piston exits CoRE as well. Same behavior if accessed from marketplace.

Yeah, that’s something that started happening on Android a few days ago. I’ve downgraded down to v0.0.030 to test and it does the same thing. So it must be something with ST’s Android app. There is no error anywhere… This must be related to CoRE being both the parent and its own child. Used to work fine, it may be a temporary thing, like my Sonos not being able to playText for a few days (error on ST’s part) and then started working just fine, on its own. I’ve learned to not panic the first time around, just wait it out for a few days…

Oh. I almost called 911 :yum:

3 Likes

Last night I was getting a screen capture of my SmartApps screen when I select the camera icon, not the rule. Today I get nothing

Rick

Hi Adrain,

3 doors to control 2 lights. If any door opens, turn on both light and eventually turn off both lights

The use case does get more complicated if any door is already open after the sunset trigger but I am not going there now :slight_smile:





Rick

Hrmm. Rule Machine went through the same thing for a period of time, I was thinking it was something in the program, but that doesn’t eplain you rolling back to way earlier version of CoRE

You can try yourself. Go to github and choose any old old version and save it into the IDE. Then open a piston and hit Done - it still goes out - and may screw up stuff on the piston :slight_smile: but then revert to latest and open the piston again and click Done to “fix” it.

I didn’t follow the thread, so I don’t know what you guys are doing. Opening an internal preview browser is enormously painful code-wise and was a cause of much grief. We almost fully migrated away from that pattern in SmartTiles.

I encourage you to try something else and check with @slagle and @jody.albritton on the status of the Android UI fix that would allow you to open links in external browser properly.

3 Likes

Brilliant… thank you…

This is really incredible… already a lot more powerful and informative than RM… although I suspect not as easy to use for the average user. I’ve already found some of the additional grouping functionality useful. Keep going!

The plan is to dumb it down when Expert mode is off. But yeah, versatility and friendly are not good neighbors.

2 Likes

The problem Toasty is having is that Android opens “external” hrefs in a web wrapper within the ST app. In a hurry, I made a screen capture of a piston “image” that generates a data URL of a png representing that image. I then open that in a new tab (easiest way at that time) so that people can hold click and save it, then post it here on the forum. iOS works fine as it really opens the link in Safari. Android won’t allow that “open new tab” so @Toasty can’t really save the image. I’ll make it display in an internal div with an img tag and then that problem is gone. The second problem is he can’t really open the dashboard in a browser unless he goes into the logs to pick up the URL. I need to display the URL in one of the pages there, possibly in a disabled text area, so he can copy it and paste it into the browser’s address bar. Also easy to fix. Other than that, the ST wrapper works pretty good. I have just a dumb html hosted on the SmartApp that provides the framework (all javascripts and css to load). The rest of the code is in a CDN hosted on a server I am paying for, but will be moved to rawgit as soon as changes quiet down. No server-side code whatsoever, all code is in client. AngluarJS rulz.

1 Like

v0.0.063.20160603 - Alpha test version - Save/Load state seems to work. LOL. Local state is piston-wide, global state is across all pistons. Each device gets one state stored locally (one per piston) and one stored globally.

Bit of background:

State variables are a different kind of variables that contain pairs of attribute:value. You can save the state of a list of devices into a single variable by using aggregation. Haven’t thoroughly tested that yet. Data type should be pretty automatic there, so if you do the avg of switch, power and energy, the switch should stay a string (the most common in the list), while power and energy should get their mathematical avg. But I digress…

There are in total 4 save tasks and 4 load tasks. The save gets the value from a device (or a list of devices) and “saves” it into a variable. The load gets the value from a variable and “loads” it into the device. If anyone wants to rename these to Capture/Restore, I can do that (I believe there was a poll that pointed out this way). Give load/save a chance and if it’s a no go, we’ll rename them. Poll to follow soon.

The 4 methods are different:

  1. Save attribute to variable - use this to get the value of an attribute into a variable that you can later use anywhere in the piston. Scalar value, meaning there is one single value stored into that variable. The variable can be local or global. You know the drill.

  2. Save state to variable - use this to get a list of attributes and their values into a state variable that you can later use with the Load state from variable - these values are not yet available anywhere else in the CoRE.

  3. Save state to local store - forget about variables, we don’t need them :slight_smile: This automatically creates a variable for each device in the list, so you don’t need to worry about variable naming. And forget about aggregation, because if you save the state of 5 devices, they are stored into 5 different state variables. Clean and dirty. Use the Load state from local store to restore whichever attributes you want for each of the devices selected.

  4. Save state to global store - just like #3, but it uses a global store instead - this means that you can save the state of a device in one piston and then later use a different piston to load that state back into the device. Magic :slight_smile:

For options 1) and 2), the save tasks provide an aggregation method - this only applies when there’s more than one device in the list, obviously. The load tasks provide two parameters to allow translations. Sometimes, you’ll want to save the state of a door into a variable and then load the state of a switch from that variable. This is where translation comes into play, because while the door may be “open”, I can’t set a bulb to that. So everything is translated into booleans. There is a list somewhere above that describes the list of values for true and false. There is also a Negate translation which allows you to change the meaning of open and closed to their reverse.

Enjoy and be gentle if you find bugs… I’ve done the minimal testing, as usual.

Possible issues: loading state from a variable may not show the updated list of state variables.

NOTE: Be cautious when loading multiple attributes from a state, especially with lights. You will soon find out that loading level, hue, saturation, color, colorTemperature and switch all at the same time may not yield the expected results because… color sets all of level, hue and saturation, switch may also change color with some DTHs, colorTemperature sets your color to white, etc. To try and help with this, I am sorting the list of attributes alphabetically so that switch comes after level. But, it may not always do the trick due to the mesh nature of the network. Best to limit your use to a certain attribute, or attributes that don’t mutually affect each other. How do I make this DOUBLE BOLD? Or triple?

#documentation for @bamarayne

1 Like

Quick question on Then-If’s…which if does the else correspond to? Which is the correct logic?

A)

if (something) {
  do this 
  if (something) {
    then do this
  } else {
   otherwise do this
  }
}

or B)

if (something) {
  do this 
  if (something) {
    then do this
  }
} else {
   otherwise do this
}

External links on Android have been broken since day one. This bug survived complete app rewrite. Twice. Keep pocking @jody.albritton and @slagle to get it fixed.

2 Likes

I had a mental debate on that and I ultimately ended up with having the Else run if any of the two IFs is false.

Generally, the way the evaluation works is, I evaluate the one (or two, for most piston types) conditional sets (primary and secondary). Based on that, I then determine the state of the piston, based on the piston type. The Else is hardwired to the state evaluating to false. So the Else runs when the piston is false. Which is why I had to choose the way I chose.

documentation

Tough effing bug, huh? :slight_smile: I wish humans were this tough too…

1 Like

No, that’s abuse of CTRL + C and CTRL + V and lack of QA.

3 Likes

Okay, so it’s really more like:

if (something) {
  do this 
  then if (something) {
    then do this
  } else {
   runElse()
  }
} else {
  runElse()
}
runElse() {
  otherwise do this
}

Correct.

Else runs:

  • Simple: IF is false
  • Latching : never
  • Then-If: (IF is false) OR (THEN IF is false)
  • Else-If: ELSE IF is false
  • And-If: (IF is false) OR (AND IF is false)
  • Or-If: (IF is false) AND (OR IF is false)
  • Follow-Up: IF is false

A more appropriate name for it would be Finally - just like in the try…catch/finally block.

1 Like

Coming at this from a user stand point… If both are false, then the piston should not run.

As a user when a rule evaluates true, then it should do stuff. If it’s false, don’t do stuff.

This is the one thing about CoRE that I think is thrusting people way off.

To a user …

True = on
False = off

1 Like