Commit 25b71990 authored by Gottfried Gaisbauer's avatar Gottfried Gaisbauer
Browse files

verbindung zwischen guru und auraserver bei fetchNewProgrammes

parent 7c5e6e04
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
This diff is collapsed.
......@@ -2,6 +2,8 @@ import signal
import sys
import threading
from datetime import datetime
from libraries.base.config import ConfigReader
from libraries.reporting.messenger import AuraMessenger
from modules.communication.zmq.zmqadapter import ServerZMQAdapter
......@@ -33,8 +35,8 @@ class Aura(threading.Thread):
try:
while server.is_alive():
print("joining")
server.join(timeout=1.0)
print(str(datetime.now())+" joining")
server.join(timeout=5.0)
# if cnt % 30 == 0:
# print(datetime.datetime.now().isoformat())
......
......@@ -8,6 +8,7 @@ from modules.communication.liquidsoap.LiquidSoapCommunicator import LiquidSoapCo
# 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
class Guru:
......@@ -83,8 +84,7 @@ class Guru:
time.sleep(2) # well, ok, here i should listen to a AuraMessenger
nextshows = self.acs.getCalendarData()
for show in nextshows:
print(show)
print("received "+str(len(nextshows))+" timeslot entries")
return nextshows
......
......@@ -25,34 +25,39 @@ import threading
import simplejson
from libraries.database.broadcasts import Timeslot
from libraries.database.broadcasts import TimeSlot, TimeSlotEntry
from libraries.reporting.messenger import AuraMessenger
from modules.communication.zmq.zmqadapter import ClientZMQAdapter
class AuraCalendarService(threading.Thread):
messenger = AuraMessenger()
calendarurl = ""
audiobase = ""
playlistdir = ""
until = ''
secondspertrack = 0
xmlplaylist = range(0)
config = None
zmqclient = None
"""
Fetching playlist data, write it into the database and notify service
"""
def __init__(self, config, datefrom="", dateto=""):
threading.Thread.__init__(self)
self.config = config
self.messenger = AuraMessenger()
self.messenger.setChannel('aura')
self.messenger.setSection('getcalendar')
self.messenger.setMailAddresses(self.config.get('frommail'), self.config.get('adminmail'))
self.zmqclient = ClientZMQAdapter(self.config.get('zmqhostip'), self.config.get('zmqport'))
#self.zmqmessenger = AuraZMQAdapter(self.config.get('zmqip'), self.config.get('zmqport'), config)
self.xmlplaylist = range(0)
self.messenger.setMailAddresses(self.config.get('frommail'), self.config.get('adminmail'))
self.dateto = dateto
self.datefrom = str(datefrom)
self.until = ''
self.secondspertrack = 0
self.calendarurl = ""
self.audiobase = ""
self.playlistdir = ""
# ------------------------------------------------------------------------------------------ #
def setDateFrom(self, date):
......@@ -122,6 +127,8 @@ class AuraCalendarService(threading.Thread):
self.secondspertrack = int(self.secondspertrack)
#print(self.data['timeslots'])
entrynum = 0
lasttimeslot_id = 0
for timeslot in self.data:
#fix nonexisting origdatetime
if 'end' not in timeslot:
......@@ -129,28 +136,34 @@ class AuraCalendarService(threading.Thread):
if 'start' not in timeslot:
continue
print("start&end set! json timeslot accepted")
print("showidentifier: "+str(timeslot['show_id']))
timeslot_db = Timeslot.query.filter(Timeslot.id == timeslot['show_id']).first()
timeslot_db = TimeSlot.query.filter(TimeSlot.timeslot_id == timeslot['timeslot_id']).first()
if not timeslot_db:
print("not event")
timeslot_db = Timeslot()
print("no timeslot with given timeslot id in database => create new")
timeslot_db = TimeSlot()
#for tableentry in Timeslot.query.filter().all():
# print(tableentry)
timeslot_entry = TimeSlotEntry.query.filter(TimeSlotEntry.entry_start == timeslot["start"], TimeSlotEntry.entry_end == timeslot["end"]).first()
if not timeslot_entry:
print("no timeslotentry from "+timeslot["start"]+" to "+timeslot["end"]+" found")
timeslot_entry = TimeSlotEntry()
# calc duration
duration = self._calcDuration(timeslot['start'], timeslot['end'])
timeslot['duration'] = datetime.timedelta(seconds=duration).__str__()
# print("is " + str(lasttimeslot_id) + " == " + str(timeslot["timeslot_id"]))
# if lasttimeslot_id == timeslot["timeslot_id"]:
# print("yes")
# entrynum = entrynum + 1
# else:
# print("no")
# entrynum = 0
# lasttimeslot_id = timeslot["timeslot_id"]
timeslot_db.show_id = timeslot["show_id"]
timeslot_db.timeslot_id = timeslot["timeslot_id"]
timeslot_db.show_id = timeslot["show_id"]
timeslot_db.timeslot_start = timeslot["timeslot_start"]
timeslot_db.timeslot_end = timeslot["timeslot_end"]
timeslot_db.start = timeslot["start"]
timeslot_db.end = timeslot["end"]
timeslot_db.source = timeslot["source"]
timeslot_db.show_name = timeslot["show_name"]
timeslot_db.show_hosts = timeslot["show_hosts"]
timeslot_db.is_repetition = timeslot["is_repetition"]
......@@ -158,8 +171,13 @@ class AuraCalendarService(threading.Thread):
timeslot_db.show_fallback_pool = timeslot["show_fallback_pool"]
timeslot_db.station_fallback_pool = timeslot["station_fallback_pool"]
timeslot_db.store()
timeslot_db.commit() # getting id after commit
timeslot_entry.timeslot_id = timeslot["timeslot_id"]
timeslot_entry.entry_start = timeslot["start"]
timeslot_entry.entry_end = timeslot["end"]
timeslot_entry.source = timeslot["source"]
timeslot_db.store(True)
timeslot_entry.store(True)
event = {'job': 'dump', 'location': timeslot['timeslot_id'], 'length': duration}
self.messenger.queueAddEvent('dumpstart', timeslot["start"], event, 'recorder')
......@@ -235,7 +253,6 @@ class AuraCalendarService(threading.Thread):
#jsondata = '{"timeslots":[{"id":"0","name":"frozine","playlist_id":"file:///var/audio/test.flac","shortdesc":"test description","start":"2017-09-26 10:00:00","end":"2017-09-26 11:00:00","fallback_pool":"/var/audio","fallback_playlist":"/var/audio/fallback.pls"},{"id":"1","name":"bücherwahl","playlist_id":"http://fro.at:8000/listen.pls","shortdesc":"test description","start":"2017-09-26 11:00:00","end":"2017-09-26 12:00:00","fallback_pool":"/var/audio","fallback_playlist":"/var/audio/fallback.pls"},{"id":"2","name":"Radio Bulgari","playlist_id":"pool:///var/audio/","shortdesc":"test description","start":"2017-09-26 12:00:00","end":"2017-09-26 13:00:00","fallback_pool":"/var/audio","fallback_playlist":"/var/audio/fallback.pls"},{"id":"3","name":"FROmat","playlist_id":"file:///var/audio/test.flac","shortdesc":"test description","start":"2017-09-26 13:00:00","end":"2017-09-26 14:00:00","fallback_pool":"/var/audio","fallback_playlist":"/var/audio/fallback.pls"},{"id":"4","name":"frozine","playlist_id":"file:///var/audio/test.flac","shortdesc":"test description","repetition_id":1,"start":"2017-09-26 14:00:00","end":"2017-09-26 15:00:00","fallback_pool":"/var/audio","fallback_playlist":"/var/audio/fallback.pls"}]}'
try:
self.data = simplejson.loads(jsondata)
print("json loaded")
except Exception as e:
self.messenger.send("Could not decode calender data from service " + self.dataURL + "! Exception: "+e, '1102', 'error',
'fetchCalenderData', self._getErrorData(), 'getcalendar')
......@@ -243,8 +260,9 @@ class AuraCalendarService(threading.Thread):
else:
# check data
try:
print(self.data)
print(len(self.data))
print("json data not really checked. i believe what i get")
#print(self.data)
#print(len(self.data))
except KeyError as e:
self.messenger.send("Could not decode calender data from service " + self.dataURL + "! Exception: "+e, '1102', 'error',
'fetchCalenderData', self._getErrorData(), 'getcalendar')
......@@ -288,7 +306,7 @@ class AuraCalendarService(threading.Thread):
"""
#print(self.calendarurl)
self.dataURL = self.calendarurl.replace('#datefrom#', self.datefrom.replace(' ', 'T')).replace('#dateto#', self.dateto.replace(' ', 'T'))
print("URL set: "+self.dataURL)
#print("URL set: "+self.dataURL)
def getUrl(self):
url = self.dataURL[0:self.dataURL.find('&')]
......@@ -297,7 +315,7 @@ class AuraCalendarService(threading.Thread):
def getData(self):
params = self.dataURL[self.dataURL.find('&'):]
print("params: "+params)
#print("params: "+params)
def getCalendarData(self):
return self.data
\ No newline at end of file
# -*- coding: utf-8 -*-
import sys
import simplejson
import urllib
"""
Die AuraClient Klasse stellt die Tasks zur Verfügung,
die dem Playlout Controller übertragen werden können
Dies ist im Wesentlichen ein Wrapper
"""
class AuraClient():
def __init__(self, sender):
"""
Constructor
@type sender: object
@param sender: Der Communicator Adapter - z-B. zmq
"""
self.sender = sender
# ------------------------------------------------------------------------------------------ #
def command(self, command):
"""
Kommando an den Controller absetzen
und Antwort entgegennehmen
@type command: string
@param command: Kommando
@rtype: string
@return: Antwort des Controllers
"""
self.sender.send(command)
message = self.sender.receive()
return message
# ------------------------------------------------------------------------------------------ #
def channel_skip(self, channel):
"""
Skipt einen Kanal oder die Playlist
@type channel: string
@param channel: Kanal
@rtype: string
@return: Antwort des Controllers
"""
return self.command('channel_skip ' + channel)
# ------------------------------------------------------------------------------------------ #
def channel_is_active(self, channel='playlist'):
"""
Ist der Kanal aktiv?
@type channel: string
@param channel: Kanal
@rtype: boolean
@return: True/False
"""
state = self._get_channel_state(channel)
is_active = True if state['selected'] == 'true' else False
return is_active
# ------------------------------------------------------------------------------------------ #
def channel_on(self, channel):
"""
Kanal einschalten
@type channel: string
@param channel: Kanal
@rtype: string
@return: Antwort des Controllers
"""
return self.command('channel_on ' + channel)
# ------------------------------------------------------------------------------------------ #
def channel_off(self, channel):
"""
Kanal ausschalten
@type channel: string
@param channel: Kanal
@rtype: string
@return: Antwort des Controllers
"""
return self.command('channel_off ' + channel)
# ------------------------------------------------------------------------------------------ #
def get_channellist(self):
"""
Channels als Liste ausgeben
@rtype: list
@return: Antwort des Controllers
"""
return simplejson.loads(self.command('listChannels'))
# ------------------------------------------------------------------------------------------ #
def get_channelqueue(self, channel):
"""
Channel Queue ausgeben
@type channel: string
@param channel: Kanal
@rtype: dict
@return: Antwort des Controllers
"""
return simplejson.loads(self.command('channel_queue ' + channel))
# ------------------------------------------------------------------------------------------ #
def get_channel_volume(self, channel='playlist'):
"""
Lautstärke des Kanals ausgeben
@type channel: string
@param channel: Kanal
@rtype: string/boolean
@return: Volumen von 1-100/False
"""
state = self._get_channel_state(channel)
channels = simplejson.loads(self.command('allData'))
try:
volume = state['volume']
except KeyError:
return False
else:
return volume
return False
# ------------------------------------------------------------------------------------------ #
def channel_remove_track(self, channel, track_pos):
"""
Löscht einen Track aus dem secondary_queue
@type channel: string
@param channel: Kanal
@type track_pos: string/int
@param track_pos: Position des zu entfernenden Eintrags
@rtype: string
@return: Antwort des Controllers
"""
return self.command('channel_remove ' + channel + ' ' + str(track_pos))
# ------------------------------------------------------------------------------------------ #
def channel_seek(self, channel, duration):
"""
Spult den laufenen Track des Kanals <duration> Sekunden weiter (falls möglich)
Beispiel: channel_seek('ch1',60) - 60 Sekunden nach vorne
@type channel: string
@param channel: Kanal
@type duration: string/int
@param duration: Dauer in Sekunden
@rtype: string
@return: Antwort des Controllers
"""
return self.command('channel_seek ' + channel + ' ' + str(duration))
# ------------------------------------------------------------------------------------------ #
def channel_track_up(self, channel, track_pos):
"""
Einen Track um eine Position nach oben schieben
@type channel: string
@param channel: Kanal
@type track_pos: string
@param track_pos: Position des zu verschiebenden Eintrags
@rtype: string
@return: Antwort des Controllers
"""
return self.command('channel_move ' + channel + ' ' + str(track_pos) + ' ' + str(track_pos - 1))
# ------------------------------------------------------------------------------------------ #
def channel_track_down(self, channel, track_pos):
"""
Einen Track um eine Position nach unten schieben
@type channel: string
@param channel: Kanal
@type track_pos: string
@param track_pos: Position des zu verschiebenden Eintrags
@rtype: string
@return: Antwort des Controllers
"""
return self.command('channel_move ' + channel + ' ' + str(track_pos) + ' ' + str(track_pos + 1))
# ------------------------------------------------------------------------------------------ #
def channel_track_insert(self, channel, uri, pos=0):
"""
Uri eines Audios in den (secondary) queue einfügen
@type channel: string
@param channel: Kanal
@type uri: string
@param uri: uri, z.b. file:///my/audio/song.mp3
@rtype: string
@return: Antwort des Controllers
"""
return self.command('channel_insert ' + channel + ' ' + urllib.quote(uri) + ' ' + str(pos))
# ------------------------------------------------------------------------------------------ #
def channel_set_volume(self, channel, volume):
"""
Lautstärke setzen (Prozentual von 1 - 100
@type channel: string
@param channel: Kanal
@type volume: string/int
@param volume: Zahl von 1 bis 100
@rtype: string
@return: Antwort des Controllers
"""
return self.command('channel_volume ' + channel + ' ' + str(volume))
# ------------------------------------------------------------------------------------------ #
def _get_channel_state(self, channel):
"""
Private: Status eines Kanals abfragen
Ausgabe Beispiel: {'ready':'true', 'selected:'false', 'single':'false','volume':'100%','remaining:'0.00'}
@type channel: string
@param channel: Kanal
@rtype: dict/boolen
@return: Antwort des Controllers/ False
"""
data = simplejson.loads(self.command('allData'))
if not isinstance(data, dict):
# es wurde kein assoz. Array/dict zurückgegeben
return False
if data['success'] != 'success':
# die Abfrage war nicht erfolgreich
return False
if not data.has_key('value'):
# es wurden keine Werte geliefert
return False
channels = data['value']
if not isinstance(channels, dict):
# es wurde kein assoz. Array/dict zurückgegeben
return False
if channels.has_key(channel):
chan = channels[channel]
try:
state = chan['state']
except KeyError:
return False
else:
return state
else:
return False
# ------------------------------------------------------------------------------------------ #
def playlist_load(self, uri):
"""
Playlist im XSPF-Format laden
@type uri: string
@param uri: Uri einer Playlist - z.B. /my/playlists/2014-12-22-12-00.xspf
@rtype: string
@return: Antwort des Controllers
"""
return self.command('playlist_load ' + str(uri))
# ------------------------------------------------------------------------------------------ #
def playlist_data(self):
"""
Gibt die aktuelle Playlist als dict zurück
@rtype: dict
@return: Antwort des Controllers
"""
return simplejson.loads(self.command('playlist_data'))
# ------------------------------------------------------------------------------------------ #
def playlist_flush(self):
"""
Leert die Playlist
@rtype: dict
@return: Antwort des Controllers
"""
return self.command('playlist_flush')
# ------------------------------------------------------------------------------------------ #
def playlist_insert(self, uri, pos):
"""
Audio in Playlist einfügen
@type uri: string
@param uri: Uri einer Audiodatei - z.B. /my/audio/song.mp3
@rtype: string
@return: Antwort des Controllers
"""
return self.command('playlist_insert ' + uri + ' ' + pos)
# ------------------------------------------------------------------------------------------ #
def playlist_track_up(self, track_pos):
"""
Einen Track der Playlist um eine Position nach oben schieben
@type track_pos: string
@param track_pos: Position des zu verschiebenden Eintrags
@rtype: string
@return: Antwort des Controllers
"""
return self.command('playlist_move ' + str(track_pos) + ' ' + str(track_pos - 1))
# ------------------------------------------------------------------------------------------ #
def playlist_track_down(self, track_pos):
"""
Einen Track der Playlist um eine Position nach unten schieben
@type track_pos: string
@param track_pos: Position des zu verschiebenden Eintrags
@rtype: string
@return: Antwort des Controllers
"""
self.command('playlist_move ' + str(track_pos) + ' ' + str(track_pos + 1))
# ------------------------------------------------------------------------------------------ #
def playlist_pause(self):
"""
Playlist anhalten
@rtype: string
@return: Antwort des Controllers
"""
return self.command('playlist_pause')
# ------------------------------------------------------------------------------------------ #
def playlist_stop(self):
"""
Playlist stoppen
@rtype: string
@return: Antwort des Controllers
"""
return self.command('playlist_stop')
# ------------------------------------------------------------------------------------------ #
def playlist_play(self):
"""
Playlist starten/abspielen
@rtype: string
@return: Antwort des Controllers
"""
return self.command('playlist_play')
# ------------------------------------------------------------------------------------------ #
def playlist_remove_track(self, track_pos):
"""
Löscht einen Track der Playlist
Hinweis: Der laufende Track wird nicht berücksichtigt
@type track_pos: string/int
@param track_pos: Position des zu entfernenden Eintrags
@rtype: string
@return: Antwort des Controllers
"""
return self.command('playlist_remove ' + str(track_pos))
# ------------------------------------------------------------------------------------------ #
def playlist_seek(self, duration):
"""
Spult den laufenden Track der Playlist <duration> Sekunden weiter (falls möglich)
Beispiel: playlist_seek('ch1',60) - 60 Sekunden nach vorne
@type duration: string/int
@param duration: Dauer in Sekunden
@rtype: string
@return: Antwort des Controllers
"""
return self.command('playlist_seek ' + str(duration))
# ------------------------------------------------------------------------------------------ #
def playlist_skip(self):
"""
Skipt den laufenden Track der Playlist
@rtype: string
@return: Antwort des Controllers
"""
return self.command('playlist_skip')
# ------------------------------------------------------------------------------------------ #
def recorder_start(self):
"""
Recorder starten
@rtype: string
@return: Antwort des Controllers
"""
return self.command('recorder_start')
# ------------------------------------------------------------------------------------------ #
def recorder_stop(self):
"""
Recorder stoppen
@rtype: string
@return: Antwort des Controllers
"""
return self.command('recorder_stop')
def recorder_data(self):
"""
Daten der aktuellen Aufnahme abrufen
Beispiel: {'file':'/my/audio/2014-12-22-12-00.wav', 'recorded': '25'} - Die Aufnahme der Datei /my/audio/2014-12-22-12-00.wav ist bei 25%
@rtype: dict
@return: Antwort des Controllers
"""
return simplejson.loads(self.command('recorder_data'))
\ No newline at end of file
__author__ = 'michel'
# -*- coding: utf-8 -*-
import datetime, os, urllib
import datetime, os, urllib, sys
import pprint
from flask_sqlalchemy import SQLAlchemy
from flask_babel import Babel, get_locale
from flask import Flask
#from modules.web import db
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Boolean, Column, Date, DateTime, Float, Integer, String, Text, Time, ForeignKey
from libraries.base.config import ConfigReader
Base = declarative_base()
#from modules.web import db
#### DATABASE CONN ####
config = ConfigReader()
ini_path = "/etc/comba/comba.ini"
config.set('configpath', ini_path)
config.loadConfig()