mirror of
https://github.com/fHDHR/fHDHR_NextPVR.git
synced 2025-12-06 13:26:57 -05:00
commit
bf312bc009
@ -5,10 +5,25 @@
|
|||||||
"config_file": true,
|
"config_file": true,
|
||||||
"config_web": false
|
"config_web": false
|
||||||
},
|
},
|
||||||
"refresh_frequency":{
|
"max_age":{
|
||||||
"value": 1800,
|
"value": 1800,
|
||||||
"config_file": true,
|
"config_file": true,
|
||||||
"config_web": false
|
"config_web": false
|
||||||
|
},
|
||||||
|
"proto":{
|
||||||
|
"value": "ipv4",
|
||||||
|
"config_file": true,
|
||||||
|
"config_web": false
|
||||||
|
},
|
||||||
|
"iface":{
|
||||||
|
"value": "none",
|
||||||
|
"config_file": true,
|
||||||
|
"config_web": false
|
||||||
|
},
|
||||||
|
"multicast_address":{
|
||||||
|
"value": "none",
|
||||||
|
"config_file": true,
|
||||||
|
"config_web": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
from .originwrapper import OriginServiceWrapper
|
from .originwrapper import OriginServiceWrapper
|
||||||
from .device import fHDHR_Device
|
from .device import fHDHR_Device
|
||||||
|
from .api import fHDHR_API_URLs
|
||||||
|
|
||||||
import fHDHR.tools
|
import fHDHR.tools
|
||||||
|
|
||||||
fHDHR_VERSION = "v0.4.5-beta"
|
fHDHR_VERSION = "v0.4.6-beta"
|
||||||
|
|
||||||
|
|
||||||
class fHDHR_INT_OBJ():
|
class fHDHR_INT_OBJ():
|
||||||
@ -18,10 +19,12 @@ class fHDHR_INT_OBJ():
|
|||||||
|
|
||||||
self.web = fHDHR.tools.WebReq()
|
self.web = fHDHR.tools.WebReq()
|
||||||
|
|
||||||
|
self.api = fHDHR_API_URLs(settings)
|
||||||
|
|
||||||
|
|
||||||
class fHDHR_OBJ():
|
class fHDHR_OBJ():
|
||||||
|
|
||||||
def __init__(self, settings, logger, db, alternative_epg, origin):
|
def __init__(self, settings, logger, db, origin, alternative_epg):
|
||||||
self.fhdhr = fHDHR_INT_OBJ(settings, logger, db)
|
self.fhdhr = fHDHR_INT_OBJ(settings, logger, db)
|
||||||
|
|
||||||
self.originwrapper = OriginServiceWrapper(self.fhdhr, origin)
|
self.originwrapper = OriginServiceWrapper(self.fhdhr, origin)
|
||||||
|
|||||||
36
fHDHR/api/__init__.py
Normal file
36
fHDHR/api/__init__.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import urllib.parse
|
||||||
|
|
||||||
|
|
||||||
|
class fHDHR_API_URLs():
|
||||||
|
|
||||||
|
def __init__(self, settings):
|
||||||
|
self.config = settings
|
||||||
|
|
||||||
|
self.address = self.config.dict["fhdhr"]["address"]
|
||||||
|
self.discovery_address = self.config.dict["fhdhr"]["discovery_address"]
|
||||||
|
self.port = self.config.dict["fhdhr"]["port"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def base(self):
|
||||||
|
if self.discovery_address:
|
||||||
|
return ('http://%s:%s' % self.discovery_address_tuple)
|
||||||
|
elif self.address == "0.0.0.0":
|
||||||
|
return ('http://%s:%s' % self.address_tuple)
|
||||||
|
else:
|
||||||
|
return ('http://%s:%s' % self.address_tuple)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def base_quoted(self):
|
||||||
|
return urllib.parse.quote(self.base)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def discovery_address_tuple(self):
|
||||||
|
return (self.discovery_address, int(self.port))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def localhost_address_tuple(self):
|
||||||
|
return ("127.0.0.1", int(self.port))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def address_tuple(self):
|
||||||
|
return (self.address, int(self.port))
|
||||||
@ -9,7 +9,6 @@ import platform
|
|||||||
from fHDHR import fHDHR_VERSION, fHDHR_OBJ
|
from fHDHR import fHDHR_VERSION, fHDHR_OBJ
|
||||||
import fHDHR.exceptions
|
import fHDHR.exceptions
|
||||||
import fHDHR.config
|
import fHDHR.config
|
||||||
from fHDHR.http import fHDHR_HTTP_Server
|
|
||||||
from fHDHR.db import fHDHRdb
|
from fHDHR.db import fHDHRdb
|
||||||
|
|
||||||
ERR_CODE = 1
|
ERR_CODE = 1
|
||||||
@ -32,16 +31,16 @@ def build_args_parser():
|
|||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
def get_configuration(args, script_dir):
|
def get_configuration(args, script_dir, origin, fHDHR_web):
|
||||||
if not os.path.isfile(args.cfg):
|
if not os.path.isfile(args.cfg):
|
||||||
raise fHDHR.exceptions.ConfigurationNotFound(filename=args.cfg)
|
raise fHDHR.exceptions.ConfigurationNotFound(filename=args.cfg)
|
||||||
return fHDHR.config.Config(args.cfg, script_dir)
|
return fHDHR.config.Config(args.cfg, script_dir, origin, fHDHR_web)
|
||||||
|
|
||||||
|
|
||||||
def run(settings, logger, db, alternative_epg, origin):
|
def run(settings, logger, db, script_dir, fHDHR_web, origin, alternative_epg):
|
||||||
|
|
||||||
fhdhr = fHDHR_OBJ(settings, logger, db, alternative_epg, origin)
|
fhdhr = fHDHR_OBJ(settings, logger, db, origin, alternative_epg)
|
||||||
fhdhrweb = fHDHR_HTTP_Server(fhdhr)
|
fhdhrweb = fHDHR_web.fHDHR_HTTP_Server(fhdhr)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
@ -81,11 +80,11 @@ def run(settings, logger, db, alternative_epg, origin):
|
|||||||
return ERR_CODE
|
return ERR_CODE
|
||||||
|
|
||||||
|
|
||||||
def start(args, script_dir, alternative_epg, origin):
|
def start(args, script_dir, fHDHR_web, origin, alternative_epg):
|
||||||
"""Get Configuration for fHDHR and start"""
|
"""Get Configuration for fHDHR and start"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
settings = get_configuration(args, script_dir)
|
settings = get_configuration(args, script_dir, origin, fHDHR_web)
|
||||||
except fHDHR.exceptions.ConfigurationError as e:
|
except fHDHR.exceptions.ConfigurationError as e:
|
||||||
print(e)
|
print(e)
|
||||||
return ERR_CODE_NO_RESTART
|
return ERR_CODE_NO_RESTART
|
||||||
@ -94,17 +93,19 @@ def start(args, script_dir, alternative_epg, origin):
|
|||||||
|
|
||||||
db = fHDHRdb(settings)
|
db = fHDHRdb(settings)
|
||||||
|
|
||||||
return run(settings, logger, db, alternative_epg, origin)
|
return run(settings, logger, db, script_dir, fHDHR_web, origin, alternative_epg)
|
||||||
|
|
||||||
|
|
||||||
def main(script_dir, alternative_epg, origin):
|
def main(script_dir, fHDHR_web, origin, alternative_epg):
|
||||||
"""fHDHR run script entry point"""
|
"""fHDHR run script entry point"""
|
||||||
|
|
||||||
print("Loading fHDHR " + fHDHR_VERSION)
|
print("Loading fHDHR %s" % fHDHR_VERSION)
|
||||||
|
print("Loading fHDHR_web %s" % fHDHR_web.fHDHR_web_VERSION)
|
||||||
|
print("Loading Origin Service: %s %s" % (origin.ORIGIN_NAME, origin.ORIGIN_VERSION))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
args = build_args_parser()
|
args = build_args_parser()
|
||||||
return start(args, script_dir, alternative_epg, origin)
|
return start(args, script_dir, fHDHR_web, origin, alternative_epg)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("\n\nInterrupted")
|
print("\n\nInterrupted")
|
||||||
return ERR_CODE
|
return ERR_CODE
|
||||||
|
|||||||
@ -15,7 +15,10 @@ from fHDHR.tools import isint, isfloat, is_arithmetic, is_docker
|
|||||||
|
|
||||||
class Config():
|
class Config():
|
||||||
|
|
||||||
def __init__(self, filename, script_dir):
|
def __init__(self, filename, script_dir, origin, fHDHR_web):
|
||||||
|
self.origin = origin
|
||||||
|
self.fHDHR_web = fHDHR_web
|
||||||
|
|
||||||
self.internal = {}
|
self.internal = {}
|
||||||
self.conf_default = {}
|
self.conf_default = {}
|
||||||
self.dict = {}
|
self.dict = {}
|
||||||
@ -27,7 +30,8 @@ class Config():
|
|||||||
def initial_load(self, script_dir):
|
def initial_load(self, script_dir):
|
||||||
|
|
||||||
data_dir = pathlib.Path(script_dir).joinpath('data')
|
data_dir = pathlib.Path(script_dir).joinpath('data')
|
||||||
www_dir = pathlib.Path(data_dir).joinpath('www')
|
fHDHR_web_dir = pathlib.Path(script_dir).joinpath('fHDHR_web')
|
||||||
|
www_dir = pathlib.Path(fHDHR_web_dir).joinpath('www_dir')
|
||||||
|
|
||||||
self.internal["paths"] = {
|
self.internal["paths"] = {
|
||||||
"script_dir": script_dir,
|
"script_dir": script_dir,
|
||||||
@ -37,7 +41,7 @@ class Config():
|
|||||||
"cache_dir": pathlib.Path(data_dir).joinpath('cache'),
|
"cache_dir": pathlib.Path(data_dir).joinpath('cache'),
|
||||||
"internal_config": pathlib.Path(data_dir).joinpath('internal_config'),
|
"internal_config": pathlib.Path(data_dir).joinpath('internal_config'),
|
||||||
"www_dir": www_dir,
|
"www_dir": www_dir,
|
||||||
"www_templates_dir": pathlib.Path(www_dir).joinpath('templates'),
|
"www_templates_dir": pathlib.Path(fHDHR_web_dir).joinpath('templates'),
|
||||||
"font": pathlib.Path(data_dir).joinpath('garamond.ttf'),
|
"font": pathlib.Path(data_dir).joinpath('garamond.ttf'),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +68,10 @@ class Config():
|
|||||||
|
|
||||||
self.internal["versions"]["fHDHR"] = fHDHR_VERSION
|
self.internal["versions"]["fHDHR"] = fHDHR_VERSION
|
||||||
|
|
||||||
|
self.internal["versions"]["fHDHR_web"] = self.fHDHR_web.fHDHR_web_VERSION
|
||||||
|
|
||||||
|
self.internal["versions"][self.origin.ORIGIN_NAME] = self.origin.ORIGIN_VERSION
|
||||||
|
|
||||||
self.internal["versions"]["Python"] = sys.version
|
self.internal["versions"]["Python"] = sys.version
|
||||||
|
|
||||||
opersystem = platform.system()
|
opersystem = platform.system()
|
||||||
|
|||||||
@ -71,22 +71,34 @@ class Channels():
|
|||||||
|
|
||||||
if updatelist:
|
if updatelist:
|
||||||
channel_origin_id_list = [str(self.list[x].dict["origin_id"]) for x in list(self.list.keys())]
|
channel_origin_id_list = [str(self.list[x].dict["origin_id"]) for x in list(self.list.keys())]
|
||||||
|
|
||||||
self.fhdhr.logger.info("Performing Channel Scan.")
|
self.fhdhr.logger.info("Performing Channel Scan.")
|
||||||
|
|
||||||
channel_dict_list = self.origin.get_channels()
|
channel_dict_list = self.origin.get_channels()
|
||||||
|
self.fhdhr.logger.info("Found %s channels for %s." % (len(channel_dict_list), self.fhdhr.config.dict["main"]["servicename"]))
|
||||||
|
|
||||||
|
newchan = 0
|
||||||
for channel_info in channel_dict_list:
|
for channel_info in channel_dict_list:
|
||||||
|
|
||||||
chan_existing = False
|
chan_existing = False
|
||||||
if str(channel_info["id"]) in channel_origin_id_list:
|
if str(channel_info["id"]) in channel_origin_id_list:
|
||||||
chan_existing = True
|
chan_existing = True
|
||||||
channel_obj = self.get_channel_obj("origin_id", channel_info["id"])
|
channel_obj = self.get_channel_obj("origin_id", channel_info["id"])
|
||||||
else:
|
else:
|
||||||
channel_obj = Channel(self.fhdhr, self.id_system, origin_id=channel_info["id"])
|
channel_obj = Channel(self.fhdhr, self.id_system, origin_id=channel_info["id"])
|
||||||
|
|
||||||
channel_id = channel_obj.dict["id"]
|
channel_id = channel_obj.dict["id"]
|
||||||
channel_obj.basics(channel_info)
|
channel_obj.basics(channel_info)
|
||||||
if not chan_existing:
|
if not chan_existing:
|
||||||
self.list[channel_id] = channel_obj
|
self.list[channel_id] = channel_obj
|
||||||
|
newchan += 1
|
||||||
|
|
||||||
|
if not newchan:
|
||||||
|
newchan = "no"
|
||||||
|
self.fhdhr.logger.info("Found %s NEW channels." % newchan)
|
||||||
|
|
||||||
|
self.fhdhr.logger.info("Total Channel Count: %s" % len(self.list.keys()))
|
||||||
|
|
||||||
if not self.list_update_time:
|
|
||||||
self.fhdhr.logger.info("Found " + str(len(self.list)) + " channels for " + str(self.fhdhr.config.dict["main"]["servicename"]))
|
|
||||||
self.list_update_time = datetime.datetime.now()
|
self.list_update_time = datetime.datetime.now()
|
||||||
self.fhdhr.db.set_fhdhr_value("channels", "scanned_time", time.time())
|
self.fhdhr.db.set_fhdhr_value("channels", "scanned_time", time.time())
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
class Channel():
|
class Channel():
|
||||||
@ -15,6 +16,7 @@ class Channel():
|
|||||||
self.channel_id = channel_id
|
self.channel_id = channel_id
|
||||||
self.dict = self.fhdhr.db.get_channel_value(str(channel_id), "dict") or self.default_dict
|
self.dict = self.fhdhr.db.get_channel_value(str(channel_id), "dict") or self.default_dict
|
||||||
self.verify_dict()
|
self.verify_dict()
|
||||||
|
|
||||||
self.fhdhr.db.set_channel_value(self.dict["id"], "dict", self.dict)
|
self.fhdhr.db.set_channel_value(self.dict["id"], "dict", self.dict)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -89,6 +91,13 @@ class Channel():
|
|||||||
channel_info["HD"] = 0
|
channel_info["HD"] = 0
|
||||||
self.dict["HD"] = channel_info["HD"]
|
self.dict["HD"] = channel_info["HD"]
|
||||||
|
|
||||||
|
if "enabled" in list(channel_info.keys()):
|
||||||
|
if "created" not in list(self.dict.keys()):
|
||||||
|
self.dict["enabled"] = channel_info["enabled"]
|
||||||
|
|
||||||
|
if "created" not in list(self.dict.keys()):
|
||||||
|
self.dict["created"] = time.time()
|
||||||
|
|
||||||
self.fhdhr.db.set_channel_value(self.dict["id"], "dict", self.dict)
|
self.fhdhr.db.set_channel_value(self.dict["id"], "dict", self.dict)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import urllib.parse
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
|
||||||
@ -10,14 +9,8 @@ class fHDHR_Cluster():
|
|||||||
self.ssdp = ssdp
|
self.ssdp = ssdp
|
||||||
|
|
||||||
self.friendlyname = self.fhdhr.config.dict["fhdhr"]["friendlyname"]
|
self.friendlyname = self.fhdhr.config.dict["fhdhr"]["friendlyname"]
|
||||||
self.location = None
|
|
||||||
self.location_url = None
|
|
||||||
|
|
||||||
if fhdhr.config.dict["fhdhr"]["discovery_address"]:
|
|
||||||
self.location = ('http://' + fhdhr.config.dict["fhdhr"]["discovery_address"] + ':' +
|
|
||||||
str(fhdhr.config.dict["fhdhr"]["port"]))
|
|
||||||
self.location_url = urllib.parse.quote(self.location)
|
|
||||||
|
|
||||||
|
if self.fhdhr.config.dict["fhdhr"]["discovery_address"]:
|
||||||
self.startup_sync()
|
self.startup_sync()
|
||||||
|
|
||||||
def cluster(self):
|
def cluster(self):
|
||||||
@ -31,7 +24,7 @@ class fHDHR_Cluster():
|
|||||||
"base_url": fhdhr_list[location]["base_url"],
|
"base_url": fhdhr_list[location]["base_url"],
|
||||||
"name": fhdhr_list[location]["name"]
|
"name": fhdhr_list[location]["name"]
|
||||||
}
|
}
|
||||||
if item_dict["base_url"] != self.location:
|
if item_dict["base_url"] != self.fhdhr.api.base:
|
||||||
locations.append(item_dict)
|
locations.append(item_dict)
|
||||||
if len(locations):
|
if len(locations):
|
||||||
locations = sorted(locations, key=lambda i: i['name'])
|
locations = sorted(locations, key=lambda i: i['name'])
|
||||||
@ -43,7 +36,7 @@ class fHDHR_Cluster():
|
|||||||
cluster = self.fhdhr.db.get_fhdhr_value("cluster", "dict") or self.default_cluster()
|
cluster = self.fhdhr.db.get_fhdhr_value("cluster", "dict") or self.default_cluster()
|
||||||
return_dict = {}
|
return_dict = {}
|
||||||
for location in list(cluster.keys()):
|
for location in list(cluster.keys()):
|
||||||
if location != self.location:
|
if location != self.fhdhr.api.base:
|
||||||
return_dict[location] = {
|
return_dict[location] = {
|
||||||
"Joined": True
|
"Joined": True
|
||||||
}
|
}
|
||||||
@ -59,8 +52,8 @@ class fHDHR_Cluster():
|
|||||||
|
|
||||||
def default_cluster(self):
|
def default_cluster(self):
|
||||||
defdict = {}
|
defdict = {}
|
||||||
defdict[self.location] = {
|
defdict[self.fhdhr.api.base] = {
|
||||||
"base_url": self.location,
|
"base_url": self.fhdhr.api.base,
|
||||||
"name": self.friendlyname
|
"name": self.friendlyname
|
||||||
}
|
}
|
||||||
return defdict
|
return defdict
|
||||||
@ -73,13 +66,13 @@ class fHDHR_Cluster():
|
|||||||
else:
|
else:
|
||||||
self.fhdhr.logger.info("Found %s clustered services." % str(len(list(cluster.keys()))))
|
self.fhdhr.logger.info("Found %s clustered services." % str(len(list(cluster.keys()))))
|
||||||
for location in list(cluster.keys()):
|
for location in list(cluster.keys()):
|
||||||
if location != self.location:
|
if location != self.fhdhr.api.base:
|
||||||
self.fhdhr.logger.info("Checking Cluster Syncronization information from %s." % location)
|
self.fhdhr.logger.info("Checking Cluster Syncronization information from %s." % location)
|
||||||
sync_url = location + "/api/cluster?method=get"
|
sync_url = location + "/api/cluster?method=get"
|
||||||
try:
|
try:
|
||||||
sync_open = self.fhdhr.web.session.get(sync_url)
|
sync_open = self.fhdhr.web.session.get(sync_url)
|
||||||
retrieved_cluster = sync_open.json()
|
retrieved_cluster = sync_open.json()
|
||||||
if self.location not in list(retrieved_cluster.keys()):
|
if self.fhdhr.api.base not in list(retrieved_cluster.keys()):
|
||||||
return self.leave()
|
return self.leave()
|
||||||
except self.fhdhr.web.exceptions.ConnectionError:
|
except self.fhdhr.web.exceptions.ConnectionError:
|
||||||
self.fhdhr.logger.error("Unreachable: " + location)
|
self.fhdhr.logger.error("Unreachable: " + location)
|
||||||
@ -91,9 +84,9 @@ class fHDHR_Cluster():
|
|||||||
def disconnect(self):
|
def disconnect(self):
|
||||||
cluster = self.fhdhr.db.get_fhdhr_value("cluster", "dict") or self.default_cluster()
|
cluster = self.fhdhr.db.get_fhdhr_value("cluster", "dict") or self.default_cluster()
|
||||||
for location in list(cluster.keys()):
|
for location in list(cluster.keys()):
|
||||||
if location != self.location:
|
if location != self.fhdhr.api.base:
|
||||||
self.fhdhr.logger.info("Informing %s that I am departing the Cluster." % location)
|
self.fhdhr.logger.info("Informing %s that I am departing the Cluster." % location)
|
||||||
sync_url = location + "/api/cluster?method=del&location=" + self.location
|
sync_url = location + "/api/cluster?method=del&location=" + self.fhdhr.api.base
|
||||||
try:
|
try:
|
||||||
self.fhdhr.web.session.get(sync_url)
|
self.fhdhr.web.session.get(sync_url)
|
||||||
except self.fhdhr.web.exceptions.ConnectionError:
|
except self.fhdhr.web.exceptions.ConnectionError:
|
||||||
@ -111,8 +104,8 @@ class fHDHR_Cluster():
|
|||||||
def push_sync(self):
|
def push_sync(self):
|
||||||
cluster = self.fhdhr.db.get_fhdhr_value("cluster", "dict") or self.default_cluster()
|
cluster = self.fhdhr.db.get_fhdhr_value("cluster", "dict") or self.default_cluster()
|
||||||
for location in list(cluster.keys()):
|
for location in list(cluster.keys()):
|
||||||
if location != self.location:
|
if location != self.fhdhr.api.base:
|
||||||
sync_url = location + "/api/cluster?method=sync&location=" + self.location_url
|
sync_url = location + "/api/cluster?method=sync&location=" + self.fhdhr.api.base_quoted
|
||||||
try:
|
try:
|
||||||
self.fhdhr.web.session.get(sync_url)
|
self.fhdhr.web.session.get(sync_url)
|
||||||
except self.fhdhr.web.exceptions.ConnectionError:
|
except self.fhdhr.web.exceptions.ConnectionError:
|
||||||
|
|||||||
@ -36,12 +36,7 @@ class EPG():
|
|||||||
if epg_method not in list(self.sleeptime.keys()):
|
if epg_method not in list(self.sleeptime.keys()):
|
||||||
self.sleeptime[epg_method] = self.fhdhr.config.dict["epg"]["update_frequency"]
|
self.sleeptime[epg_method] = self.fhdhr.config.dict["epg"]["update_frequency"]
|
||||||
|
|
||||||
if self.fhdhr.config.dict["fhdhr"]["address"] == "0.0.0.0":
|
self.epg_update_url = "%s/api/epg?method=update" % (self.fhdhr.api.base)
|
||||||
self.location = ('http://127.0.0.1:%s' % str(self.fhdhr.config.dict["fhdhr"]["port"]))
|
|
||||||
else:
|
|
||||||
self.location = ('http://%s:%s' % (self.fhdhr.config.dict["fhdhr"]["address"], str(self.fhdhr.config.dict["fhdhr"]["port"])))
|
|
||||||
|
|
||||||
self.epg_update_url = "%s/api/epg?method=update" % (self.location)
|
|
||||||
|
|
||||||
def clear_epg_cache(self, method=None):
|
def clear_epg_cache(self, method=None):
|
||||||
|
|
||||||
|
|||||||
@ -15,79 +15,19 @@ class SSDPServer():
|
|||||||
|
|
||||||
self.detect_method = fHDHR_Detect(fhdhr)
|
self.detect_method = fHDHR_Detect(fhdhr)
|
||||||
|
|
||||||
if (fhdhr.config.dict["fhdhr"]["discovery_address"] and
|
if (self.fhdhr.config.dict["fhdhr"]["discovery_address"] and
|
||||||
fhdhr.config.dict["ssdp"]["enabled"]):
|
self.fhdhr.config.dict["ssdp"]["enabled"]):
|
||||||
|
self.setup_ssdp()
|
||||||
|
|
||||||
self.sock = None
|
self.sock.bind((self.bind_address, 1900))
|
||||||
self.proto = "ipv4"
|
|
||||||
self.port = 1900
|
|
||||||
self.iface = None
|
|
||||||
self.address = None
|
|
||||||
|
|
||||||
allowed_protos = ("ipv4", "ipv6")
|
|
||||||
if self.proto not in allowed_protos:
|
|
||||||
raise ValueError("Invalid proto - expected one of {}".format(allowed_protos))
|
|
||||||
|
|
||||||
self.location = ('http://' + fhdhr.config.dict["fhdhr"]["discovery_address"] + ':' +
|
|
||||||
str(fhdhr.config.dict["fhdhr"]["port"]) + '/device.xml')
|
|
||||||
|
|
||||||
self._iface = None
|
|
||||||
|
|
||||||
if self.proto == "ipv4":
|
|
||||||
self._af_type = socket.AF_INET
|
|
||||||
self._broadcast_ip = "239.255.255.250"
|
|
||||||
self._address = (self._broadcast_ip, self.port)
|
|
||||||
self.bind_address = "0.0.0.0"
|
|
||||||
elif self.proto == "ipv6":
|
|
||||||
self._af_type = socket.AF_INET6
|
|
||||||
self._broadcast_ip = "ff02::c"
|
|
||||||
self._address = (self._broadcast_ip, self.port, 0, 0)
|
|
||||||
self.bind_address = "::"
|
|
||||||
|
|
||||||
self.broadcast_addy = "{}:{}".format(self._broadcast_ip, self.port)
|
|
||||||
|
|
||||||
self.sock = socket.socket(self._af_type, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
|
||||||
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
||||||
|
|
||||||
# Bind to specific interface
|
|
||||||
if self.iface is not None:
|
|
||||||
self.sock.setsockopt(socket.SOL_SOCKET, getattr(socket, "SO_BINDTODEVICE", 25), self.iface)
|
|
||||||
|
|
||||||
# Subscribe to multicast address
|
|
||||||
if self.proto == "ipv4":
|
|
||||||
mreq = socket.inet_aton(self._broadcast_ip)
|
|
||||||
if self.address is not None:
|
|
||||||
mreq += socket.inet_aton(self.address)
|
|
||||||
else:
|
|
||||||
mreq += struct.pack(b"@I", socket.INADDR_ANY)
|
|
||||||
self.sock.setsockopt(
|
|
||||||
socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq,
|
|
||||||
)
|
|
||||||
# Allow multicasts on loopback devices (necessary for testing)
|
|
||||||
self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1)
|
|
||||||
elif self.proto == "ipv6":
|
|
||||||
# In IPv6 we use the interface index, not the address when subscribing to the group
|
|
||||||
mreq = socket.inet_pton(socket.AF_INET6, self._broadcast_ip)
|
|
||||||
if self.iface is not None:
|
|
||||||
iface_index = socket.if_nametoindex(self.iface)
|
|
||||||
# Send outgoing packets from the same interface
|
|
||||||
self.sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, iface_index)
|
|
||||||
mreq += struct.pack(b"@I", iface_index)
|
|
||||||
else:
|
|
||||||
mreq += socket.inet_pton(socket.AF_INET6, "::")
|
|
||||||
self.sock.setsockopt(
|
|
||||||
socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq,
|
|
||||||
)
|
|
||||||
self.sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_LOOP, 1)
|
|
||||||
self.sock.bind((self.bind_address, self.port))
|
|
||||||
|
|
||||||
self.msearch_payload = self.create_msearch_payload()
|
self.msearch_payload = self.create_msearch_payload()
|
||||||
|
|
||||||
self.rmg_ssdp = RMG_SSDP(fhdhr, self._broadcast_ip)
|
self.max_age = int(fhdhr.config.dict["ssdp"]["max_age"])
|
||||||
self.hdhr_ssdp = HDHR_SSDP(fhdhr, self._broadcast_ip)
|
self.age_time = None
|
||||||
|
|
||||||
self.refresh = int(fhdhr.config.dict["ssdp"]["refresh_frequency"])
|
self.rmg_ssdp = RMG_SSDP(fhdhr, self.broadcast_ip, self.max_age)
|
||||||
self.refresh_last = None
|
self.hdhr_ssdp = HDHR_SSDP(fhdhr, self.broadcast_ip, self.max_age)
|
||||||
|
|
||||||
self.do_alive()
|
self.do_alive()
|
||||||
self.m_search()
|
self.m_search()
|
||||||
@ -95,17 +35,17 @@ class SSDPServer():
|
|||||||
def do_alive(self, forcealive=False):
|
def do_alive(self, forcealive=False):
|
||||||
|
|
||||||
send_alive = False
|
send_alive = False
|
||||||
if not self.refresh_last:
|
if not self.age_time:
|
||||||
send_alive = True
|
send_alive = True
|
||||||
elif forcealive:
|
elif forcealive:
|
||||||
send_alive = True
|
send_alive = True
|
||||||
elif time.time() >= (self.refresh_last + self.refresh):
|
elif time.time() >= (self.age_time + self.max_age):
|
||||||
send_alive = True
|
send_alive = True
|
||||||
|
|
||||||
if send_alive:
|
if send_alive:
|
||||||
self.fhdhr.logger.info("Sending Alive message to network.")
|
self.fhdhr.logger.info("Sending Alive message to network.")
|
||||||
self.do_notify(('239.255.255.250', 1900))
|
self.do_notify(self.broadcase_address_tuple)
|
||||||
self.refresh_last = time.time()
|
self.age_time = time.time()
|
||||||
|
|
||||||
def do_notify(self, address):
|
def do_notify(self, address):
|
||||||
|
|
||||||
@ -118,11 +58,11 @@ class SSDPServer():
|
|||||||
rmg_notify = self.rmg_ssdp.get()
|
rmg_notify = self.rmg_ssdp.get()
|
||||||
notify_list.append(rmg_notify)
|
notify_list.append(rmg_notify)
|
||||||
|
|
||||||
for notify in notify_list:
|
for notifydata in notify_list:
|
||||||
|
|
||||||
self.fhdhr.logger.debug("Created {}".format(notify))
|
self.fhdhr.logger.debug("Created {}".format(notifydata))
|
||||||
try:
|
try:
|
||||||
self.sock.sendto(notify, address)
|
self.sock.sendto(notifydata, address)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
# Most commonly: We received a multicast from an IP not in our subnet
|
# Most commonly: We received a multicast from an IP not in our subnet
|
||||||
self.fhdhr.logger.debug("Unable to send NOTIFY: %s" % e)
|
self.fhdhr.logger.debug("Unable to send NOTIFY: %s" % e)
|
||||||
@ -157,12 +97,12 @@ class SSDPServer():
|
|||||||
self.fhdhr.logger.debug("NOTIFY data: {}".format(headers))
|
self.fhdhr.logger.debug("NOTIFY data: {}".format(headers))
|
||||||
try:
|
try:
|
||||||
if headers["server"].startswith("fHDHR"):
|
if headers["server"].startswith("fHDHR"):
|
||||||
if headers["location"] != self.location:
|
|
||||||
savelocation = headers["location"].split("/device.xml")[0]
|
savelocation = headers["location"].split("/device.xml")[0]
|
||||||
if savelocation.endswith("/hdhr"):
|
if savelocation.endswith("/hdhr"):
|
||||||
savelocation = savelocation.replace("/hdhr", '')
|
savelocation = savelocation.replace("/hdhr", '')
|
||||||
elif savelocation.endswith("/rmg"):
|
elif savelocation.endswith("/rmg"):
|
||||||
savelocation = savelocation.replace("/rmg", '')
|
savelocation = savelocation.replace("/rmg", '')
|
||||||
|
if savelocation != self.fhdhr.api.base:
|
||||||
self.detect_method.set(savelocation)
|
self.detect_method.set(savelocation)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
@ -171,21 +111,25 @@ class SSDPServer():
|
|||||||
|
|
||||||
def m_search(self):
|
def m_search(self):
|
||||||
data = self.msearch_payload
|
data = self.msearch_payload
|
||||||
self.sock.sendto(data, self._address)
|
self.sock.sendto(data, self.broadcase_address_tuple)
|
||||||
|
|
||||||
def create_msearch_payload(self):
|
def create_msearch_payload(self):
|
||||||
data = (
|
|
||||||
"M-SEARCH * HTTP/1.1\r\n"
|
data = ''
|
||||||
"HOST:{}\r\n"
|
data_command = "M-SEARCH * HTTP/1.1"
|
||||||
'MAN: "ssdp:discover"\r\n'
|
|
||||||
"ST:{}\r\n"
|
data_dict = {
|
||||||
"MX:{}\r\n"
|
"HOST": "%s:%s" % (self.broadcast_ip, 1900),
|
||||||
).format(
|
"MAN": "ssdp:discover",
|
||||||
self.broadcast_addy,
|
"ST": "ssdp:all",
|
||||||
"ssdp:all",
|
"MX": 1,
|
||||||
1
|
}
|
||||||
)
|
|
||||||
|
data += "%s\r\n" % data_command
|
||||||
|
for data_key in list(data_dict.keys()):
|
||||||
|
data += "%s:%s\r\n" % (data_key, data_dict[data_key])
|
||||||
data += "\r\n"
|
data += "\r\n"
|
||||||
|
|
||||||
return data.encode("utf-8")
|
return data.encode("utf-8")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@ -196,3 +140,69 @@ class SSDPServer():
|
|||||||
self.do_alive()
|
self.do_alive()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
self.sock.close()
|
self.sock.close()
|
||||||
|
|
||||||
|
def setup_ssdp(self):
|
||||||
|
self.sock = None
|
||||||
|
|
||||||
|
self.proto = self.setup_proto()
|
||||||
|
self.iface = self.fhdhr.config.dict["ssdp"]["iface"]
|
||||||
|
self.address = self.fhdhr.config.dict["ssdp"]["multicast_address"]
|
||||||
|
self.setup_addressing()
|
||||||
|
|
||||||
|
self.sock = socket.socket(self.af_type, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
||||||
|
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
|
||||||
|
self.setup_interface()
|
||||||
|
|
||||||
|
self.setup_multicasting()
|
||||||
|
|
||||||
|
def setup_proto(self):
|
||||||
|
proto = self.fhdhr.config.dict["ssdp"]["proto"]
|
||||||
|
allowed_protos = ("ipv4", "ipv6")
|
||||||
|
if proto not in allowed_protos:
|
||||||
|
raise ValueError("Invalid proto - expected one of {}".format(allowed_protos))
|
||||||
|
return proto
|
||||||
|
|
||||||
|
def setup_addressing(self):
|
||||||
|
if self.proto == "ipv4":
|
||||||
|
self.af_type = socket.AF_INET
|
||||||
|
self.broadcast_ip = "239.255.255.250"
|
||||||
|
self.broadcase_address_tuple = (self.broadcast_ip, 1900)
|
||||||
|
self.bind_address = "0.0.0.0"
|
||||||
|
elif self.proto == "ipv6":
|
||||||
|
self.af_type = socket.AF_INET6
|
||||||
|
self.broadcast_ip = "ff02::c"
|
||||||
|
self.broadcast_address_tuple = (self.broadcast_ip, 1900, 0, 0)
|
||||||
|
self.bind_address = "::"
|
||||||
|
|
||||||
|
def setup_interface(self):
|
||||||
|
# Bind to specific interface
|
||||||
|
if self.iface is not None:
|
||||||
|
self.sock.setsockopt(socket.SOL_SOCKET, getattr(socket, "SO_BINDTODEVICE", 25), self.iface)
|
||||||
|
|
||||||
|
def setup_multicasting(self):
|
||||||
|
# Subscribe to multicast address
|
||||||
|
if self.proto == "ipv4":
|
||||||
|
mreq = socket.inet_aton(self.broadcast_ip)
|
||||||
|
if self.address is not None:
|
||||||
|
mreq += socket.inet_aton(self.address)
|
||||||
|
else:
|
||||||
|
mreq += struct.pack(b"@I", socket.INADDR_ANY)
|
||||||
|
self.sock.setsockopt(
|
||||||
|
socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
|
||||||
|
# Allow multicasts on loopback devices (necessary for testing)
|
||||||
|
self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1)
|
||||||
|
elif self.proto == "ipv6":
|
||||||
|
# In IPv6 we use the interface index, not the address when subscribing to the group
|
||||||
|
mreq = socket.inet_pton(socket.AF_INET6, self.broadcast_ip)
|
||||||
|
if self.iface is not None:
|
||||||
|
iface_index = socket.if_nametoindex(self.iface)
|
||||||
|
# Send outgoing packets from the same interface
|
||||||
|
self.sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, iface_index)
|
||||||
|
mreq += struct.pack(b"@I", iface_index)
|
||||||
|
else:
|
||||||
|
mreq += socket.inet_pton(socket.AF_INET6, "::")
|
||||||
|
self.sock.setsockopt(
|
||||||
|
socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq,
|
||||||
|
)
|
||||||
|
self.sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_LOOP, 1)
|
||||||
|
|||||||
@ -2,43 +2,38 @@
|
|||||||
|
|
||||||
class HDHR_SSDP():
|
class HDHR_SSDP():
|
||||||
|
|
||||||
def __init__(self, fhdhr, _broadcast_ip):
|
def __init__(self, fhdhr, broadcast_ip, max_age):
|
||||||
self.fhdhr = fhdhr
|
self.fhdhr = fhdhr
|
||||||
|
|
||||||
self.ssdp_content = None
|
self.ssdp_content = None
|
||||||
|
|
||||||
self._broadcast_ip = _broadcast_ip
|
self.broadcast_ip = broadcast_ip
|
||||||
self.nt = 'urn:schemas-upnp-org:device:MediaServer:1'
|
self.device_xml_path = '/device.xml'
|
||||||
self.usn = 'uuid:' + fhdhr.config.dict["main"]["uuid"] + '::' + self.nt
|
|
||||||
self.server = 'fHDHR/%s UPnP/1.0' % fhdhr.version
|
self.max_age = max_age
|
||||||
self.location = ('http://' + fhdhr.config.dict["fhdhr"]["discovery_address"] + ':' +
|
|
||||||
str(fhdhr.config.dict["fhdhr"]["port"]) + '/device.xml')
|
|
||||||
self.al = self.location
|
|
||||||
self.max_age = 1800
|
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
if self.ssdp_content:
|
if self.ssdp_content:
|
||||||
return self.ssdp_content.encode("utf-8")
|
return self.ssdp_content.encode("utf-8")
|
||||||
|
|
||||||
data = (
|
data = ''
|
||||||
"NOTIFY * HTTP/1.1\r\n"
|
data_command = "NOTIFY * HTTP/1.1"
|
||||||
"HOST:{}\r\n"
|
|
||||||
"NT:{}\r\n"
|
data_dict = {
|
||||||
"NTS:ssdp:alive\r\n"
|
"HOST": "%s:%s" % (self.broadcast_ip, 1900),
|
||||||
"USN:{}\r\n"
|
"NT": 'urn:schemas-upnp-org:device:MediaServer:1',
|
||||||
"SERVER:{}\r\n"
|
"NTS": "ssdp:alive",
|
||||||
).format(
|
"USN": 'uuid:%s::%s' % (self.fhdhr.config.dict["main"]["uuid"], 'urn:schemas-upnp-org:device:MediaServer:1'),
|
||||||
self._broadcast_ip,
|
"SERVER": 'fHDHR/%s UPnP/1.0' % self.fhdhr.version,
|
||||||
self.nt,
|
"LOCATION": "%s%s" % (self.fhdhr.api.base, self.device_xml_path),
|
||||||
self.usn,
|
"AL": "%s%s" % (self.fhdhr.api.base, self.device_xml_path),
|
||||||
self.server
|
"Cache-Control:max-age=": self.max_age
|
||||||
)
|
}
|
||||||
if self.location is not None:
|
|
||||||
data += "LOCATION:{}\r\n".format(self.location)
|
data += "%s\r\n" % data_command
|
||||||
if self.al is not None:
|
for data_key in list(data_dict.keys()):
|
||||||
data += "AL:{}\r\n".format(self.al)
|
data += "%s:%s\r\n" % (data_key, data_dict[data_key])
|
||||||
if self.max_age is not None:
|
|
||||||
data += "Cache-Control:max-age={}\r\n".format(self.max_age)
|
|
||||||
data += "\r\n"
|
data += "\r\n"
|
||||||
|
|
||||||
self.ssdp_content = data
|
self.ssdp_content = data
|
||||||
return data.encode("utf-8")
|
return data.encode("utf-8")
|
||||||
|
|||||||
@ -2,43 +2,38 @@
|
|||||||
|
|
||||||
class RMG_SSDP():
|
class RMG_SSDP():
|
||||||
|
|
||||||
def __init__(self, fhdhr, _broadcast_ip):
|
def __init__(self, fhdhr, broadcast_ip, max_age):
|
||||||
self.fhdhr = fhdhr
|
self.fhdhr = fhdhr
|
||||||
|
|
||||||
self.ssdp_content = None
|
self.ssdp_content = None
|
||||||
|
|
||||||
self._broadcast_ip = _broadcast_ip
|
self.broadcast_ip = broadcast_ip
|
||||||
self.nt = 'urn:schemas-upnp-org:device-1-0'
|
self.device_xml_path = '/device.xml'
|
||||||
self.usn = 'uuid:' + fhdhr.config.dict["main"]["uuid"] + '::' + self.nt
|
|
||||||
self.server = 'fHDHR/%s UPnP/1.0' % fhdhr.version
|
self.max_age = max_age
|
||||||
self.location = ('http://' + fhdhr.config.dict["fhdhr"]["discovery_address"] + ':' +
|
|
||||||
str(fhdhr.config.dict["fhdhr"]["port"]) + '/device.xml')
|
|
||||||
self.al = self.location
|
|
||||||
self.max_age = 1800
|
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
if self.ssdp_content:
|
if self.ssdp_content:
|
||||||
return self.ssdp_content.encode("utf-8")
|
return self.ssdp_content.encode("utf-8")
|
||||||
|
|
||||||
data = (
|
data = ''
|
||||||
"NOTIFY * HTTP/1.1\r\n"
|
data_command = "NOTIFY * HTTP/1.1"
|
||||||
"HOST:{}\r\n"
|
|
||||||
"NT:{}\r\n"
|
data_dict = {
|
||||||
"NTS:ssdp:alive\r\n"
|
"HOST": "%s:%s" % (self.broadcast_ip, 1900),
|
||||||
"USN:{}\r\n"
|
"NT": 'urn:schemas-upnp-org:device-1-0',
|
||||||
"SERVER:{}\r\n"
|
"NTS": "ssdp:alive",
|
||||||
).format(
|
"USN": 'uuid:%s::%s' % (self.fhdhr.config.dict["main"]["uuid"], 'urn:schemas-upnp-org:device-1-0'),
|
||||||
self._broadcast_ip,
|
"SERVER": 'fHDHR/%s UPnP/1.0' % self.fhdhr.version,
|
||||||
self.nt,
|
"LOCATION": "%s%s" % (self.fhdhr.api.base, self.device_xml_path),
|
||||||
self.usn,
|
"AL": "%s%s" % (self.fhdhr.api.base, self.device_xml_path),
|
||||||
self.server
|
"Cache-Control:max-age=": self.max_age
|
||||||
)
|
}
|
||||||
if self.location is not None:
|
|
||||||
data += "LOCATION:{}\r\n".format(self.location)
|
data += "%s\r\n" % data_command
|
||||||
if self.al is not None:
|
for data_key in list(data_dict.keys()):
|
||||||
data += "AL:{}\r\n".format(self.al)
|
data += "%s:%s\r\n" % (data_key, data_dict[data_key])
|
||||||
if self.max_age is not None:
|
|
||||||
data += "Cache-Control:max-age={}\r\n".format(self.max_age)
|
|
||||||
data += "\r\n"
|
data += "\r\n"
|
||||||
|
|
||||||
self.ssdp_content = data
|
self.ssdp_content = data
|
||||||
return data.encode("utf-8")
|
return data.encode("utf-8")
|
||||||
|
|||||||
@ -18,13 +18,8 @@ class Tuner():
|
|||||||
self.tuner_lock = threading.Lock()
|
self.tuner_lock = threading.Lock()
|
||||||
self.set_off_status()
|
self.set_off_status()
|
||||||
|
|
||||||
if fhdhr.config.dict["fhdhr"]["address"] == "0.0.0.0":
|
self.chanscan_url = "%s/api/channels?method=scan" % (self.fhdhr.api.base)
|
||||||
self.location = ('http://127.0.0.1:%s' % str(fhdhr.config.dict["fhdhr"]["port"]))
|
self.close_url = "%s/api/tuners?method=close&tuner=%s" % (self.fhdhr.api.base, str(self.number))
|
||||||
else:
|
|
||||||
self.location = ('http://%s:%s' % (fhdhr.config.dict["fhdhr"]["address"], str(fhdhr.config.dict["fhdhr"]["port"])))
|
|
||||||
|
|
||||||
self.chanscan_url = "%s/api/channels?method=scan" % (self.location)
|
|
||||||
self.close_url = "%s/api/tuners?method=close&tuner=%s" % (self.location, str(self.number))
|
|
||||||
|
|
||||||
def channel_scan(self):
|
def channel_scan(self):
|
||||||
if self.tuner_lock.locked():
|
if self.tuner_lock.locked():
|
||||||
|
|||||||
@ -8,6 +8,9 @@ from .rmg import fHDHR_RMG
|
|||||||
from .api import fHDHR_API
|
from .api import fHDHR_API
|
||||||
|
|
||||||
|
|
||||||
|
fHDHR_web_VERSION = "v0.4.0-beta"
|
||||||
|
|
||||||
|
|
||||||
class fHDHR_HTTP_Server():
|
class fHDHR_HTTP_Server():
|
||||||
app = None
|
app = None
|
||||||
|
|
||||||
@ -86,10 +89,11 @@ class fHDHR_HTTP_Server():
|
|||||||
self.app.add_url_rule(endpoint, endpoint_name, handler, methods=methods)
|
self.app.add_url_rule(endpoint, endpoint_name, handler, methods=methods)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.http = WSGIServer((
|
|
||||||
self.fhdhr.config.dict["fhdhr"]["address"],
|
self.http = WSGIServer(self.fhdhr.api.address_tuple,
|
||||||
int(self.fhdhr.config.dict["fhdhr"]["port"])
|
self.app.wsgi_app,
|
||||||
), self.app.wsgi_app, log=self.fhdhr.logger)
|
log=self.fhdhr.logger)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.http.serve_forever()
|
self.http.serve_forever()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
@ -10,9 +10,9 @@ class Cluster_HTML():
|
|||||||
self.fhdhr = fhdhr
|
self.fhdhr = fhdhr
|
||||||
self.location_dict = {
|
self.location_dict = {
|
||||||
"name": self.fhdhr.config.dict["fhdhr"]["friendlyname"],
|
"name": self.fhdhr.config.dict["fhdhr"]["friendlyname"],
|
||||||
"location": self.fhdhr.device.cluster.location,
|
"location": self.fhdhr.api.base,
|
||||||
"joined": "N/A",
|
"joined": "N/A",
|
||||||
"url_query": self.fhdhr.device.cluster.location_url
|
"url_query": self.fhdhr.api.base_quoted
|
||||||
}
|
}
|
||||||
|
|
||||||
def __call__(self, *args):
|
def __call__(self, *args):
|
||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
3
main.py
3
main.py
@ -9,6 +9,7 @@ import pathlib
|
|||||||
from multiprocessing import freeze_support
|
from multiprocessing import freeze_support
|
||||||
|
|
||||||
from fHDHR.cli import run
|
from fHDHR.cli import run
|
||||||
|
import fHDHR_web
|
||||||
import alternative_epg
|
import alternative_epg
|
||||||
import origin
|
import origin
|
||||||
|
|
||||||
@ -16,4 +17,4 @@ SCRIPT_DIR = pathlib.Path(os.path.dirname(os.path.abspath(__file__)))
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
freeze_support()
|
freeze_support()
|
||||||
sys.exit(run.main(SCRIPT_DIR, alternative_epg, origin))
|
sys.exit(run.main(SCRIPT_DIR, fHDHR_web, origin, alternative_epg))
|
||||||
|
|||||||
@ -2,3 +2,6 @@
|
|||||||
from .origin_service import *
|
from .origin_service import *
|
||||||
from .origin_channels import *
|
from .origin_channels import *
|
||||||
from .origin_epg import *
|
from .origin_epg import *
|
||||||
|
|
||||||
|
ORIGIN_NAME = "fHDHR_NextPVR"
|
||||||
|
ORIGIN_VERSION = "v0.5.0-beta"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user