added testing script, improved osc2cam verbosity and introducing result/response osc message to client
This commit is contained in:
parent
099cb06741
commit
1d5a54aca7
|
@ -0,0 +1,3 @@
|
||||||
|
192.168.1.51, 9000
|
||||||
|
192.168.1.52, 9000
|
||||||
|
192.168.1.53, 9000
|
|
@ -0,0 +1,3 @@
|
||||||
|
localhost, 9001
|
||||||
|
localhost, 9002
|
||||||
|
localhost, 9003
|
|
@ -6,8 +6,15 @@ import re
|
||||||
import sys
|
import sys
|
||||||
import httplib
|
import httplib
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
from chaosc.simpleOSCServer import SimpleOSCServer
|
from chaosc.simpleOSCServer import SimpleOSCServer
|
||||||
|
|
||||||
|
try:
|
||||||
|
from chaosc.c_osc_lib import OSCMessage
|
||||||
|
except ImportError, e:
|
||||||
|
print e
|
||||||
|
from chaosc.osc_lib import OSCMessage
|
||||||
|
|
||||||
|
|
||||||
class OSC2CamServer(SimpleOSCServer):
|
class OSC2CamServer(SimpleOSCServer):
|
||||||
"""OSC filtering/transcoding middleware
|
"""OSC filtering/transcoding middleware
|
||||||
|
@ -27,37 +34,67 @@ class OSC2CamServer(SimpleOSCServer):
|
||||||
|
|
||||||
SimpleOSCServer.__init__(self, ("", args.port))
|
SimpleOSCServer.__init__(self, ("", args.port))
|
||||||
|
|
||||||
|
self.args = args
|
||||||
self.set_url = "/cgi-bin/admin/"
|
self.set_url = "/cgi-bin/admin/"
|
||||||
self.get_url = "/cgi-bin/view/"
|
self.get_url = "/cgi-bin/view/"
|
||||||
self.ptz_ctl_url = "/cgi-bin/operator/ptzset"
|
self.ptz_ctl_url = "/cgi-bin/operator/ptzset"
|
||||||
self.ptz_config_url = "/cgi-bin/operator/ptzconfig"
|
self.ptz_config_url = "/cgi-bin/operator/ptzconfig"
|
||||||
|
self.parse_cam_config()
|
||||||
self.connections = [httplib.HTTPConnection(host, port) for host, port in cams]
|
self.connections = [httplib.HTTPConnection(host, port) for host, port in cams]
|
||||||
self.resetCams()
|
self.resetCams()
|
||||||
|
self.targets = list()
|
||||||
|
|
||||||
|
|
||||||
|
def parse_cam_config(self):
|
||||||
|
lines = open(self.args.cam_config_file).readlines()
|
||||||
|
cams = list()
|
||||||
|
for line in lines:
|
||||||
|
host, port = line.split(",")
|
||||||
|
host = host.strip()
|
||||||
|
port = int(port.strip())
|
||||||
|
cams.append((host, port))
|
||||||
|
return cams
|
||||||
|
|
||||||
|
|
||||||
|
def handleConnResult(self, connection, client_address=None, cmd=None):
|
||||||
|
conn_result = connection.getresponse()
|
||||||
|
if client_address is not None:
|
||||||
|
response = OSCMessage("/Response")
|
||||||
|
response.appendTypedArg(cmd, "s")
|
||||||
|
response.appendTypedArg(conn_result.status, "i")
|
||||||
|
response.appendTypedArg(conn_result.reason, "s")
|
||||||
|
self.socket.sendto(response.encode_osc(), client_address)
|
||||||
|
|
||||||
|
if conn_result.status != 200:
|
||||||
|
print "%s. Error: %d, %s" % (datetime.now().strftime("%x %X"), conn_result.status, conn_result.reason)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def resetCams(self):
|
def resetCams(self):
|
||||||
""" configures each ip cam"""
|
""" configures each ip cam"""
|
||||||
|
|
||||||
for connection in self.connections:
|
now = datetime.now().strftime("%x %X")
|
||||||
|
for ix, connection in enumerate(self.connections):
|
||||||
|
print "%s: resetting camera %d to: resolution 640x480, 75%% compression and 25 fps" % (now, ix)
|
||||||
connection.request("GET", "%sparam?action=update&Image.I0.MJPEG.Resolution=640x480" % self.set_url)
|
connection.request("GET", "%sparam?action=update&Image.I0.MJPEG.Resolution=640x480" % self.set_url)
|
||||||
conn_result = connection.getresponse()
|
self.handleConnResult(connection, None)
|
||||||
print conn_result.status, conn_result.reason
|
|
||||||
connection.request("GET", "%sparam?action=update&Image.I0.Appearance.Compression=75" % self.set_url)
|
connection.request("GET", "%sparam?action=update&Image.I0.Appearance.Compression=75" % self.set_url)
|
||||||
conn_result = connection.getresponse()
|
self.handleConnResult(connection, None)
|
||||||
print conn_result.status, conn_result.reason
|
|
||||||
connection.request("GET", "%sparam?action=update&Image.I0.MJPEG.FPS=25" % self.set_url)
|
connection.request("GET", "%sparam?action=update&Image.I0.MJPEG.FPS=25" % self.set_url)
|
||||||
conn_result = connection.getresponse()
|
self.handleConnResult(connection, None)
|
||||||
print conn_result.status, conn_result.reason
|
|
||||||
|
|
||||||
|
|
||||||
def move_cam(self, cam_id, args):
|
def move_cam(self, cam_id, args, client_address):
|
||||||
""" moves given ip cam"""
|
""" moves given ip cam"""
|
||||||
|
|
||||||
direction = args[0]
|
direction = args[0]
|
||||||
|
now = datetime.now().strftime("%x %X")
|
||||||
if direction in ("home", "up", "down", "left", "right", "upleft", "upright", "downleft", "downright", "repeat", "stop"):
|
if direction in ("home", "up", "down", "left", "right", "upleft", "upright", "downleft", "downright", "repeat", "stop"):
|
||||||
|
print "%s: move camera %d to: dir %r" % (now, cam_id, direction)
|
||||||
connection = self.connections[cam_id]
|
connection = self.connections[cam_id]
|
||||||
connection.request("GET", "%s?move=%s" % (self.ptz_ctl_url, direction))
|
connection.request("GET", "%s?move=%s" % (self.ptz_ctl_url, direction))
|
||||||
conn_result = connection.getresponse()
|
self.handleConnResult(connection, client_address, "moveCam")
|
||||||
print conn_result.status, conn_result.reason
|
|
||||||
|
|
||||||
|
|
||||||
def use_cam_preset(self, cam_id, args):
|
def use_cam_preset(self, cam_id, args):
|
||||||
|
@ -65,9 +102,11 @@ class OSC2CamServer(SimpleOSCServer):
|
||||||
|
|
||||||
presetno = args[0]
|
presetno = args[0]
|
||||||
connection = self.connections[cam_id]
|
connection = self.connections[cam_id]
|
||||||
|
now = datetime.now().strftime("%x %X")
|
||||||
|
print "%s: use camera %d preset %d" % (now, cam_id, presetno)
|
||||||
|
|
||||||
connection.request("GET", "%s?gotoserverpresetno=%d" % (self.ptz_ctl_url, presetno))
|
connection.request("GET", "%s?gotoserverpresetno=%d" % (self.ptz_ctl_url, presetno))
|
||||||
conn_result = connection.getresponse()
|
self.handleConnResult(connection, client_address, "useCamPreset")
|
||||||
print conn_result.status, conn_result.reason
|
|
||||||
|
|
||||||
|
|
||||||
def set_cam_preset(self, cam_id, args):
|
def set_cam_preset(self, cam_id, args):
|
||||||
|
@ -76,8 +115,7 @@ class OSC2CamServer(SimpleOSCServer):
|
||||||
presetno = args[0]
|
presetno = args[0]
|
||||||
connection = self.connections[cam_id]
|
connection = self.connections[cam_id]
|
||||||
connection.request("GET", "%s?setserverpresetno=%d&home=yes" % (self.ptz_config_url, presetno))
|
connection.request("GET", "%s?setserverpresetno=%d&home=yes" % (self.ptz_config_url, presetno))
|
||||||
conn_result = connection.getresponse()
|
self.handleConnResult(connection, client_address, "setCamPreset")
|
||||||
print conn_result.status, conn_result.reason
|
|
||||||
|
|
||||||
|
|
||||||
def zoom_cam(self, cam_id, args):
|
def zoom_cam(self, cam_id, args):
|
||||||
|
@ -91,8 +129,7 @@ class OSC2CamServer(SimpleOSCServer):
|
||||||
direction = 1
|
direction = 1
|
||||||
connection = self.connections[cam_id]
|
connection = self.connections[cam_id]
|
||||||
connection.request("GET", "%s?zoom=%s" % (self.ptz_ctl_url, direction))
|
connection.request("GET", "%s?zoom=%s" % (self.ptz_ctl_url, direction))
|
||||||
conn_result = connection.getresponse()
|
self.handleConnResult(connection, client_address, "zoomCam")
|
||||||
print conn_result.status, conn_result.reason
|
|
||||||
|
|
||||||
|
|
||||||
def toggle_night_view(self, cam_id, args):
|
def toggle_night_view(self, cam_id, args):
|
||||||
|
@ -107,16 +144,16 @@ class OSC2CamServer(SimpleOSCServer):
|
||||||
|
|
||||||
connection = self.connections[cam_id]
|
connection = self.connections[cam_id]
|
||||||
connection.request("GET", "%sparam?action=update&Image.I0.Appearance.NightMode=%s" % (self.set_url, state))
|
connection.request("GET", "%sparam?action=update&Image.I0.Appearance.NightMode=%s" % (self.set_url, state))
|
||||||
conn_result = connection.getresponse()
|
self.handleConnResult(connection, client_address, "toggleNightView")
|
||||||
print conn_result.status, conn_result.reason
|
|
||||||
|
|
||||||
|
|
||||||
def dispatchMessage(self, osc_address, typetags, args, packet, client_address):
|
def dispatchMessage(self, osc_address, typetags, args, packet, client_address):
|
||||||
""" dispatches parsed osc messages to the ip cam command methods"""
|
""" dispatches parsed osc messages to the ip cam command methods"""
|
||||||
|
|
||||||
|
print "client_address", client_address
|
||||||
cam_id = args.pop(0)
|
cam_id = args.pop(0)
|
||||||
if osc_address == "/moveCam":
|
if osc_address == "/moveCam":
|
||||||
self.move_cam(cam_id, args)
|
self.move_cam(cam_id, args, client_address)
|
||||||
elif osc_address == "/setCamPreset":
|
elif osc_address == "/setCamPreset":
|
||||||
self.set_cam_preset(cam_id, args)
|
self.set_cam_preset(cam_id, args)
|
||||||
elif osc_address == "/useCamPreset":
|
elif osc_address == "/useCamPreset":
|
||||||
|
@ -125,12 +162,49 @@ class OSC2CamServer(SimpleOSCServer):
|
||||||
self.zoom_cam(cam_id, args)
|
self.zoom_cam(cam_id, args)
|
||||||
elif osc_address == "/toggleNightView":
|
elif osc_address == "/toggleNightView":
|
||||||
self.toggle_night_view(cam_id, args)
|
self.toggle_night_view(cam_id, args)
|
||||||
|
elif osc_address == "/subscribe":
|
||||||
|
self.__subscription_handler(osc_address, typetags, args, packet, client_address)
|
||||||
|
|
||||||
|
def __subscription_handler(self, addr, typetags, args, client_address):
|
||||||
|
"""handles a target subscription.
|
||||||
|
|
||||||
|
The provided 'typetags' equals ["s", "i"] and
|
||||||
|
'args' contains [host, portnumber]
|
||||||
|
|
||||||
|
only subscription requests with valid host will be granted.
|
||||||
|
"""
|
||||||
|
|
||||||
|
address = args
|
||||||
|
try:
|
||||||
|
r = socket.getaddrinfo(address[0], address[1], socket.AF_INET6, socket.SOCK_DGRAM, 0, socket.AI_V4MAPPED | socket.AI_ALL)
|
||||||
|
print "addrinfo", r
|
||||||
|
if len(r) == 2:
|
||||||
|
address = r[1][4]
|
||||||
|
try:
|
||||||
|
print "%s: subscribe %r (%s:%d) by %s:%d" % (
|
||||||
|
datetime.now().strftime("%x %X"), args[3], address[0],
|
||||||
|
address[1], client_address[0], client_address[1])
|
||||||
|
self.targets[tuple(address)] = args[3]
|
||||||
|
except IndexError:
|
||||||
|
self.targets[tuple(address)] = ""
|
||||||
|
print "%s: subscribe (%s:%d) by %s:%d" % (
|
||||||
|
datetime.now().strftime("%x %X"), address[0], address[1],
|
||||||
|
client_address[0], client_address[1])
|
||||||
|
except socket.error, error:
|
||||||
|
print error
|
||||||
|
print "subscription attempt from %r: host %r not usable" % (
|
||||||
|
client_address, address[0])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(prog='osc2cam')
|
parser = argparse.ArgumentParser(prog='osc2cam')
|
||||||
parser.add_argument('-p', "--port", required=True,
|
parser.add_argument('-p', "--port", required=True,
|
||||||
type=int, help='my port')
|
type=int, help='my port')
|
||||||
|
parser.add_argument('-C', "--client_port", required=True,
|
||||||
|
type=int, help='client port to send reponse to')
|
||||||
|
parser.add_argument('-c', "--cam-config-file", required=True,
|
||||||
|
type=str, help='txt file for cam configuration, each line should be of the form "host, port"')
|
||||||
|
|
||||||
args = parser.parse_args(sys.argv[1:])
|
args = parser.parse_args(sys.argv[1:])
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# This file is part of chaosc
|
||||||
|
#
|
||||||
|
# chaosc is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# chaosc is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with chaosc. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2012-2013 Stefan Kögl
|
||||||
|
|
||||||
|
|
||||||
|
import socket, argparse, sys
|
||||||
|
|
||||||
|
from chaosc.simpleOSCServer import SimpleOSCServer
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
from chaosc.c_osc_lib import OSCMessage, decode_osc
|
||||||
|
except ImportError, e:
|
||||||
|
print e
|
||||||
|
from chaosc.osc_lib import OSCMessage, decode_osc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_moveCam(args, cam_id, sock):
|
||||||
|
directions = ("home", "up", "down", "left", "right", "upleft", "upright", "downleft", "downright", "repeat", "stop")
|
||||||
|
for direction in directions:
|
||||||
|
moveCam = OSCMessage("/moveCam")
|
||||||
|
moveCam.appendTypedArg(cam_id, "i")
|
||||||
|
moveCam.appendTypedArg(direction, "s")
|
||||||
|
binary = moveCam.encode_osc()
|
||||||
|
|
||||||
|
try:
|
||||||
|
sent = sock.sendto(binary, (args.osc2cam_host, args.osc2cam_port))
|
||||||
|
except socket.error, e:
|
||||||
|
if e[0] in (7, 65): # 7 = 'no address associated with nodename', 65 = 'no route to host'
|
||||||
|
raise e
|
||||||
|
else:
|
||||||
|
raise Exception("while sending OSCMessage 'moveCam' for cam_id %r with direction %r to %r:%r: %s" % (cam_id, direction, args.osc2cam_host, args.osc2cam_port, str(e)))
|
||||||
|
response = sock.recv(4096)
|
||||||
|
if response:
|
||||||
|
osc_address, typetags, arguments = decode_osc(response, 0, len(response))
|
||||||
|
print osc_address, arguments
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def parse_cam_config(path):
|
||||||
|
lines = open(path).readlines()
|
||||||
|
cams = list()
|
||||||
|
for line in lines:
|
||||||
|
host, port = line.split(",")
|
||||||
|
host = host.strip()
|
||||||
|
port = int(port.strip())
|
||||||
|
cams.append((host, port))
|
||||||
|
return cams
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(prog='osc2cam-test')
|
||||||
|
parser.add_argument("-o", '--osc2cam_host', required=True,
|
||||||
|
type=str, help='host of osc2cam instance to control')
|
||||||
|
parser.add_argument("-p", '--osc2cam_port', required=True,
|
||||||
|
type=int, help='port of osc2cam instance to control')
|
||||||
|
parser.add_argument('-c', "--cam-config-file", required=True,
|
||||||
|
type=str, help='txt file for cam configuration, each line should be of the form "host, port"')
|
||||||
|
|
||||||
|
args = parser.parse_args(sys.argv[1:])
|
||||||
|
|
||||||
|
cams = parse_cam_config(args.cam_config_file)
|
||||||
|
|
||||||
|
sock = socket.socket(2, 2, 17)
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 4096)
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 4096)
|
||||||
|
sock.settimeout(1)
|
||||||
|
sock.bind(("localhost", 10000))
|
||||||
|
#sock.connect((args.osc2cam_host, args.osc2cam_port))
|
||||||
|
|
||||||
|
for ix, (host, port) in enumerate(cams):
|
||||||
|
test_moveCam(args, ix, sock)
|
||||||
|
|
||||||
|
main()
|
Loading…
Reference in New Issue