You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
5.1 KiB
Python

import os
import glob
import sys
class CAPSProfile:
def __init__(self):
self.streams = [] # List of strings, e.g. XY.ABCD.*.*
self.stations = [] # List of network, station tuples, e.g. (XY,ABCD)
self.oldStates = [] # Content of old state file
'''
Plugin handler for the CAPS plugin.
'''
class SeedlinkPluginHandler:
# Create defaults
def __init__(self):
self.profiles = {}
def push(self, seedlink):
try:
maxTimeDiff = float(seedlink._get('plugins.caps.maxTimeDiff', False))
except:
maxTimeDiff = 86400
inOrder = ""
try:
if seedlink._get('plugins.caps.inOrder', False):
inOrder = " --in-order"
except:
pass
# Check and set defaults
try:
address = seedlink.param('sources.caps.address')
except KeyError:
address = "localhost:18002"
try:
streams = [chaId.strip() for chaId in seedlink.param(
'sources.caps.streams').split(',')]
except KeyError:
seedlink.setParam('sources.caps.streams', "*.*")
streams = ["*.*"]
try:
seedlink.param('sources.caps.encoding')
except KeyError:
seedlink.setParam('sources.caps.encoding', "STEIM2")
try:
seedlink.param('sources.caps.proc')
except KeyError:
seedlink.setParam('sources.caps.proc', "")
# parse address URL and create capsId of form:
# host[.port][_user]
addressFormatError = "Error: invalid address format, expected " \
"[[caps|capss]://][user:pass@]host[:port]"
# protocol
toks = address.split("://")
if len(toks) > 2:
raise Exception(addressFormatError)
elif len(toks) == 2:
protocol = toks[0]
address = toks[1]
if protocol != "caps" and protocol != "capss":
raise Exception(addressFormatError)
else:
protocol = "caps"
# authentication
toks = address.split("@")
if len(toks) > 2:
raise Exception(addressFormatError)
elif len(toks) == 2:
capsId = "%s_%s" % (toks[1].replace(
":", "."), toks[0].split(":")[0])
else:
capsId = address.replace(":", ".")
address = "%s://%s" % (protocol, address)
if capsId not in self.profiles:
profile = CAPSProfile()
self.profiles[capsId] = profile
else:
profile = self.profiles[capsId]
for chaId in streams:
toks = chaId.split('.')
if len(toks) != 2:
raise Exception(
"Error: invalid stream format, expected [LOC.CHA]")
streamID = seedlink.net + "." + seedlink.sta + "." + chaId
profile.streams.append(streamID)
profile.stations.append((seedlink.net, seedlink.sta))
log = os.path.join(seedlink.config_dir, "caps2sl.%s.state" % capsId)
streamsFile = os.path.join(
seedlink.config_dir, "caps2sl.%s.req" % capsId)
seedlink.setParam('sources.caps.address', address)
seedlink.setParam('sources.caps.log', log)
seedlink.setParam('sources.caps.streamsFile', streamsFile)
seedlink.setParam('sources.caps.maxTimeDiff', maxTimeDiff)
seedlink.setParam('sources.caps.inOrder', inOrder)
seedlink.setParam('seedlink.caps.id', capsId)
return capsId
def flush(self, seedlink):
# Populate request file per address
for id, profile in self.profiles.items():
caps2slreq = os.path.join(
seedlink.config_dir, "caps2sl.%s.req" % id)
fd = open(caps2slreq, "w")
for streamId in profile.streams:
fd.write("%s\n" % streamId)
fd.close()
try:
caps2slstate = os.path.join(seedlink.config_dir, "caps2sl.%s.state" % id)
# Read existing state file
fd = open(caps2slstate, "r")
profile.oldStates = [line.strip() for line in fd.readlines()]
except:
pass
# Delete all existing state files
for fl in glob.glob(os.path.join(seedlink.config_dir, "caps2sl.*.state")):
try:
os.remove(fl)
except:
sys.stderr.write("Failed to remove old state file: %s\n" % str(fl))
# Clean up state file to contain only configured stations
for id, profile in self.profiles.items():
caps2slstate = os.path.join(seedlink.config_dir, "caps2sl.%s.state" % id)
newStates = []
for (net, sta) in profile.stations:
for line in profile.oldStates:
if line.startswith(net + "." + sta + "."):
newStates.append(line)
if len(newStates) > 0:
fd = open(caps2slstate, "w")
for line in newStates:
fd.write(line + "\n")
fd.close()