Tagging @nayelyz
According to most sources, GPT4 can be helpful with programming, but also can produce totally unworkable code. It is unable to check its own work, it just produces something that looks like good code.
This problem is so persistent that many engineering forums have banned GPT produced answers, because less experienced programmers end up with code with severe flaws, and the experienced programmers are having to spend too much time checking offerings which look good but don’t work.
.
GPT4 is better at coding than the previous versions, but it still has the same basic flaws.
It can be a really useful tool for programmers, particularly to identify existing errors. And it’s also really quick to generate a lot of code which can then be reviewed by an expert. But it is not yet a really good substitute for programming skills.
It is certainly interesting.
Comparing device attributes to themselves is an intriguing way of making the rules trigger on new data. It kind of looks like it might actually work. It certainly makes more sense than using changes
on an operand
which is the way I’ve seen it suggested it can be done, despite that being completely at odds with the documentation.
Using the device attribute value in a command
argument as it does can apparently be done so that might work.
The one I’ve not seen before is using the on
or off
attribute value of the switch as the command
. I like that a lot. I hope it works.
Apart from having a bit lopped off the end, it actually looks like a rather elegant solution to the problem if you can actually do those things in practice.
Sometimes I make posts that are irrelevant.
Hi, @RJGill84
The colorControl capability is tricky, so, I created a sample, I just tested it and it worked on virtual devices that include it:
{
"name": "Changes - colorControl",
"actions": [
{
"if": {
"changes": {
"operand": {
"device": {
"devices": [
"device1-id"
],
"component": "main",
"capability": "colorControl",
"attribute": "saturation"
}
}
},
"then": [
{
"command": {
"devices": [
"device2-id"
],
"commands": [
{
"component": "main",
"capability": "colorControl",
"command": "setColor",
"arguments": [
{
"map":{
"hue": {
"device": {
"devices": [
"device1-id"
],
"component": "main",
"capability": "colorControl",
"attribute": "hue"
}
},
"saturation": {
"device": {
"devices": [
"device1-id"
],
"component": "main",
"capability": "colorControl",
"attribute": "saturation"
}
}
}
}
]
}
]
}
}
]
}
}
]
}
Note: Currently, the widget in the app that allows us to select a color uses the command “setColor” and it gets the values of “hue” and “saturation” as the arguments, therefore, we need to save them in the corresponding attributes, that’s why this Rule is based in the change of one of them.
The attribute “color” is no longer used in the app to define a color.
I can accept that this construct works but please can the documentation be sorted out to explain why. The API Reference clearly states that changes
is ‘A condition that returns true when its evaluation resolves to true and the previous evaluation resolved to false.’ How does the operand
evaluate to either true or false?
In the documentation of Rules, there’s another description:
" changes
is a Condition that tracks the state of the operation it contains, returning true when the state of the inner operation transitions from false to true."
This gives the understanding that when the current state of the device is not the expected one according to what we set in the “operation” inside “changes”, then, it remains false. Otherwise, when an event is received and it matches the content of the “operation”, it will become true.
In the case of “operand”, we’re checking if the device got something on that specific capability and attribute, it can be any value. That’s why it is useful in this case because other conditions need a specific value to compare with the new event.
I’ll check with the team if they can provide more info about it, what I shared above is my understanding of how it works based on my tests.
This is interesting because it would allow doing device behavior sync’ing by just determining if there had been a change to some capability of the device. And unfortunately, it’s not exposed in the Routines for things like dim level where it would be nice to know that it had simply changed and not changed to some specific value, range, etc. like what is implemented currently.
Despite both using the same back end (Rules engine), there must be something that allows the interpretation between what the user selects and what it means in the Rules API language, in the case of the options you mention, adding them to the Routines tool would be a feature request. I created one for mirror behavior a while back, but I haven’t got any response, I’ll include your comment there.
I know I’ve been badgering you for years about this issue, but I think at last I see what is going on. The confusion is not caused by changes
but by operand
.
There is absolutely no description of operand
in the Documentation or the API Reference. All we are told is that it contains an ‘Operand’ object.
If operand
is an ‘Operand’ that returns true if the current event is relevant to its content then the failure to document it as such is right up there with the biggest failures that SmartThings has ever had. It is of absolutely colossal importance to the understanding and creation of Rules.
One of the strengths of webCoRE pistons is that they could target their response specifically to the event that caused the piston to run. Now it turns out that similar functionality has been hiding in plain sight in Rules for ages.
It rather sounds like it is in fact possible to know when a Rule was activated by a specific button being pressed. That in itself is game changing.
I am now kicking myself for not realising what was going on.
I fully appreciate that there has to be something that translates the UI representation into the backend rules. What is disappointing is that the ability to trigger on dim level is a recently added feature and one would think that they would have taken into account all the triggering cases in the Rules and built those into the UI. They clearly thought of equals, greater than, less than, and in a range. Seems like it would have been easy to have also added a simple “Changes” to the list.
Thank you for the code sample @nayelyz
I provided your reply to ChatGPT and it rewrote the code based on your suggestions. I find its responses just as interesting as the code.
{
"name": "Sync Hue, Saturation, Brightness, and On/Off",
"actions": [
{
"if": {
"changes": {
"operand": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "colorControl",
"attribute": "saturation"
}
}
},
"then": [
{
"command": {
"devices": [
"bulb-1-id",
"bulb-2-id",
"bulb-3-id"
],
"commands": [
{
"component": "main",
"capability": "colorControl",
"command": "setColor",
"arguments": [
{
"map": {
"hue": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "colorControl",
"attribute": "hue"
}
},
"saturation": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "colorControl",
"attribute": "saturation"
}
}
}
}
]
}
]
}
}
]
}
},
{
"if": {
"changes": {
"operand": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "switchLevel",
"attribute": "level"
}
}
},
"then": [
{
"command": {
"devices": [
"bulb-1-id",
"bulb-2-id",
"bulb-3-id"
],
"component": "main",
"capability": "switchLevel",
"command": "setLevel",
"arguments": [
{
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "switchLevel",
"attribute": "level"
}
}
]
}
}
]
}
},
{
"if": {
"changes": {
"operand": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "switch",
"attribute": "switch"
}
}
},
"then": [
{
"command": {
"devices": [
"bulb-1-id",
"bulb-2-id",
"bulb-3-id"
],
"component": "main",
"capability": "switch",
"command": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "switch",
"attribute": "switch"
}
}
}
}
]
}
}
]
}
What are your thoughts on this version @orangebucket?

