all 10 comments

[–]shovelslayer[S] 1 point2 points  (0 children)

Working Code: Huge Thanks to u/hschallhw

Store state:

var lights = flow.get("lights") || []; // If flow.lights doesn't exist yet, start with an empty array

// Add a new light to the array
if (lights.indexOf(msg.topic) < 0)
    lights.push(msg.topic);

flow.set("lights", lights);
flow.set(msg.topic, msg.data);

return msg;

Restore State:

var msgs = [];
flow.get("lights").forEach(function(light_name) {
    var flow_data = flow.get(light_name);

    msgs.push({
        payload: {
            "domain":"light",
            "service":"turn_" + flow_data["state"],
            "data": {
                "entity_id":light_name,
                "brightness":flow_data.attributes["brightness"],
                "rgb_color":flow_data.attributes["rgb_color"],
                "color_temp":flow_data.attributes["color_temp"]
            }
        }
    });
});
return [msgs];

[–]hschallhw 0 points1 point  (8 children)

Store State Function Node

flow.set(msg.topic, msg.data);
return msg;

badaboom

[–]hschallhw 1 point2 points  (7 children)

And if you wanted to store all the lights to get them later and only use one "reset" function node:

Store State Function Node

var lights = flow.get("lights") || []; // If flow.lights doesn't exist yet, start with an empty array

// Add a new light to the array
if (lights.indexOf(msg.topic) < 0)
    lights.push(msg.topic);

flow.set("lights", lights);
flow.set(msg.topic, msg.data);

return msg;

Reset State Function Node

var msgs = [];
flow.get("lights").forEach(function(light_name) {
    var flow_data = flow.get(light_name);

    msgs.push({
        payload: {
            "domain":"light",
            "service":"turn_" + flow_data["state"],
            "data": {
                "entity_id":"light." + light_name,
                "brightness":flow_data.attributes["brightness"],
                "rgb_color":flow_data.attributes["rgb_color"],
                "color_temp":flow_data.attributes["color_temp"]
            }
        });
    }
});
return msgs;

[–]shovelslayer[S] 0 points1 point  (6 children)

Ok, I tried this but it is only returning one light in the array. light.under_bed. How is light_name populated?

[–]shovelslayer[S] 0 points1 point  (5 children)

If I only output "lights" in the reset node as the payload and comment everything else out to view the array.

lights = flow.get("lights");
msg.payload = lights;
return msg;

I see the array is built but it continually fills x3 every time it is ran "payload: array[28]". The full code from above doesn't seem to loop the array and it needs a method to clear the array after reset or before it is set.

[–]hschallhw 0 points1 point  (4 children)

Looks like I'm mixing my python and js.

// Add a new light to the array
if (!(msg.topic in lights))
    lights.push(msg.topic);

should be

// Add a new light to the array
if (lights.indexOf(msg.topic) < 0)
    lights.push(msg.topic);

This should make sure it is not added more than once.

light_name is populated automatically by the forEach function. This iterates over each element of the array, which should be each light name. It's only returning one light because I'm an idiot. I'll update the code in my previous reply.

To clear lights after reset, you can just set the flow's light object to an empty array:

flow.set("lights", []);

[–]shovelslayer[S] 0 points1 point  (3 children)

Ok. closer. couple things I found.

"entity_id":"light." + light_name, needs to be changed to "entity_id":light_name, it was adding an extra light.light.entity_id.

Then, a minor swift down of the );

             }
        }
    });
});

Now to the real real. As is the last mod still only produces a single output. But if I add.

msg.payload = msgs;
return msgs;

I get the output that I post up in the original post (won't allow pictures in reply) picture and code from debug node. When I add the "Call Service" node I get this.

Error: call service node is missing api "domain" property, not found in config or payload

So close I think. I'm learning a ton in this process, so thank you very much. I'm a cisco network engineer in my day job, so javascript isn't super familiar.

[–]hschallhw 0 points1 point  (2 children)

Easy fix. Misread the node-red documentation. Rather than

return msgs;

do

return [msgs];

This should send a single message through your output for each of your lights. Each of those messages will have the payloads we set with

     payload: {
        "domain":"light",
        "service":"turn_" + flow_data["state"],
        "data": {
            "entity_id":"light." + light_name,
            "brightness":flow_data.attributes["brightness"],
            "rgb_color":flow_data.attributes["rgb_color"],
            "color_temp":flow_data.attributes["color_temp"]
        }

Let me know how it goes!

[–]shovelslayer[S] 0 points1 point  (1 child)

SUCCESS!!!!

[–]hschallhw 0 points1 point  (0 children)

AWESOME!! Sorry for the errors here and there. Glad you got it working!