Use the node red values in Python

Hello,

I can not find a solution how I can process the values from Node-Red in a Python script.
Here, I get the X & Y coordinate from a Siemens CPU (317F) over a OPC UA Server to my Raspberry

The coordinates are in the payload. At the moment I wirte the coordinates in two different text files. The values are overwritten every 2 seconds.
Now I'm trying to integrate the values into a Python script.
Is it necessary at all that I write the values for it in text files or is there any other option like a block that provides the values?
With the script I want to start a video recording automatically after starting the Pi and the coordinates should be integrated as text / subtitles in the video.

Here is my actual python-script:

  1. from picamera import PiCamera
  2. from time import sleep
  3. import datetime
  4. dateipfad = "/home/pi"
  5. dateiname = datetime.datetime.now().strftime('%Y.%m.%d-%H%M%S')
  6. videodatei = f"{dateiname}.h264"
  7. print(videodatei)
  8. camera = PiCamera()
  9. camera.start_preview()
  10. camera.start_recording(videodatei)
  11. sleep(10)
  12. camera.stop_recording()
  13. camera.stop_preview()

Thanks for any help!

Best Regards

No, no, no, use MQTT instead to integrate NR with Python. Works excellent and fast
Need help? Google or ask questions here. Share the code of your python script (or part of it) and I or other users will help. Also share the exact output from the OPC UA Client nodes (the messages holding the coordinates to be used)

1 Like

We are currently unable to switch to MQTT. We bought an OPC-UA server especially for this. Is there no way to implement it with OPC-UA? I hope that it can't be that difficult to read or use the value from a text file with Python :expressionless:

You can call a python script several ways from NR - using the exec node, node-red-node-daemon or one of the 'python contrib nodes which I'm sure you have searched and evaluated.

So in regards to your your question is "How do I pass paramerters to a python program from Node-RED" It depends on how you are doing it.

After reading the readme's for each method you should be able to try passing something to a simple python program to get familiar with what it takes. If you get stuck, paste a copy of an export of your little test flow and indicate where you are having an issue.

@gragtoni435
You write "I can not find a solution how I can process the values from Node-Red in a Python script."

From this and the information given in the picture etc, I assume your system structure would be like this: OPC UA Server <----> NR(OPC UA Client -> File) -----> Python (Reading file, processing)

What I suggested is a structure like below where you use MQTT, you are not switching to, you keep the OPC server and OPC client connections in NR as is, you just send the data to the python script via MQTT, instead of writing to a file
OC UA Server <----> NR(OPC UA Client -> MQTT out) -----> MQTT Broker -----> Python (MQTT Client, processing)

You can run the broker in the same pi as NR. Besides, writing to a file as an interface is very inefficient and will also wear out your sd card at some time if you write frequently to it

aaaaaah okay.
Now I think I understand the idea.
I have installed MQTT on my Pi.
If I understand it right, I have to take a "mqtt in" and a "mqtt out" between the OPC UA Clients and the msg, haven't I?
Like on this picture

But how can I then query the values in my Python script?
I think this is the easiest command to get the text in the video.
camera.annotate_text = "text"

But how get I the informations from the MQTT in this line?

Hello again,

After many more searches, I continued a little.
Hier der aktuelle Status:


Now I have the MQTT connection in node red. I tested it in a small flow, it worked perfectly there. But in this flow the lower msg.payload receives no data.
Only the upper one receives the position data from the OPC-UA client continuously.
The debug window for the lower payload is always empty. Why?
The upper one receives the news updated every second as normal.

Zum weiteren habe ich die Abfrage mal mit diesem Programm hier getestet:


Es wird auch kein Fehler im Script angezeigt aber wie man sehen kann, ohne Werte kommt eben auch kein Wert hier raus.

Kann mir bei den Problem jemand helfen? Fehlt mir ein spezieller Baustein der von OPC-UA auf MQTT umwandelt ?

Thanks for any help! :innocent:

Some basics first

In MQTT you work with topics, it is similar to "Postfach"

When you send data via MQTT you publish it to a specific topic. If you are interested to receive this data you subscribe to the same topic

In the flow where you are checking this, it is therefore very important that you publish to the same topic as you subscribe to

In the test python script you show, are you subscribing to the same topic that you publish to?

@krambriw Walter, just to clarify, if I'm not mistaken, your suggestionn will require that the python script be running constantly because it will be waiting for a MQTT msg to arrive. In addition the python code needs to subscribe to the same topic that the NR MQTT-out is using.

If the NR flow needs acknowledgment that the python code got the msg, then the python code will have to publish a msg using a mqtt topic and the NR flow will have to subscribe to that topic to receive the acknowledgement.

1 Like

Yes, you are absolutely correct in all you say. I just thought best to take it step-wise since the user seems new to MQTT. Currently the subscription seems to be the (first) blocking point

First thing to solve is to check that the subscription to the same topic works in NR as the user already is trying but failing

The final python script will for sure have all those parts included but it is not a big concern, done it maybe 100 times :wink:

Ahhh, but has the OP? Everything is easy once you have done it a 100 times :joy:

I am willing to write that script for the OP, I have already many good "templates" in my own system running since years

2 Likes

It works! :partying_face:
I adjusted the topics everywhere and now I have the X and Y values in the Python script.
Now the last problem is, that I need the values as text in the video.

Do i need every of this commands? Or can I delete some of this, which are not required?

I want the msg.payload in the line "camera.annotate_text" so that the current values can always be seen in the video. How can I do that?
Is the easiest way to use a for-loop, that updated every e.g. 2 seconds the values?
The video will be very long, 2-3 h for example.

