Commit b1b3764b authored by Gottfried Gaisbauer's avatar Gottfried Gaisbauer
Browse files

fetch new programmes and print act programme

parent 25b71990
This diff is collapsed.
......@@ -6,12 +6,14 @@ from datetime import datetime
from libraries.base.config import ConfigReader
from libraries.reporting.messenger import AuraMessenger
from modules.controller.controller import AuraController
from modules.communication.zmq.zmqadapter import ServerZMQAdapter
class Aura(threading.Thread):
config = None
messenger = None
controller = None
def __init__(self):
self.config = ConfigReader()
......@@ -22,6 +24,8 @@ class Aura(threading.Thread):
server = object
self.controller = AuraController(self.config)
def receive_signal(signum, stack):
print("received signal")
server.reload()
......@@ -31,12 +35,14 @@ class Aura(threading.Thread):
def startListening(self):
# start listener thread
server = ServerZMQAdapter(ip=self.config.get('zmqhostip'), port=int(self.config.get('zmqport')), config=self.config)
server = ServerZMQAdapter(self.controller, self.config)
try:
while server.is_alive():
print(str(datetime.now())+" joining")
server.join(timeout=5.0)
server.join()
print("join out")
# if cnt % 30 == 0:
# print(datetime.datetime.now().isoformat())
......
......@@ -2,13 +2,13 @@
import time
import simplejson
from argparse import ArgumentParser
from modules.communication.liquidsoap.LiquidSoapCommunicator import LiquidSoapCommunicator
# from modules.base.calendar import AuraCalendarService
from libraries.base.calendar import AuraCalendarService
from libraries.base.config import ConfigReader
# from modules.communication.zmq.zmqadapter import ClientZMQAdapter
from modules.communication.zmq.zmqadapter import ClientZMQAdapter
class Guru:
......@@ -16,8 +16,9 @@ class Guru:
config.loadConfig()
lsc = LiquidSoapCommunicator(False)
acs = AuraCalendarService(config) # AuraScheduler(lsc.getClient(), "/etc/comba/scheduler.xml")
# # AuraScheduler(lsc.getClient(), "/etc/comba/scheduler.xml")
#fcd = FetchCalendarData()
zmqclient = ClientZMQAdapter(config.get('zmqhostip'), config.get('zmqport'))
def __init__(self):
nothing_done = True
......@@ -26,7 +27,7 @@ class Guru:
parser = ArgumentParser()
# commands
parser.add_argument("-fnp", "--fetch-new-programmes", action="store_true", dest="fetchnewprogramme",
parser.add_argument("-fnp", "--fetch-new-programmes", action="store_true", dest="fetch_new_programme",
default=False, help="Fetch new programmes from calendarurl in comba.ini")
# getter
......@@ -34,6 +35,8 @@ class Guru:
help="Which mixer is activated?")
parser.add_argument("-pms", "--print-mixer-status", action="store_true", dest="printmixerstatus", default=False,
help="Prints all mixer sources and their states")
parser.add_argument("-pap", "--print-act-programme", action="store_true", dest="printactprog", default=False,
help="Prints the actual Programme, the controller holds")
# manipulation
parser.add_argument("-am", "--select-mixer", action="store", dest="selectmixer", default=-1,
......@@ -51,9 +54,9 @@ class Guru:
parser.print_help()
exit(1)
if args.fetchnewprogramme:
if args.fetch_new_programme:
print("Guru is learning how to fetch new programmes")
self.fetchNewProgrammes()
self.fetch_new_programme()
nothing_done = False
if args.getactivemixer:
......@@ -64,6 +67,10 @@ class Guru:
self.printmixerstatus()
nothing_done = False
if args.printactprog:
self.printactprog()
nothing_done = False
if args.addsource != "":
print("Guru still has to learn to add a source")
nothing_done = False
......@@ -79,14 +86,11 @@ class Guru:
if nothing_done:
parser.print_help()
def fetchNewProgrammes(self):
self.acs.start()
time.sleep(2) # well, ok, here i should listen to a AuraMessenger
nextshows = self.acs.getCalendarData()
print("received "+str(len(nextshows))+" timeslot entries")
return nextshows
def fetch_new_programme(self):
reply = self.zmqclient.send("fetch_new_programme")
print(type(reply))
print(reply)
print(simplejson.loads(reply))
def selectmixer(self, mixernumber, activate=True):
return self.lsc.switchmixernumber(mixernumber, activate)
......@@ -108,6 +112,10 @@ class Guru:
for k,v in status.items():
print("source: "+k+"\t status: "+v)
def printactprog(self):
reply = self.zmqclient.send("get_act_programme")
print(reply)
# # ## ## ## ## ## # #
# # ENTRY FUNCTION # #
......
This diff is collapsed.
......@@ -11,6 +11,7 @@ import pprint
from sqlalchemy import Boolean, Column, Date, DateTime, Float, Integer, String, Text, Time, ForeignKey
from libraries.database.database import db
class Model:
def store(self, commit=False):
db.session.add(self)
......@@ -20,6 +21,8 @@ class Model:
def commit(self):
db.session.commit()
# ------------------------------------------------------------------------------------------ #
class TimeSlotModel(Model):
def get_length(self):
......@@ -31,10 +34,25 @@ class TimeSlotModel(Model):
def pretty_print(self):
return pprint.pprint(self)
class TimeSlotEntryModel(Model):
# ------------------------------------------------------------------------------------------ #
@staticmethod
def upcoming(datefrom=datetime.datetime.now()):
upcomingtracks = TimeSlotEntry.query.filter(TimeSlotEntry.start > datefrom).all()
return upcomingtracks
# ------------------------------------------------------------------------------------------ #
@staticmethod
def select_all():
return TimeSlotEntry.query.filter().all()
def __str__(self):
return "TimeSlotEntry starts @ "+TimeSlotEntry.entry_start+" and ends @ "+TimeSlotEntry.entry_end+" and plays "+TimeSlotEntry.source
# ------------------------------------------------------------------------------------------ #
class TimeSlot(db.Model, TimeSlotModel):
"""
One specific Show
One specific TimeSlot for a show
"""
__tablename__ = 'timeslot'
timeslot_id = Column(Integer, primary_key=True)
......@@ -55,11 +73,16 @@ class TimeSlot(db.Model, TimeSlotModel):
# entry_end = Column(DateTime, nullable=False)
# source = Column(String(255))
class TimeSlotEntry(db.Model, TimeSlotModel):
def print(self):
return "TimeSlot starts @ "+self.timeslot_start+" and ends @ "+self.timeslot_end+" and plays "+self.source
class TimeSlotEntry(db.Model, TimeSlotEntryModel):
"""
One show can have multiple entries
"""
#entry_id = Column(Integer, primary_key=True, autoincrement=True)
__tablename__ = 'timeslotentry'
timeslot_id = Column(Integer, ForeignKey("timeslot.timeslot_id"))
entry_start = Column(DateTime, primary_key=True, nullable=False)
entry_end = Column(DateTime, primary_key=True, nullable=False)
......
......@@ -5,10 +5,10 @@ import zmq.auth
import redis
import random
import string
import simplejson
from zmq.auth.thread import ThreadAuthenticator
from threading import Event
from modules.controller.controller import AuraController
from libraries.security.whitelist import AuraWhitelist
from libraries.security.user import AuraUser
from modules.scheduling.scheduler import AuraScheduler
......@@ -18,10 +18,11 @@ class ServerZMQAdapter(threading.Thread):
config = None
controller = None
def __init__(self, ip, port, config):
def __init__(self, controller, config):
print("Initializing Server ZMQ")
self.ip = ip
self.port = str(port)
self.controller = controller
self.ip = config.get('zmqhostip')
self.port = config.get('zmqport')
# init
threading.Thread.__init__ (self)
......@@ -29,12 +30,6 @@ class ServerZMQAdapter(threading.Thread):
self.config = config
self.controller = AuraController(
self,
self.config.get('socketdir') + '/playd.sock',
self.config.get('socketdir') + '/record.sock',
self.config.get("install_dir"))
self.context = zmq.Context().instance()
self.authserver = ThreadAuthenticator(self.context)
self.socket = self.context.socket(zmq.REP)
......@@ -48,6 +43,7 @@ class ServerZMQAdapter(threading.Thread):
"""
run runs on function start
"""
self.controller.setSender(self)
self.startAuthserver()
self.socket.plain_server = True
print("binding to: tcp://"+self.ip+":"+self.port)
......@@ -59,44 +55,55 @@ class ServerZMQAdapter(threading.Thread):
while not self.shutdown_event.is_set():
print("waiting for zmq message on socket tcp://"+self.ip+":"+self.port+"\n")
data = self.socket.recv().decode("utf-8")
msg = b''
msg = ''
retval = None
self.can_send = True
datasplit = data.split(' ')
command = str(datasplit.pop(0))
params = "()" if len(datasplit) < 1 else "('" + "','".join(datasplit) + "')"
#params = "()" if len(datasplit) < 1 else "('" + "','".join(datasplit) + "')"
params = "()" if len(datasplit) < 1 else "'" + "','".join(datasplit) + "'"
try:
# if there are params => use exec and get no retval
# if there are no params => easily use getattr and get a retval
statement = "self.controller." + command + params
print("zmq received message '" + data + "' and executing " + statement)
#exec("retval = "+statement)
print("zmq received message '"+data+"' and executing "+statement)
exec(statement)
f = getattr(self.controller, command)
retval = f() # json string
except SyntaxError as e:
print(e)
msg = b'Warning: Syntax Error'
msg = 'Warning: Syntax Error'
self.controller.message(msg)
self.socket.send()
except AttributeError as e:
print(e)
msg = b'Warning: Method ' + command.encode() + b' does not exist'
msg = 'Warning: Method ' + command + ' does not exist'
self.controller.message(msg)
except TypeError as e:
print(e)
msg = b'Warning: Wrong number of params'
msg = 'Warning: Wrong number of params'
self.controller.message(msg)
except Exception as e:
print(e)
msg = b'Warning: Unknown Error'
msg = 'Warning: Unknown Error'
self.controller.message(msg)
if msg == b'':
msg = b'OK'
if msg == '':
msg = 'OK'
#print("return message: " + msg)
if retval is None:
self.socket.send(msg.encode())
else:
self.socket.send(retval.encode()) # str(retval).encode())
print("return message: "+msg.decode("utf-8"))
self.socket.send(msg)
return
......@@ -132,7 +139,7 @@ class ServerZMQAdapter(threading.Thread):
self.run()
# ------------------------------------------------------------------------------------------ #
def send(self,message):
def send(self, message):
"""
Send a message to the client
:param message: string
......@@ -142,7 +149,7 @@ class ServerZMQAdapter(threading.Thread):
self.socket.send(message.encode("utf-8"))
self.can_send = False
else:
print("cannot send message via ZMQ: "+message.decode())
print("cannot send message via ZMQ: "+str(message))
# ------------------------------------------------------------------------------------------ #
def startAuthserver(self):
......@@ -237,7 +244,7 @@ class ClientZMQAdapter:
print(e)
return False
return True
return self.message
# ------------------------------------------------------------------------------------------ #
def setUsername(self, username):
......
......@@ -20,13 +20,13 @@ from libraries.security.user import AuraUser
from libraries.base.schedulerconfig import AuraSchedulerConfig
from modules.scheduling.scheduler import AuraScheduler
from libraries.client.auraclient import AuraClient
from libraries.base.calendar import AuraCalendarService
"""
AuraController Class
Is holding the eventqueue and communicates with the liquidsoap server
Benötigt die LiquidsoapClient Klasse
Communicates with the liquidsoap server and the scheduler
"""
......@@ -34,16 +34,17 @@ class AuraController(LiquidController):
#auraclient = AuraClient()
messenger = AuraMessenger()
scheduler = AuraScheduler()
scheduler = None
userdb = AuraUser()
is_intern = False
lq_error = ''
config = None
sender = None
# Constructor
def __init__(self, sender, lqs_socket, lqs_recsocket, install_dir):
super().__init__(sender, lqs_socket, lqs_recsocket)
def __init__(self, config):
super().__init__(config.get('socketdir') + '/playd.sock', config.get('socketdir') + '/record.sock')
"""
Constructor
@type sender: object
......@@ -58,14 +59,24 @@ class AuraController(LiquidController):
self.knownfields = ["status", "album", "time", "title", "artist", "comment", "filename", "on_air", "source", "rid", "genre"]
self.job_result = ['', '', '', '', '', '']
self.sender = sender
self.messenger.setChannel('controller')
self.messenger.setSection('execjob')
errors_file = install_dir+"/errormessages/controller_error.js"
errors_file = config.get("install_dir")+"/errormessages/controller_error.js"
self.errorData = simplejson.load(open(errors_file))
self.scheduler = AuraScheduler(config)
self.config = config
# ------------------------------------------------------------------------------------------ #
def setSender(self, sender):
"""
:param sender: ServerZMQAdapter
:return: None
"""
self.sender = sender
# ------------------------------------------------------------------------------------------ #
def message(self, message, log=False, warning=False):
"""
......@@ -89,31 +100,27 @@ class AuraController(LiquidController):
else:
logging.info(message)
def newprogramme(self):
self.scheduler.newprogramme()
# ------------------------------------------------------------------------------------------ #
def scheduler_reload(self):
"""
Veranlasst den Scheduler zum Reload
"""
pids = psutil.get_pid_list()
foundProcess = False
for pid in pids:
cmd = psutil.Process(pid).cmdline
if len(cmd) > 1:
processName = cmd[1]
else:
processName = psutil.Process(pid).name
def fetch_new_programme(self):
acs = AuraCalendarService(self.config)
queue = acs.getQueue()
if processName.find(process) > 0:
os.kill(pid,signal.SIGUSR1)
foundProcess = True
break
if not foundProcess:
return False
# start fetching thread
acs.start()
# wait for the end
response = queue.get()
if response == "fetching_finished":
self.scheduler.reload_programme()
return acs.get_calendar_data()
else:
return True
print("Got an unknown response from AuraCalendarService: "+response)
# ------------------------------------------------------------------------------------------ #
def get_act_programme(self):
return self.scheduler.get_act_programme()
# ------------------------------------------------------------------------------------------ #
def scheduler_data(self):
......
......@@ -16,11 +16,9 @@ class LiquidController(object):
lqcr = None
# Constructor
def __init__(self, sender, lqs_socket, lqs_recsocket):
def __init__(self, lqs_socket, lqs_recsocket):
"""
Constructor
@type sender: object
@param sender: Der Communicator Adapter - z-B. zmq
@type lqs_socket: string
@param lqs_socket: Liquidsoap Player Socket
@type lqs_recsocket: string
......
......@@ -13,7 +13,7 @@ set("server.socket.path", "./<script>.sock")
#input_alsa = input.alsa(bufferize=false, id="alsa_in")
input_pulse = input.pulseaudio(id="linein")
#input_fs = single(id="fs", "/var/audio/fallback/music.wav")
input_http = input.http(id="http", "http://stream.fro.at/fro64.mp3")
input_http = input.http(id="http", "http://stream.fro.at/fro128.mp3")
......
......@@ -14,7 +14,7 @@ class ModelBroadcastEventOverrides(object):
@staticmethod
def upcoming(datefrom, freq):
dateto = (datefrom + timedelta(seconds=freq))
upcomingtracks = BroadcastEvent.query.filter(BroadcastEvent.start > datefrom, BroadcastEvent.start >= dateto).all()
#upcomingtracks = BroadcastEvent.query.filter(BroadcastEvent.start > datefrom, BroadcastEvent.start >= dateto).all()
# print(type(BroadcastEvent))
# print(BroadcastEvent)
......@@ -27,5 +27,5 @@ class ModelBroadcastEventOverrides(object):
# print((BroadcastEvent.start > datefrom))
# print((BroadcastEvent.start <= dateto))
return upcomingtracks
return None #upcomingtracks
......@@ -27,6 +27,7 @@ __author__ = 'Michael Liebler <michael-liebler@radio-z.net>'
"""
Comba Scheduler Klasse
Is holding the eventqueue
"""
import signal
import pyev
......@@ -42,13 +43,11 @@ from glob import glob
import threading
# Die eigenen Bibliotheken
from libraries.base.config import ConfigReader
from libraries.base.schedulerconfig import AuraSchedulerConfig
from libraries.reporting.messenger import AuraMessenger
#from libraries.base.calendar import AuraCalendarService
from libraries.base.calendar import AuraCalendarService
from modules.scheduling.models import ModelBroadcastEventOverrides
from libraries.database.broadcasts import TimeSlot
from sqlalchemy.sql import select
from libraries.database.broadcasts import TimeSlot, TimeSlotEntry
"""
Comba Scheduler Class
......@@ -58,12 +57,14 @@ Liefert Start und Stop Jobs an den Comba Controller, lädt XML-Playlisten und r
class AuraScheduler():
messenger = AuraMessenger()
auraconfig = ConfigReader()
timeslotentries = None
timeslotevents = None
schedulerconfig = None
client = None
def __init__(self): #, liquidsoap_client):
def __init__(self, config): #, liquidsoap_client):
"""
Constructor
@type liquidsoap_client: object
......@@ -71,6 +72,7 @@ class AuraScheduler():
@type config: string
@param config: Pfad zum scheduler.xml
"""
self.auraconfig = config
self.auraconfig.loadConfig()
#self.client = liquidsoap_client
......@@ -99,9 +101,10 @@ class AuraScheduler():
self.scriptdir = os.path.dirname(os.path.abspath(__file__)) + '/..'
self.timeslotevents = TimeSlotEntry.query.filter
#errors_file = os.path.dirname(os.path.realpath(__file__)) + '/error/scheduler_error.js'
errors_file = self.auraconfig.get("install_dir") + "/errormessages/controller_error.js"
json_data = open(errors_file)
json_data = open(self.auraconfig.get("install_dir") + "/errormessages/scheduler_error.js")
self.errorData = simplejson.load(json_data)
self.messenger.send('Scheduler started', '0000', 'success', 'initApp', None, 'appinternal')
......@@ -145,14 +148,23 @@ class AuraScheduler():
self.messenger.send('Scheduler reloaded by user', '0500', 'success', 'reload', None, 'appinternal')
self.start()
def newprogramme(self):
# ------------------------------------------------------------------------------------------ #
def reload_programme(self):
self.programme = TimeSlotEntry.select_all()
def newProgramme(self):
# self.
# fetch timeslots from database
timeslotsdb = TimeSlot.query.filter().all()
timeslotsdb = TimeSlot.getall()
print(timeslotsdb)
for ts_db in timeslotsdb:
print(ts_db.show_id)
print("new programme in scheduler")
s = select([TimeSlot])
#s = select([TimeSlot])
def get_act_programme(self):
return self.programme
# ------------------------------------------------------------------------------------------ #
......@@ -291,6 +303,7 @@ class AuraScheduler():
@type revents: object
@param revents: Event Callbacks
"""
print("AuraScheduler saying alive")
self.messenger.sayAlive()
# ------------------------------------------------------------------------------------------ #
......@@ -511,9 +524,9 @@ class AuraScheduler():
# ------------------------------------------------------------------------------------------ #
def on_start(self, watcher, revents):
if self.get('has_input_device'):
self.client.playlist_play()
self.client.playlist_pause()
# if self.auraconfig.get('has_input_device'):
self.client.playlist_play()
self.client.playlist_pause()
watcher.stop()
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment