Raspberry Pi - peer to peer connection with an IP camera

Hi!

I’d like to connect my IP camera to the pi directly via RJ45 cable.

On Raspbian OS, I was able to do that by following this guide.

Any guide or link to do so?

Appreciate to your help!

Eric.

Hey there @emollergren welcome to the forum.

balenaOS and the balenaCloud platform are container-based in order to be scalable as you roll out many devices, so you have to do things a bit differently to just installing natively on something like Raspbian OS.

I personally would have a look online for existing containers that can take an RTSP stream from the camera and display it. Maybe something like this: Docker

If you’re following the guide you’ll also need a container that offers DHCP server functionality, and to be able to configure your wired networking using the docs here: Network Setup on balenaOS - Balena Documentation

Hope this helps you get started.

Hi, @chrisys

Thanks for your reply.

Is there any sample service that can support the peer to peer connection?

I guess DNS server should be running and also IP address of the ethernet should be static.

Thanks!

What I want to do is to connect my IP camera directly to my RPi and assign a static IP address to it to grab video stream.

Has anyone ever tried this on balenaOS?

Regards.

There’s no reason why this wouldn’t be possible, but no examples come to mind.

Hi,

I hope to have some time tonight to test some things.
My general approach would be to spin up a service with a dedicated dhcp server as a basis.

Something along the lines of.

Dockerfile.template:

FROM balenalib/%%BALENA_MACHINE_NAME%%

RUN install_packages network-manager udhcpd

ENV app_dhcp_config /root/udhcpd.conf

COPY static_eth0.nmconnection /etc/NetworkManager/system-connections/
COPY udhcpd.conf ${app_dhcp_config}
COPY start.sh /root/

CMD ["bash", "/root/start.sh"]

static_eth0.nmconnection

[connection]
id=static_eth0
type=ethernet
interface-name=eth0
permissions=
secondaries=

[ethernet]
mac-address-blacklist=

[ipv4]
address1=192.168.1.1/24
dns=8.8.8.8;8.8.4.4;
dns-search=
method=manual

[ipv6]
addr-gen-mode=stable-privacy
dns-search=
method=manual

udhcpd.conf:

start 192.168.1.20
end 192.168.1.254
interface eth0

static_lease <camera mac> 192.168.1.10

option subnet 255.255.255.0
option router 192.168.1.1
option dns 192.168.1.1

lease_file /var/run/udhcpd/udhcpd.leases
pid_file /var/run/udhcpd/udhcpd.pid

start.sh:

#!/bin/sh

udhcpd -c ${app_dhcp_config}

while true;
do
    # Do something, maybe check leases file?

    sleep 1
done

This would in theory set up eth0 with a static IP and DHCP server.
When a device with MAC address <camera mac> connects, it would be assigned the address 192.168.1.10.

1 Like

Hi @TJvV @chrisys

Thank you for your reply.
I will try it and let you know.

Thanks,
Eric

Hi @TJvV

I’ve tested it today, however, it doesn’t assign the IP address to the IP camera which is connected to the RPi directly. Does it work on your side?

Regards.

Hi,

Ironically, I was a bit too busy with some network issues of my own yesterday :stuck_out_tongue:

Today, I did get somewhere though.
I tried out some things with my raspberry pi4 and my laptop and found a few bugs in what I said off the top of my head.

Fixes

First things first: The network manager connection file.
I was hoping loading it from the container would work, but it doesn’t.
I was hoping it would, but such is life. You can move it to the boot partition: /boot/system-connections/
If you’re logged into the Host OS, you can grab it from the container with the commands

container_id=$(balena ps | awk '/main/ {print $1}')
balena cp ${container_id}:/root/static_eth0.nmconnection /mnt/boot/system-connections/

After moving it, NetworkManager still wouldn’t load it, because of a tiny bug in the config.
We said we wanted IPv6 to be configured manually, but didn’t specify an address.
Setting method=disabled allows us to test this with IPv4 only.
To prevent some routing issues, I also added an entry never-default=true to the connection.
This ensures your internet connection keeps going through the wifi.

Next, to activate the connection from the container, I forgot to declare the right DBUS socket
Adding

ENV DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket
ENV UDEV on

to the Dockerfile.template helps fix that.

Next, the script: udhcpd doesn’t have the -c option for specifying the config file, simply doing udhcpd ${app_dhcp_config} is good enough.
I entered the MAC address for my laptops ethernet port (enp6s0) in the config file.
I also found out that udhcpd doesn’t actually write the leases_file immediately, which was kinda surprising.
It did run however, so I continued testing.

Finally, I connected my laptop, ran dhclient enp6s0, and got the static lease I expected.

New stuff

I have modified the scripts a bit further to take environment variables.
The static lease entry is only added when these are set:
app_camera_mac to specify the expected MAC
app_camera_ip to specify the desired IP

If the IP is specified, it will try to ping the device.
It will also print out the current leases.

I hope to do some more testing tomorrow, to get to the point where it will actually show whether it’s connected or not.

The current version of the files

Dockerfile.template:

FROM balenalib/%%BALENA_MACHINE_NAME%%

RUN install_packages network-manager udhcpd

ENV DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket
ENV UDEV on

ENV app_udhcpd_config=/root/udhcpd.conf

COPY static_eth0.nmconnection /root/
COPY udhcpd.conf /root/
COPY start.sh /root/

CMD ["bash", "/root/start.sh"]

start.sh:

#!/bin/bash

# Move connection file to /data/, so it can be more easily picked up in Host
cp /root/static_eth0.nmconnection /data/

# Bring up the connection
nmcli con up static_eth0

# Update DHCP config
UDHCPD_CONF=/tmp/udhcpd.conf

