1

I have two GoPro cameras that I can control through 10.5.5.9/x/x/x/ over WiFi - the thought process is that I can control both using two different network interfaces to connect to both cameras and then send a request to the URL (from earlier) and control both the cameras.

To test my theory I did the following commands in terminal:

curl --interface wlan0 http://10.5.5.9/gp/gpControl/command/shutter?p=1

curl --interface wlan1 http://10.5.5.9/gp/gpControl/command/shutter?p=1

Subsequently, this activates both cameras and they both begin recording. Great!

Putting this code into Python I tried the simple version of:

import os

resp = os.popen('curl --interface wlan0 http://10.5.5.9/gp/gpControl/command/shutter?p=1').read()
print(resp)
resp = os.popen('curl --interface wlan1 http://10.5.5.9/gp/gpControl/command/shutter?p=1').read()
print(resp)

But it only activates one camera and not the other, what is the reason behind this? I did the similar method using the answer to this question and it does the same, only activating one camera.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • - Using python, the same camera is activated only once? Or twice? The reason to ask is to try to understand whether the --interface is being considered when passing the command to O.S. – silver Apr 06 '20 at 20:11
  • 2
    - Consider using subprocess over os.popen (which is deprecated) https://docs.python.org/3.8/library/subprocess.html#replacing-os-popen-os-popen2-os-popen3 – silver Apr 06 '20 at 20:14
  • @silver It will send the command to one camera then try to send the same command to the same camera - which tells me it is not likely sending from a different interface. Same thing happens with the solution that I linked to. – Maxwell Newberry Apr 06 '20 at 20:24
  • Can you try to configure one of the wlans and the second camera in a different IP subnet? This would remove a handful of layers to look at. Which python version are you using? – silver Apr 06 '20 at 20:40
  • @silver It looks like Python 3.6.9 – Maxwell Newberry Apr 06 '20 at 20:42
  • `pycurl` is a Python library that backends into the C libcurl library. It is not applicable to using the command-line curl interface in Python. – Charles Duffy Apr 06 '20 at 20:48
  • BTW, if you switch to `subprocess`, you'll be able to pass an explicit argument list so you don't need to worry about a shell munging your URL before it gets to curl. That is to say, with `subprocess.Popen(['curl', '--interface', 'wlan0', 'http://10.5.5.9/gp/gpControl/command/shutter?p=1'], stdout=subprocess.PIPE).communicate()`, you don't need to worry about the shell deciding that the `?` is a wildcard, or deciding that a `&` in your URL is a command separator. – Charles Duffy Apr 06 '20 at 20:51
  • As a different matter: Which operating system user did you test running your curl command from on the command line with? Which operating system user does your Python code run with? A difference between those is a much more likely explanation for the problem at hand (since unprivileged users are typically not allowed to select the interface to route traffic through). – Charles Duffy Apr 06 '20 at 20:53
  • @CharlesDuffy When I use that it seems to do that same thing as before, it will activate one camera but then instead of switching interfaces and sending the command to the other camera, it will try and send the same command to same camera. – Maxwell Newberry Apr 06 '20 at 20:57
  • That's what I'd expect if the Python program didn't have enough permissions to honor the `--interface` specification. – Charles Duffy Apr 06 '20 at 20:58
  • ...quick question towards that end; is the host's IP address different between the local various interfaces? (It's already established that the *destination* IP address is the same, but that's not the one I'm asking about now). – Charles Duffy Apr 06 '20 at 20:59
  • BTW, `if!wlan0` is preferred over just `wlan0`, assuming you have a modern version of curl. Of course, if you're passing that through a shell you'll need to quote it to work in interactive shells with history expansion support (if you use the subprocess syntax I described above you don't need to worry about that). – Charles Duffy Apr 06 '20 at 21:03
  • See: `https://stackoverflow.com/q/2339469/5372462` – ofirule Apr 06 '20 at 21:08
  • Does this answer your question? [reading a os.popen(command) into a string](https://stackoverflow.com/questions/2339469/reading-a-os-popencommand-into-a-string) – ofirule Apr 06 '20 at 21:10
  • @CharlesDuffy I am running a normal user, without sudo and it works in terminal. I am running Jetpack 4.3 through Nvidia Jetson products (TX2). I will look into giving the python script better permissions. Are you aware of a command to do so off the top of your head? – Maxwell Newberry Apr 06 '20 at 21:14
  • @ofirule Unfortunately, no. It does the same result as all the other solutions. – Maxwell Newberry Apr 06 '20 at 21:15
  • If it works as a normal user, then I'm *assuming* you have different local IP addresses for each local interface (I asked if that was the case earlier, and you never answered), and routing rules that honor that. In that case, the process can just do a per-IP bind, which doesn't need any extra permissions. – Charles Duffy Apr 06 '20 at 21:16
  • BTW, at this point, I would be reaching for syscall-tracing tools to compare what's going on under-the-hood in the working and broken cases. [`sysdig`](https://github.com/draios/sysdig/) is my personal favorite, but in a pinch `strace -f` works too (it's just really, *really* slow). – Charles Duffy Apr 06 '20 at 21:18
  • wlan0 - inet 10.5.5.100/24, wlan1 - inet 192.168.1.10/24 – Maxwell Newberry Apr 06 '20 at 21:21
  • Then I'd be looking at your routing table before anything else. How is traffic from 192.168.1.10 routed to get to a separate 10.5.5.x namespace? Have you retested the code from a shell and made sure it *still* works? – Charles Duffy Apr 07 '20 at 12:46
  • Again, though -- in this kind of context, `strace -f` is your friend. – Charles Duffy Apr 07 '20 at 12:49
  • It is more likely a configuration issue. Change the IP address of one of the cameras to 192.168.1.nnn ( nnn is any free address in the same subnet your wlan1 is configured). Then you do not need to bother to determine the physical interface. The routing protocol of the operating system will find the interface in the same net of the destination. – silver Apr 07 '20 at 21:16

1 Answers1

0

Try subprocess.run instead of os.popen:

import subprocess

resp = subprocess.run(["curl", "--interface", "wlan0", "http://10.5.5.9/gp/gpControl/command/shutter?p=1"], capture_output=True, shell=True)
print(resp)
resp = subprocess.run(["curl", "--interface", "wlan1", "http://10.5.5.9/gp/gpControl/command/shutter?p=1"], capture_output=True, shell=True)
print(resp)
silver
  • 126
  • 5
  • Check the comments -- this was one of the first changes suggested after the question was posted, and was reported to have no effect. (Also, the OP is on a version of Python old enough to not have `run()`, so it's necessary to operate on a Popen object explicitly). – Charles Duffy Apr 07 '20 at 12:46