Restart NodeRED After PAC Control Download

Is there anyway to restart Node-RED (or, more accurately, restart Node-RED flows) every time I do a download from PAC Control?

Before I think too much more about this… you just gotta know I’m going to ask… why?

Unfortunately, the answer is probably some bad programming in some custom nodes I’ve written. I’ve written a few nodes that are called periodically that rely on some specifically named variables in my control strategy. I’ve noticed that sometimes when I do a download, these nodes will essentially hang. Restarting Node-RED fixes the problem. I’m also working to include better error handling in the nodes themselves, but being able to restart the flows (which is really what I want, not restarting the entire runtime) would be a quick fix.

Ah, Ok, that makes sense now.
Thanks for the clear explanation. (I would be putting a catch node in and recording any errors - to a local file perhaps - to see whats going on).

I think the best way to do this is to put in the powerup chart in PAC Control an API call to the Node-RED admin.
https://nodered.org/docs/api/admin/
You will most likely need this call here:
https://nodered.org/docs/api/admin/methods/post/flows/

I don’t have time to spin up some sample code (got new groov family hardware on my desk to test), but you will need to dig into the httpget command with the key etc.

@Beno: thanks for pointing me in the right direction. I should be able to manage that.

1 Like

So I’m trying to go down the route mentioned by @Beno and send an HTTP request to the Node-RED Admin API on my Groov EPIC PR-1. For now, I’ve created a simple PAC strategy that only has one block and I’m attempting to GET “/auth/login” as described here.

Here’s my OptoScript code:

HttpGet(st_ResponseContents,
        st_ResponseHeaders,
        st_GetHeaders,
        1,
        "/node-red/auth/login",
        i_HTTP,
        443,
        "127.0.0.1");

Every time I run the code, I get an HTTP status of 500 no matter what I do. I’m sure I’m forgetting something stupid, but I can’t for the life of me figure out what it is. All three string tables remain empty after the GET request.

I’ve tried various paths:

  • /node-red/auth/login
  • /auth/login

I’ve tried both localhost and 127.0.0.1 for the hostname and nothing has made a difference so far.

Edit: Looks like my HttpGet function call is returning -2008, which I’m assuming is an SSL certificate error. I still don’t know how to fix it, but it’s an extra piece of information.

Edit 2: I added the self-signed certificate in Groov Manage, and that resolved one error. Now I’m getting a 401 error saying that I have to login before I can access that page. Any tips on how to login would be great.

Edit 3: Figured out that I had to add an apiKey header to my GET request.

If anybody else is interested, here’s what seems to be working for me. I created a subroutine called RestartNodeRED. It accepts one parameter, the API key of a user with appropriate permissions. Here’s the code of the subroutine:

// Prepare request.
st_SourceContents[0] = "[]";

// Create headers.
st_SourceHeaders[0] = "Host: localhost";
st_SourceHeaders[1] = "Content-Type: application/json";
st_SourceHeaders[2] = "apiKey: " + s_Key;
st_SourceHeaders[3] = "Node-RED-Deployment-Type: reload";
HttpPostCalcContentLength(st_SourceContents, st_SourceHeaders, 4);

// Clear response fields.
MoveToStrTableElements("", 0, -1, st_ResponseContents);
MoveToStrTableElements("", 0, -1, st_ResponseHeaders);

// Submit request.
i_Status = HttpPostFromStringTable(st_ResponseContents,
                                   st_ResponseHeaders,
                                   st_SourceContents,
                                   st_SourceHeaders,
                                   1,
                                   "/node-red/flows",
                                   i_HTTP,
                                   443,
                                   "localhost");

// Return true if POST successful and appropriate status code returned.
if (i_Status == 0 and i_HTTP == 204) then
  SetVariableTrue(b_Result);
else
  SetVariableFalse(b_Result);
endif
1 Like

Fantastic!
Thanks for following up and for sharing the code.
Really appreciate that!