def on_message(client, userdata, msg):
    global camera
    global videodatei
    print(msg.payload)
#    camera.annotate_text = "whatever"
    camera.annotate_text = str(msg.payload)
    camera.start_preview()    
    camera.start_recording(videodatei)
    time.sleep(15) #Don't forget to add the line "import time" in the beginning of the script!!!
    camera.stop_recording()
    camera.stop_preview()    

As the above is an example just to test if it is working, I think there might be some more logic needed. Suppose the recording is already ongoing and you receive a new message (with updated text). What should happen? Maybe the text gets updated? Should the recording stop and then restart?

To be able to check if the recording is already ongoing some more stuff needs to be added. But try the above example first so we can verify if that part works or not

Okay, here are my scripts:

  1. The script is for automatic video recording when the Pi starts. The name file is associated with the time so that the files do not overwrite. The time is only 10s for testing. At the end it is something like 3h, but this doesn`t matter at the moment.
from picamera import PiCamera
from time import sleep
import datetime


dateipfad = "/home/pi"
dateiname = datetime.datetime.now().strftime('%Y.%m.%d-%H%M')
videodatei = f"{dateiname}.h264"
print(videodatei)
camera = PiCamera()
camera.start_preview()
camera.start_recording(videodatei)
sleep(10)
camera.stop_recording()
camera.stop_preview()

  1. Then after getting the connection in Node-Red, I took this script for testing. Here you can always see that the two values (in this case X coordinate: 3 and Y: 10) are constantly transmitted every second in the payload.
import paho.mqtt.client as mqtt

def on_connect (client, userdata, flags, rc):
    print("connected with result code" + str(rc))
    
    client.subscribe("positions/#")
    
def on_message(client, userdata, msg):
    print(msg.payload)
          
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect("localhost", 1883, 10)
client.loop_forever()

Is it better to load the coordinates in different payloads so that you can distinguish them?
Does the payload actually overwrite itself, meaning that only the later value is still there? or can both values be in the payload?
At the moment node-red is like that:

So now I've tried the script above. Not even a video recording is started here :frowning:
Here is the first try.

from picamera import PiCamera
from time import sleep
import datetime
import paho.mqtt.client as mqtt


dateipfad = "/home/pi"
dateiname = datetime.datetime.now().strftime('%Y.%m.%d-%H%M')
videodatei = f"{dateiname}.h264"
print(videodatei)
camera = PiCamera()

def on_connect (client, userdata, flags, rc):
    print("connected with result code" + str(rc)) 
    client.subscribe("positions/#")  
def on_message(client, userdata, msg):
    global camera
    global videodatei
    print(msg.payload)
    camera.annotate_text = str(msg.payload)
    camera.start_preview()
    camera.start_recording(videodatei)
    sleep(15)
    camera.stop_recording()
    camera.stop_preview()
    
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("localhost", 1883, 10)

As the above is an example just to test if it is working, I think there might be some more logic needed. Suppose the recording is already ongoing and you receive a new message (with updated text). What should happen? Maybe the text gets updated? Should the recording stop and then restart?To be able to check if the recording is already ongoing some more stuff needs to be added. But try the above example first so we can verify if that part works or not

The updated text (X/Y-coordinates) should be constantly updated in the video

I am happy for any help! :innocent:
We want to test it tomorrow. I think today will be a long night. :thinking:

In the last example I miss the line "client.loop_forever()". Without it, you will not receive any messages

Does the recording start with your script 1) ??

Script 1 is just my booth before I connect Node-Red. Now I'm trying to combine Script 1 with 2 so that it works as intended.
Now with the line it works.
But now a video is recorded for 15 seconds with the b10 as text in the video. After the 15 seconds the next recording starts with b3 as text
But both values should be displayed ..

from picamera import PiCamera
from time import sleep
import datetime
import paho.mqtt.client as mqtt


dateipfad = "/home/pi"
dateiname = datetime.datetime.now().strftime('%Y.%m.%d-%H%M')
videodatei = f"{dateiname}.h264"
print(videodatei)
camera = PiCamera()

def on_connect (client, userdata, flags, rc):
    print("connected with result code" + str(rc)) 
    client.subscribe("positions/#")  
def on_message(client, userdata, msg):
    global camera
    global videodatei
    print(msg.payload)
    camera.annotate_text = str(msg.payload)
    camera.start_preview()
    camera.start_recording(videodatei)
    sleep(15)
    camera.stop_recording()
    camera.stop_preview()
    
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect("localhost", 1883, 10)
client.loop_forever()

What does this b mean? In Node-Red I see only the value and not the b

The b means buffer so you need to decode it to get the actual text. Typically you would do

    print(msg.payload.decode("utf-8"))
    camera.annotate_text = str(msg.payload.decode("utf-8"))

This is what happens:
When you send a message to the script it takes the text in the msg.payload and puts it in the video view. Next the recording and viewing starts and the script goes into sleep. During the sleep the script will NOT receive any additional messages, they will be kept in the MQTT broker. When the sleep is over, recording and viewing is stopped and the message kept in the MQTT broker is received. The whole thing is starting over now with the new text received.

So your wish to present both values cannot be fulfilled in this way. You have to do it differently. You have to send both values in the same message, not as two separate messages.

Are you fully sure you feel enough comfortable working in Python? Or is this getting too complex?

OK. Thank you.
Yes, I already understand how the current script works and that it just doesn't work the way I want it to.
But unfortunately I myself have no idea how I have to realize that it just works as intended.
If you could help me here, I would be very grateful.
At the moment I find everything in python understandable & logical.