Use the node red values in Python

(Slight correction, the b here stands for a bytes string. They’re pretty comparable looking at it from a JavaScript perspective, but in any python documentation you’d see the word bytes used for it. The rest of the information provided here however is spot on!)

1 Like

You can combine the two values in NR before you send the message to the Python script (using the join node) or put them together in the script before you do annotate and start recording and viewing

I assume this is what is missing?

Tomorrow morning I can show you, now is a bit late

I used the join module to combine the messages in Node Red. Now, as shown in the picture, the X coordinate and then the Y coordinate with a line break arrives in a message.


It also works in the video. :slight_smile:

Now the function is missing that the values are constantly updated. Maybe with a While True loop?

Thank you for your efforts!
I keep trying to somehow manage that. We want to test it on the reserved machine tomorrow morning. So I have to keep trying to ensure that the current values are always displayed.
I am happy about every possible little food for thought how you can achieve this.

God damn it, I thought I got it with the following script:

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%S')
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
    camera.start_preview()
    camera.start_recording(videodatei)
    i = 1
    while i < 9999:
        client.on_connect = on_connect
        print(msg.payload.decode("utf-8"))
        i += 1
        camera.annotate_text = str(msg.payload.decode("utf-8"))
        sleep(1)
    sleep(10)
    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()

I thought so it works, but since I do not change the position data to control it, I made a small change to node red accordingly to simulate it.
In the picture you can see that I have changed the payload from 4 to 5 to see whether the program running alongside also notices the change.
But unfortunately no, the value 4 remains

If the command "client.on_connect = on_connect" in the While Loop is not queried for the current value? Or how is that done?

Ok, here is my last status for today.

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%S')
videodatei = f"{dateiname}.h264"
print(videodatei)
camera = PiCamera()

def on_position(msg):
    rt = (msg.payload.decode("utf-8"))
    print(rt)
    return rt
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
    camera.start_preview()
    camera.start_recording(videodatei)
    i = 1
    while i < 9999:
        print(i)
        on_position (rt)
        print(rt)
        i += 1
        camera.annotate_text = rt
        sleep(1)
    sleep(10)
    camera.stop_recording()
    camera.stop_preview()

I tried to do an extra function in the While Loop, which polls the new value of the payload every second.
But it didn't work out. I never managed to get the new value here. At the point where the "on_position" function was called, the program always stopped and was frozen.
It didn't even output the value of rt.

This part is very likely not doing what you would think it does. Can you explain what you think/hope the program would do here?

I want the loop to ask for the value from the payload again (with the "on_position" function) and then to put the new value into the video as text.
And the whole thing repeats itself every second.
how often at the end can be set with the value of i. you should then be able to set the duration of the video.

I have re-worked your script a bit...soon ready

This is the re-worked script you can try. Hopefully I got things correct :wink:

What is important is that we can never allow the script to sleep. So instead I have re-worked it so that it should be awake and always ready for new incoming messages. To achieve this I am using the Timer from threading.

I have also added support for an abort command soo that you can terminate the script correctly, just send the string "abort" from NR and the script will terminate gracefully including cancelling an eventual timer still running

Script is below:

#!/usr/bin/env python3

from picamera import PiCamera
from time import sleep
import datetime
import paho.mqtt.client as mqtt
from sys import exit
from threading import Timer


def on_connect (client, userdata, flags, rc):
    print("connected with result code" + str(rc)) 
    client.subscribe("positions/#")  


def on_message(client, userdata, msg):
    global th_abort
    global camera
    global recording
    global t
    print(msg.payload.decode("utf-8"))
    if 'abort' in msg.payload.decode("utf-8"):
        if t.is_alive():
            t.cancel()
            stopRecording()
        th_abort = True
    else:
        camera.annotate_text = str(msg.payload.decode("utf-8"))
        if not recording:
            startRecording()


def on_subscribe(client, userdata, mid, granted_qos):
    print ('Subscribed')


def startRecording():
    global camera
    global recording
    global t
    recording = True
    dateiname = datetime.datetime.now().strftime('%Y.%m.%d-%H%M')
    videodatei = f"{dateiname}.h264"
    print(videodatei)
    camera.start_preview()
    camera.start_recording(videodatei)
    t = Timer(10.0, stopRecording)
    t.start()


def stopRecording():
    global camera
    global recording
    camera.stop_recording()
    camera.stop_preview()
    recording = False


# Main starts here -----------------------------------------------------------
t = None
th_abort = False
recording = False
dateipfad = "/home/pi"
camera = PiCamera()

client = mqtt.Client()
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_message = on_message
client.connect("localhost", 1883, 60)

client.loop_start()
while th_abort == False:
    sleep(1)
client.loop_stop()
client.disconnect()
del client
sleep(2)
print ("script terminated")
exit(0)

Thank you very much! :slight_smile:
When executing, however, an error message is made as in the picture.

Edit:
Ok I wrote this line again and it works.!
I give later the information about the test

The reason that error appeared is that your variables can’t contain dashes. A dash means minus.

In my original script I had an underscore, I think the OP corrected this and then it seems working

Two more suggestions to add:

  1. The code to cancel the Timer should be changed to this to avoid eventual error message if there is no timer running:
    if 'abort' in msg.payload.decode("utf-8"):
        try:
            if t.is_alive():
                t.cancel()
                stopRecording()
        except:
            pass
        th_abort = True

  1. If you think the script is not updating the text in the video fast enough you could try this
while th_abort == False:
    sleep(0.1)
client.loop_stop()

So, the test was successful.
Only the cloning of the SD card did not work properly. the 2nd raspberry never worked as intended.
So I set it up again, put everything on and set it up. Then copied the scripts over and then everything worked.
Thanks for the help here! :innocent:

@gragtoni435
Good to hear! Always nice with feedback when things worked out like this. Did you also use the last small modifications in my previous response?

Anyway, hopefully useful also to other users, at least an excercis in communication NR with Python using MQTT

EDIT: regarding cloning of SD-Cards. In all my pi's I have an extra micro sd card reader with an sd card inserted. I am always using the built in feature "Accessories/SD Card Copier". When I tried it has always been successful in making a perfect clone that worked perfect when I swapped sd cards

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.