What are your thoughts on this version @orangebucket?
Less interesting than the first one but probably a better bet. What I remain suspicious of is this bit:
"then": [
{
"command": {
"devices": [
"bulb-1-id",
"bulb-2-id",
"bulb-3-id"
],
"component": "main",
"capability": "switch",
"command": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "switch",
"attribute": "switch"
}
}
}
}
]
}
What it is trying to do is use the current attribute value of the master device, i.e. on
or off
, as the name of the command to issue to the devices being synced, again on
or off
. If it works it is a thing of beauty, but although it may work for the values of arguments, I have never seen it used like this and I couldn’t get it to be accepted when I tried it.
I should add that my not having seen it done before really isn’t remarkable. As with many things SmartThings, my theoretical knowledge far exceeds my practical requirements.

What it is trying to do is use the current attribute value of the master device, i.e.
on
oroff
, as the name of the command to issue to the devices being synced, againon
oroff
. If it works it is a thing of beauty, but although it may work for the values of arguments, I have never seen it used like this and I couldn’t get it to be accepted when I tried it.
@orangebucket ChatGPT provided me with this updated code for on/off based on your feedback:
{
"name": "Sync Hue, Saturation, Brightness, and On/Off",
"actions": [
// ... (hue, saturation, and brightness syncing actions)
{
"if": {
"changes": {
"operand": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "switch",
"attribute": "switch"
}
}
},
"equals": "on",
"then": [
{
"command": {
"devices": [
"bulb-1-id",
"bulb-2-id",
"bulb-3-id"
],
"component": "main",
"capability": "switch",
"command": "on"
}
}
]
}
},
{
"if": {
"changes": {
"operand": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "switch",
"attribute": "switch"
}
}
},
"equals": "off",
"then": [
{
"command": {
"devices": [
"bulb-1-id",
"bulb-2-id",
"bulb-3-id"
],
"component": "main",
"capability": "switch",
"command": "off"
}
}
]
}
}
]
}
I think it is getting a bit colder now as changes
is a boolean and equals
doesn’t work anything like that. The way it is normally done would be something like …
"then": [
{
"if": {
"equals": {
"left": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "switch",
"attribute": "switch"
}
},
"right": {
"string": "off"
}
},
"then": [
{
"command": {
"devices": [
"bulb-1-id",
"bulb-2-id",
"bulb-3-id"
],
"commands": [
{
"component": "main",
"capability": "switch",
"command": "on"
}
]
}
}
],
"else": [
{
"command": {
"devices": [
"bulb-1-id",
"bulb-2-id",
"bulb-3-id"
],
"commands": [
{
"component": "main",
"capability": "switch",
"command": "off"
}
]
}
}
]
}
}
]
Thanks for going back & forth with me on this. It suggested this in response to your post:
{
"name": "Sync color, brightness, and on/off from master bulb",
"actions": [
{
"if": {
"changes": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "switch",
"attribute": "switch"
}
},
"then": [
{
"if": {
"equals": {
"left": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "switch",
"attribute": "switch"
}
},
"right": {
"string": "on"
}
},
"then": [
{
"command": {
"devices": [
"bulb-1-id",
"bulb-2-id",
"bulb-3-id"
],
"commands": [
{
"component": "main",
"capability": "switch",
"command": "on"
}
]
}
}
],
"else": [
{
"command": {
"devices": [
"bulb-1-id",
"bulb-2-id",
"bulb-3-id"
],
"commands": [
{
"component": "main",
"capability": "switch",
"command": "off"
}
]
}
}
]
}
}
]
}
},
{
"if": {
"changes": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "colorControl",
"attribute": "hue"
}
},
"then": [
{
"command": {
"devices": [
"bulb-1-id",
"bulb-2-id",
"bulb-3-id"
],
"commands": [
{
"component": "main",
"capability": "colorControl",
"command": "setColor",
"arguments": [
{
"map": {
"hue": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "colorControl",
"attribute": "hue"
}
},
"saturation": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "colorControl",
"attribute": "saturation"
}
}
}
}
]
}
]
}
}
]
}
},
{
"if": {
"changes": {
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "switchLevel",
"attribute": "level"
}
},
"then": [
{
"command": {
"devices": [
"bulb-1-id",
"bulb-2-id",
"bulb-3-id"
],
"commands": [
{
"component": "main",
"capability": "switchLevel",
"command": "setLevel",
"arguments": [
{
"device": {
"devices": [
"master-bulb-id"
],
"component": "main",
"capability": "switchLevel",
"attribute": "level"
}
}
]
}
]
}
}
]
}
}
Are we getting warmer or is it just veering off course now?
EDIT: Sorry, posted the wrong one initially.
I am not seeing anything that I’d do any differently if I was writing it. If it doesn’t work it is certainly a good attempt.
Sadly there seems to have been syntax errors of some kind as the Rules API was complaining about the device field being unrecognized. After several revisions, I went back to the drawing board and started a new chat - and was presented with this code. It works perfectly and syncs the bulb colors - but it does NOT sync the brightness level or on/off.
Thats OK really because I can do that with SmartLighting. PROBLEM SOLVED! The moral of the story here is: customers shouldn’t have to resort to artificial intelligence to hack together a solution to something simple like color coordination, that is available in every platform other than SmartThings.
{
"if": {
"changes": {
"operand": {
"device": {
"devices": [
"Master-Bulb"
],
"component": "main",
"capability": "colorControl",
"attribute": "saturation"
}
}
},
"then": [
{
"command": {
"devices": [
"Slave-Bulb-1",
"Slave-Bulb-2",
"Slave-Bulb-3",
"Slave-Bulb-4",
"Slave-Bulb-5"
],
"commands": [
{
"component": "main",
"capability": "colorControl",
"command": "setColor",
"arguments": [
{
"map": {
"saturation": {
"device": {
"devices": [
"Master-Bulb"
],
"component": "main",
"capability": "colorControl",
"attribute": "saturation"
}
},
"level": {
"device": {
"devices": [
"Master-Bulb"
],
"component": "main",
"capability": "switchLevel",
"attribute": "level"
}
},
"hue": {
"device": {
"devices": [
"Master-Bulb"
],
"component": "main",
"capability": "colorControl",
"attribute": "hue"
}
},
"switch": {
"device": {
"devices": [
"Master-Bulb"
],
"component": "main",
"capability": "switch",
"attribute": "switch"
}
}
}
}
]
}
]
}
}
]
}
}
Just curious: what’s the state of smartthings lighting groups these days?
Can you include them in Scenes?
Are they actionable with a rules API?
If so, that might offer some other alternatives. I know the functionality on these has been changing, I just haven’t kept up with it.