psychose/osc2cam/osc2cam/main.py

228 lines
8.0 KiB
Python
Raw Normal View History

2014-03-08 02:19:24 +00:00
#!/usr/bin/python
# -*- coding: utf-8 -*-
import argparse
import re
import sys
2014-03-08 13:38:56 +00:00
import httplib
2014-03-08 02:19:24 +00:00
from datetime import datetime
2014-03-08 02:19:24 +00:00
from chaosc.simpleOSCServer import SimpleOSCServer
try:
from chaosc.c_osc_lib import OSCMessage
except ImportError, e:
print e
from chaosc.osc_lib import OSCMessage
2014-03-08 02:19:24 +00:00
class OSC2CamServer(SimpleOSCServer):
"""OSC filtering/transcoding middleware
"""
def __init__(self, args, cams):
2014-03-08 13:38:56 +00:00
"""ctor for a osc udp 2 ptz ip cam bridge
2014-03-08 02:19:24 +00:00
2014-03-08 13:38:56 +00:00
starts the server, creates http connections to specified cams
2014-03-08 02:19:24 +00:00
2014-03-08 13:38:56 +00:00
:param args: return value of argparse.parse_args
:type args: namespace object
:param cams: return value of argparse.parse_args
:type cams: list of 2 item tuples
2014-03-08 02:19:24 +00:00
"""
2014-03-08 13:38:56 +00:00
SimpleOSCServer.__init__(self, ("", args.port))
2014-03-08 02:19:24 +00:00
self.args = args
2014-03-08 13:38:56 +00:00
self.set_url = "/cgi-bin/admin/"
self.get_url = "/cgi-bin/view/"
self.ptz_ctl_url = "/cgi-bin/operator/ptzset"
self.ptz_config_url = "/cgi-bin/operator/ptzconfig"
self.parse_cam_config()
2014-03-08 13:38:56 +00:00
self.connections = [httplib.HTTPConnection(host, port) for host, port in cams]
2014-03-08 02:19:24 +00:00
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)
2014-03-08 02:19:24 +00:00
def resetCams(self):
2014-03-08 13:38:56 +00:00
""" configures each ip cam"""
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)
2014-03-08 13:38:56 +00:00
connection.request("GET", "%sparam?action=update&Image.I0.MJPEG.Resolution=640x480" % self.set_url)
self.handleConnResult(connection, None)
2014-03-08 13:38:56 +00:00
connection.request("GET", "%sparam?action=update&Image.I0.Appearance.Compression=75" % self.set_url)
self.handleConnResult(connection, None)
2014-03-08 13:38:56 +00:00
connection.request("GET", "%sparam?action=update&Image.I0.MJPEG.FPS=25" % self.set_url)
self.handleConnResult(connection, None)
2014-03-08 02:19:24 +00:00
def move_cam(self, cam_id, args, client_address):
2014-03-08 13:38:56 +00:00
""" moves given ip cam"""
2014-03-08 02:19:24 +00:00
direction = args[0]
now = datetime.now().strftime("%x %X")
2014-03-08 02:19:24 +00:00
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)
2014-03-08 13:38:56 +00:00
connection = self.connections[cam_id]
connection.request("GET", "%s?move=%s" % (self.ptz_ctl_url, direction))
self.handleConnResult(connection, client_address, "moveCam")
2014-03-08 13:38:56 +00:00
2014-03-08 02:19:24 +00:00
2014-03-08 13:38:56 +00:00
def use_cam_preset(self, cam_id, args):
""" says given ip cam to use a predefined position preset"""
2014-03-08 02:19:24 +00:00
presetno = args[0]
2014-03-08 13:38:56 +00:00
connection = self.connections[cam_id]
now = datetime.now().strftime("%x %X")
print "%s: use camera %d preset %d" % (now, cam_id, presetno)
2014-03-08 13:38:56 +00:00
connection.request("GET", "%s?gotoserverpresetno=%d" % (self.ptz_ctl_url, presetno))
self.handleConnResult(connection, client_address, "useCamPreset")
2014-03-08 02:19:24 +00:00
2014-03-08 13:38:56 +00:00
def set_cam_preset(self, cam_id, args):
""" saves the actual position of given ip cam to a preset"""
2014-03-08 02:19:24 +00:00
presetno = args[0]
2014-03-08 13:38:56 +00:00
connection = self.connections[cam_id]
connection.request("GET", "%s?setserverpresetno=%d&home=yes" % (self.ptz_config_url, presetno))
self.handleConnResult(connection, client_address, "setCamPreset")
2014-03-08 13:38:56 +00:00
2014-03-08 02:19:24 +00:00
2014-03-08 13:38:56 +00:00
def zoom_cam(self, cam_id, args):
""" tells given ip cam to zoom in or out"""
2014-03-08 02:19:24 +00:00
direction = None
arg = args[0]
if arg == "out":
direction = 0
elif arg == "in":
direction = 1
2014-03-08 13:38:56 +00:00
connection = self.connections[cam_id]
connection.request("GET", "%s?zoom=%s" % (self.ptz_ctl_url, direction))
self.handleConnResult(connection, client_address, "zoomCam")
2014-03-08 02:19:24 +00:00
2014-03-08 13:38:56 +00:00
def toggle_night_view(self, cam_id, args):
""" toggles the night view function of given ip cam"""
2014-03-08 02:19:24 +00:00
arg = args[0]
state = None
if arg == "on":
state = "auto"
else:
state = "off"
2014-03-08 13:38:56 +00:00
connection = self.connections[cam_id]
connection.request("GET", "%sparam?action=update&Image.I0.Appearance.NightMode=%s" % (self.set_url, state))
self.handleConnResult(connection, client_address, "toggleNightView")
2014-03-08 02:19:24 +00:00
def dispatchMessage(self, osc_address, typetags, args, packet, client_address):
2014-03-08 13:38:56 +00:00
""" dispatches parsed osc messages to the ip cam command methods"""
2014-03-08 14:08:25 +00:00
print "client_address", client_address
2014-03-08 14:08:25 +00:00
cam_id = args.pop(0)
if osc_address == "/moveCam":
self.move_cam(cam_id, args, client_address)
2014-03-08 14:08:25 +00:00
elif osc_address == "/setCamPreset":
self.set_cam_preset(cam_id, args)
elif osc_address == "/useCamPreset":
self.use_cam_preset(cam_id, args)
elif osc_address == "/zoomCam":
self.zoom_cam(cam_id, args)
elif osc_address == "/toggleNightView":
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])
2014-03-08 02:19:24 +00:00
def main():
2014-03-08 13:38:56 +00:00
parser = argparse.ArgumentParser(prog='osc2cam')
parser.add_argument('-p', "--port", required=True,
2014-03-08 02:19:24 +00:00
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"')
2014-03-08 02:19:24 +00:00
args = parser.parse_args(sys.argv[1:])
cams = [
2014-03-08 13:38:56 +00:00
("192.168.1.51", args.port + 1),
("192.168.1.52", args.port + 2),
("192.168.1.53", args.port + 3),
2014-03-08 02:19:24 +00:00
]
2014-03-08 13:38:56 +00:00
cams = [
("localhost", args.port + 1),
("localhost", args.port + 2),
("localhost", args.port + 3),
]
2014-03-08 02:19:24 +00:00
server = OSC2CamServer(args, cams)
2014-03-08 13:38:56 +00:00
server.serve_forever()