cp "${app_udhcpd_config}" "${UDHCPD_CONF}"
if [[ -n "${app_camera_mac}" && -n "${app_camera_ip}" ]]; then
    # mac set, assign static lease
    echo "static_lease ${app_camera_mac} ${app_camera_ip}" >> "${UDHCPD_CONF}"
fi

# Start DHCP server
udhcpd "${UDHCPD_CONF}"

while true;
do
    # Ask udhcpd to update leases file
    kill -USR1 $(pidof udhcpd)
    
    # Print leases
    dumpleases


    if [ -n "${app_camera_ip}" ]; then
        ping -q "${app_camera_ip}"
    fi

    sleep 10
done

static_eth0.nmconnection:

[connection]
id=static_eth0
type=ethernet
interface-name=eth0
permissions=
secondaries=

[ethernet]
mac-address-blacklist=

[ipv4]
address1=192.168.10.1/24
dns=8.8.8.8;8.8.4.4;
dns-search=
method=manual
never-default=true

[ipv6]
addr-gen-mode=stable-privacy
dns-search=
method=disabled

udhcpd.conf

start 192.168.10.20
end 192.168.10.254
interface eth0

option subnet 255.255.255.0
option router 192.168.10.1
option dns 192.168.10.1

Hi @TJvV

Thank you for your kind supports. I’ve had a test using these new scripts, however, it doesn’t work because there is no /var/lib/misc/udhcpd.leases file. Of course, I’ve added app_camera_mac and app_camera_ip in udhcpd.conf file before the test. And also our main goal is to assign the IP address to the IP camera once the balena container is working. Please help me. Thanks.

Hi @TJvV

This is the tutorial that I’ve used before. I’m not sure whether it could help you or not.

Hi,

In my test, I saw the message that the leases file didn’t exist only once; after that it did come up.
This is probably a race condition between the udhcpd process consuming the USR1 signal, and the dumpleases process reading the file.
I’m guessing a small delay (sleep 0.1) in between those calls might help.
It’s probably also a good idea to give a max count to the ping, like ping -c 10 to limit how often it tries to reach the camera.

Maybe it’s a good idea to take a step back, and check just the DHCP server first.

If you change the entry in start.sh to udhcpd -f "${UDHCPD_CONF}", it should run the DHCP server in the foreground, showing you any requests it gets from DHCP clients (in my case the laptop,in yours the camera) in the balena logs.

If this doesn’t show any traffic after connecting the camera, there’s probably something weird going on with your camera configuration.
Which camera are you trying to use?

PS: for faster testing changes, I usually change the CMD entry in Dockerfile.template to CMD ["balena-idle"] and then simply ssh into the device and run the scripts/commands manually.

Hi @TJvV

I’ve tested it again, these are the errors.

[Logs] [2023-12-18T11:19:27.491Z] [app] cp: cannot create regular file ‘/data/’: Not a directory
[Logs] [2023-12-18T11:19:27.707Z] [app] Error: unknown connection ‘static_eth0’.
[Logs] [2023-12-18T11:19:27.782Z] [app] udhcpd: started, v1.30.1
[Logs] [2023-12-18T11:19:27.789Z] [app] udhcpd: can’t open ‘/var/lib/misc/udhcpd.leases’: No such file or directory
[Logs] [2023-12-18T11:19:27.790Z] [app] udhcpd: is interface eth0 up and configured?: Cannot assign requested address
[Logs] [2023-12-18T11:19:27.832Z] [app] dumpleases: can’t open ‘/var/lib/misc/udhcpd.leases’: No such file or directory

Are there any help? It works well on your side? Please help me. Thanks

Hi,

Yes, it works for me.
I tried this on a freshly flashed Raspberry Pi 4-64bit with balenaOS 4.0.26+rev1 in Development mode.

It sounds very weird that you can’t copy to /data/, that’s a volume that’s always available in balena.
Which version are you running on your Pi?

If you added the connection file to the boot partition of your Pi, it should be copied and available to NetworkManager in the HostOS.

Hi, I’ve already added the connection file to the boot system, so the network manager is available now.
However, the dumpleases doesn’t work because there is no such file - dumpleases: can’t open ‘/var/lib/misc/udhcpd.leases’: No such file or directory. Any help?

Hi @TJvV
If possible, could you please show me how it works on your side via zoom? Thanks.

Hi,

That sounds doable; I should be available 2023-12-20 and 2023-12-21 between 19:00 and 21:00 UTC.

In the meantime, try just the udhcp -f /root/udhcpd.conf and see what it says.

That it can’t read the leases file, only means it starts out with a clean state.
It will write the file when you use the kill -USR1 $(pidof udhcpd) command.

Hi, I’ve already tested it, there are 2 problems.

  • udhcpd: can’t open ‘/var/lib/misc/udhcpd.leases’: No such file or directory
  • udhcpd: is interface eth0 up and configured?: Cannot assign requested address
    I think we’d better set up a zoom and discuss it. If possible, could you please send a zoom meeting link?
    Thanks.

Hi @TJvV
When you are available, could you please join the zoom meeting?
https://us05web.zoom.us/j/8568202322?pwd=OTExSWxkbndkZTlmVnY1dHc2RDRBZz09
Thanks.

Little recap of tonight:

  1. For some reason on the device, the /data directory got renamed to /gw, which made copying the connection file fail;
  2. The udhcpd config file was modified in a way that udhcpd failed to start;
  3. It’s not very clear whether the IP camera was actually sending out DHCP requests;
  4. It’s difficult to debug when things lose their connection :stuck_out_tongue:

For future reference:
I have set up a small DHCP example.
My latest addition was creating the ethernet connection directly from the container (if it didn’t exist yet).

In @emollergren case, we’re dealing with a Dahua IP camera, hints on how te configure it to use DHCP or static IP can be found here:
Changing IP address
ConfigTool