1
0
mirror of https://github.com/fHDHR/fHDHR_NextPVR.git synced 2025-12-06 13:26:57 -05:00

Merge pull request #81 from deathbybandaid/dev

Dev
This commit is contained in:
Deathbybandaid 2020-12-08 13:26:33 -05:00 committed by GitHub
commit bf312bc009
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
78 changed files with 283 additions and 208 deletions

View File

@ -5,10 +5,25 @@
"config_file": true,
"config_web": false
},
"refresh_frequency":{
"max_age":{
"value": 1800,
"config_file": true,
"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
}
}
}

View File

@ -2,10 +2,11 @@
from .originwrapper import OriginServiceWrapper
from .device import fHDHR_Device
from .api import fHDHR_API_URLs
import fHDHR.tools
fHDHR_VERSION = "v0.4.5-beta"
fHDHR_VERSION = "v0.4.6-beta"
class fHDHR_INT_OBJ():
@ -18,10 +19,12 @@ class fHDHR_INT_OBJ():
self.web = fHDHR.tools.WebReq()
self.api = fHDHR_API_URLs(settings)
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.originwrapper = OriginServiceWrapper(self.fhdhr, origin)

36
fHDHR/api/__init__.py Normal file
View 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))

View File

@ -9,7 +9,6 @@ import platform
from fHDHR import fHDHR_VERSION, fHDHR_OBJ
import fHDHR.exceptions
import fHDHR.config
from fHDHR.http import fHDHR_HTTP_Server
from fHDHR.db import fHDHRdb
ERR_CODE = 1
@ -32,16 +31,16 @@ def build_args_parser():
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):
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)
fhdhrweb = fHDHR_HTTP_Server(fhdhr)
fhdhr = fHDHR_OBJ(settings, logger, db, origin, alternative_epg)
fhdhrweb = fHDHR_web.fHDHR_HTTP_Server(fhdhr)
try:
@ -81,11 +80,11 @@ def run(settings, logger, db, alternative_epg, origin):
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"""
try:
settings = get_configuration(args, script_dir)
settings = get_configuration(args, script_dir, origin, fHDHR_web)
except fHDHR.exceptions.ConfigurationError as e:
print(e)
return ERR_CODE_NO_RESTART
@ -94,17 +93,19 @@ def start(args, script_dir, alternative_epg, origin):
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"""
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:
args = build_args_parser()
return start(args, script_dir, alternative_epg, origin)
return start(args, script_dir, fHDHR_web, origin, alternative_epg)
except KeyboardInterrupt:
print("\n\nInterrupted")
return ERR_CODE

View File

@ -15,7 +15,10 @@ from fHDHR.tools import isint, isfloat, is_arithmetic, is_docker
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.conf_default = {}
self.dict = {}
@ -27,7 +30,8 @@ class Config():
def initial_load(self, script_dir):
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"] = {
"script_dir": script_dir,
@ -37,7 +41,7 @@ class Config():
"cache_dir": pathlib.Path(data_dir).joinpath('cache'),
"internal_config": pathlib.Path(data_dir).joinpath('internal_config'),
"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'),
}
@ -64,6 +68,10 @@ class Config():
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
opersystem = platform.system()

View File

@ -71,22 +71,34 @@ class Channels():
if updatelist:
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.")
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:
chan_existing = False
if str(channel_info["id"]) in channel_origin_id_list:
chan_existing = True
channel_obj = self.get_channel_obj("origin_id", channel_info["id"])
else:
channel_obj = Channel(self.fhdhr, self.id_system, origin_id=channel_info["id"])
channel_id = channel_obj.dict["id"]
channel_obj.basics(channel_info)
if not chan_existing:
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.fhdhr.db.set_fhdhr_value("channels", "scanned_time", time.time())

View File

@ -1,3 +1,4 @@
import time
class Channel():
@ -15,6 +16,7 @@ class Channel():
self.channel_id = channel_id
self.dict = self.fhdhr.db.get_channel_value(str(channel_id), "dict") or self.default_dict
self.verify_dict()
self.fhdhr.db.set_channel_value(self.dict["id"], "dict", self.dict)
@property
@ -89,6 +91,13 @@ class Channel():
channel_info["HD"] = 0
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)
@property

View File

@ -1,4 +1,3 @@
import urllib.parse
from collections import OrderedDict
@ -10,14 +9,8 @@ class fHDHR_Cluster():
self.ssdp = ssdp
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()
def cluster(self):
@ -31,7 +24,7 @@ class fHDHR_Cluster():
"base_url": fhdhr_list[location]["base_url"],
"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)
if len(locations):
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()
return_dict = {}
for location in list(cluster.keys()):
if location != self.location:
if location != self.fhdhr.api.base:
return_dict[location] = {
"Joined": True
}
@ -59,8 +52,8 @@ class fHDHR_Cluster():
def default_cluster(self):
defdict = {}
defdict[self.location] = {
"base_url": self.location,
defdict[self.fhdhr.api.base] = {
"base_url": self.fhdhr.api.base,
"name": self.friendlyname
}
return defdict
@ -73,13 +66,13 @@ class fHDHR_Cluster():
else:
self.fhdhr.logger.info("Found %s clustered services." % str(len(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)
sync_url = location + "/api/cluster?method=get"
try:
sync_open = self.fhdhr.web.session.get(sync_url)
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()
except self.fhdhr.web.exceptions.ConnectionError:
self.fhdhr.logger.error("Unreachable: " + location)
@ -91,9 +84,9 @@ class fHDHR_Cluster():
def disconnect(self):
cluster = self.fhdhr.db.get_fhdhr_value("cluster", "dict") or self.default_cluster()
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)
sync_url = location + "/api/cluster?method=del&location=" + self.location
sync_url = location + "/api/cluster?method=del&location=" + self.fhdhr.api.base
try:
self.fhdhr.web.session.get(sync_url)
except self.fhdhr.web.exceptions.ConnectionError:
@ -111,8 +104,8 @@ class fHDHR_Cluster():
def push_sync(self):
cluster = self.fhdhr.db.get_fhdhr_value("cluster", "dict") or self.default_cluster()
for location in list(cluster.keys()):
if location != self.location:
sync_url = location + "/api/cluster?method=sync&location=" + self.location_url
if location != self.fhdhr.api.base:
sync_url = location + "/api/cluster?method=sync&location=" + self.fhdhr.api.base_quoted
try:
self.fhdhr.web.session.get(sync_url)
except self.fhdhr.web.exceptions.ConnectionError:

View File

@ -36,12 +36,7 @@ class EPG():
if epg_method not in list(self.sleeptime.keys()):
self.sleeptime[epg_method] = self.fhdhr.config.dict["epg"]["update_frequency"]
if self.fhdhr.config.dict["fhdhr"]["address"] == "0.0.0.0":
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)
self.epg_update_url = "%s/api/epg?method=update" % (self.fhdhr.api.base)
def clear_epg_cache(self, method=None):

View File

@ -15,79 +15,19 @@ class SSDPServer():
self.detect_method = fHDHR_Detect(fhdhr)
if (fhdhr.config.dict["fhdhr"]["discovery_address"] and
fhdhr.config.dict["ssdp"]["enabled"]):
if (self.fhdhr.config.dict["fhdhr"]["discovery_address"] and
self.fhdhr.config.dict["ssdp"]["enabled"]):
self.setup_ssdp()
self.sock = None
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.sock.bind((self.bind_address, 1900))
self.msearch_payload = self.create_msearch_payload()
self.rmg_ssdp = RMG_SSDP(fhdhr, self._broadcast_ip)
self.hdhr_ssdp = HDHR_SSDP(fhdhr, self._broadcast_ip)
self.max_age = int(fhdhr.config.dict["ssdp"]["max_age"])
self.age_time = None
self.refresh = int(fhdhr.config.dict["ssdp"]["refresh_frequency"])
self.refresh_last = None
self.rmg_ssdp = RMG_SSDP(fhdhr, self.broadcast_ip, self.max_age)
self.hdhr_ssdp = HDHR_SSDP(fhdhr, self.broadcast_ip, self.max_age)
self.do_alive()
self.m_search()
@ -95,17 +35,17 @@ class SSDPServer():
def do_alive(self, forcealive=False):
send_alive = False
if not self.refresh_last:
if not self.age_time:
send_alive = True
elif forcealive:
send_alive = True
elif time.time() >= (self.refresh_last + self.refresh):
elif time.time() >= (self.age_time + self.max_age):
send_alive = True
if send_alive:
self.fhdhr.logger.info("Sending Alive message to network.")
self.do_notify(('239.255.255.250', 1900))
self.refresh_last = time.time()
self.do_notify(self.broadcase_address_tuple)
self.age_time = time.time()
def do_notify(self, address):
@ -118,11 +58,11 @@ class SSDPServer():
rmg_notify = self.rmg_ssdp.get()
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:
self.sock.sendto(notify, address)
self.sock.sendto(notifydata, address)
except OSError as e:
# Most commonly: We received a multicast from an IP not in our subnet
self.fhdhr.logger.debug("Unable to send NOTIFY: %s" % e)
@ -157,12 +97,12 @@ class SSDPServer():
self.fhdhr.logger.debug("NOTIFY data: {}".format(headers))
try:
if headers["server"].startswith("fHDHR"):
if headers["location"] != self.location:
savelocation = headers["location"].split("/device.xml")[0]
if savelocation.endswith("/hdhr"):
savelocation = savelocation.replace("/hdhr", '')
elif savelocation.endswith("/rmg"):
savelocation = savelocation.replace("/rmg", '')
if savelocation != self.fhdhr.api.base:
self.detect_method.set(savelocation)
except KeyError:
return
@ -171,21 +111,25 @@ class SSDPServer():
def m_search(self):
data = self.msearch_payload
self.sock.sendto(data, self._address)
self.sock.sendto(data, self.broadcase_address_tuple)
def create_msearch_payload(self):
data = (
"M-SEARCH * HTTP/1.1\r\n"
"HOST:{}\r\n"
'MAN: "ssdp:discover"\r\n'
"ST:{}\r\n"
"MX:{}\r\n"
).format(
self.broadcast_addy,
"ssdp:all",
1
)
data = ''
data_command = "M-SEARCH * HTTP/1.1"
data_dict = {
"HOST": "%s:%s" % (self.broadcast_ip, 1900),
"MAN": "ssdp:discover",
"ST": "ssdp:all",
"MX": 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"
return data.encode("utf-8")
def run(self):
@ -196,3 +140,69 @@ class SSDPServer():
self.do_alive()
except KeyboardInterrupt:
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)

View File

@ -2,43 +2,38 @@
class HDHR_SSDP():
def __init__(self, fhdhr, _broadcast_ip):
def __init__(self, fhdhr, broadcast_ip, max_age):
self.fhdhr = fhdhr
self.ssdp_content = None
self._broadcast_ip = _broadcast_ip
self.nt = 'urn:schemas-upnp-org:device:MediaServer:1'
self.usn = 'uuid:' + fhdhr.config.dict["main"]["uuid"] + '::' + self.nt
self.server = 'fHDHR/%s UPnP/1.0' % fhdhr.version
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
self.broadcast_ip = broadcast_ip
self.device_xml_path = '/device.xml'
self.max_age = max_age
def get(self):
if self.ssdp_content:
return self.ssdp_content.encode("utf-8")
data = (
"NOTIFY * HTTP/1.1\r\n"
"HOST:{}\r\n"
"NT:{}\r\n"
"NTS:ssdp:alive\r\n"
"USN:{}\r\n"
"SERVER:{}\r\n"
).format(
self._broadcast_ip,
self.nt,
self.usn,
self.server
)
if self.location is not None:
data += "LOCATION:{}\r\n".format(self.location)
if self.al is not None:
data += "AL:{}\r\n".format(self.al)
if self.max_age is not None:
data += "Cache-Control:max-age={}\r\n".format(self.max_age)
data = ''
data_command = "NOTIFY * HTTP/1.1"
data_dict = {
"HOST": "%s:%s" % (self.broadcast_ip, 1900),
"NT": 'urn:schemas-upnp-org:device:MediaServer:1',
"NTS": "ssdp:alive",
"USN": 'uuid:%s::%s' % (self.fhdhr.config.dict["main"]["uuid"], 'urn:schemas-upnp-org:device:MediaServer:1'),
"SERVER": 'fHDHR/%s UPnP/1.0' % self.fhdhr.version,
"LOCATION": "%s%s" % (self.fhdhr.api.base, self.device_xml_path),
"AL": "%s%s" % (self.fhdhr.api.base, self.device_xml_path),
"Cache-Control:max-age=": self.max_age
}
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"
self.ssdp_content = data
return data.encode("utf-8")

View File

@ -2,43 +2,38 @@
class RMG_SSDP():
def __init__(self, fhdhr, _broadcast_ip):
def __init__(self, fhdhr, broadcast_ip, max_age):
self.fhdhr = fhdhr
self.ssdp_content = None
self._broadcast_ip = _broadcast_ip
self.nt = 'urn:schemas-upnp-org:device-1-0'
self.usn = 'uuid:' + fhdhr.config.dict["main"]["uuid"] + '::' + self.nt
self.server = 'fHDHR/%s UPnP/1.0' % fhdhr.version
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
self.broadcast_ip = broadcast_ip
self.device_xml_path = '/device.xml'
self.max_age = max_age
def get(self):
if self.ssdp_content:
return self.ssdp_content.encode("utf-8")
data = (
"NOTIFY * HTTP/1.1\r\n"
"HOST:{}\r\n"
"NT:{}\r\n"
"NTS:ssdp:alive\r\n"
"USN:{}\r\n"
"SERVER:{}\r\n"
).format(
self._broadcast_ip,
self.nt,
self.usn,
self.server
)
if self.location is not None:
data += "LOCATION:{}\r\n".format(self.location)
if self.al is not None:
data += "AL:{}\r\n".format(self.al)
if self.max_age is not None:
data += "Cache-Control:max-age={}\r\n".format(self.max_age)
data = ''
data_command = "NOTIFY * HTTP/1.1"
data_dict = {
"HOST": "%s:%s" % (self.broadcast_ip, 1900),
"NT": 'urn:schemas-upnp-org:device-1-0',
"NTS": "ssdp:alive",
"USN": 'uuid:%s::%s' % (self.fhdhr.config.dict["main"]["uuid"], 'urn:schemas-upnp-org:device-1-0'),
"SERVER": 'fHDHR/%s UPnP/1.0' % self.fhdhr.version,
"LOCATION": "%s%s" % (self.fhdhr.api.base, self.device_xml_path),
"AL": "%s%s" % (self.fhdhr.api.base, self.device_xml_path),
"Cache-Control:max-age=": self.max_age
}
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"
self.ssdp_content = data
return data.encode("utf-8")

View File

@ -18,13 +18,8 @@ class Tuner():
self.tuner_lock = threading.Lock()
self.set_off_status()
if fhdhr.config.dict["fhdhr"]["address"] == "0.0.0.0":
self.location = ('http://127.0.0.1:%s' % str(fhdhr.config.dict["fhdhr"]["port"]))
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))
self.chanscan_url = "%s/api/channels?method=scan" % (self.fhdhr.api.base)
self.close_url = "%s/api/tuners?method=close&tuner=%s" % (self.fhdhr.api.base, str(self.number))
def channel_scan(self):
if self.tuner_lock.locked():

View File

@ -8,6 +8,9 @@ from .rmg import fHDHR_RMG
from .api import fHDHR_API
fHDHR_web_VERSION = "v0.4.0-beta"
class fHDHR_HTTP_Server():
app = None
@ -86,10 +89,11 @@ class fHDHR_HTTP_Server():
self.app.add_url_rule(endpoint, endpoint_name, handler, methods=methods)
def run(self):
self.http = WSGIServer((
self.fhdhr.config.dict["fhdhr"]["address"],
int(self.fhdhr.config.dict["fhdhr"]["port"])
), self.app.wsgi_app, log=self.fhdhr.logger)
self.http = WSGIServer(self.fhdhr.api.address_tuple,
self.app.wsgi_app,
log=self.fhdhr.logger)
try:
self.http.serve_forever()
except KeyboardInterrupt:

View File

@ -10,9 +10,9 @@ class Cluster_HTML():
self.fhdhr = fhdhr
self.location_dict = {
"name": self.fhdhr.config.dict["fhdhr"]["friendlyname"],
"location": self.fhdhr.device.cluster.location,
"location": self.fhdhr.api.base,
"joined": "N/A",
"url_query": self.fhdhr.device.cluster.location_url
"url_query": self.fhdhr.api.base_quoted
}
def __call__(self, *args):

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -9,6 +9,7 @@ import pathlib
from multiprocessing import freeze_support
from fHDHR.cli import run
import fHDHR_web
import alternative_epg
import origin
@ -16,4 +17,4 @@ SCRIPT_DIR = pathlib.Path(os.path.dirname(os.path.abspath(__file__)))
if __name__ == '__main__':
freeze_support()
sys.exit(run.main(SCRIPT_DIR, alternative_epg, origin))
sys.exit(run.main(SCRIPT_DIR, fHDHR_web, origin, alternative_epg))

View File

@ -2,3 +2,6 @@
from .origin_service import *
from .origin_channels import *
from .origin_epg import *
ORIGIN_NAME = "fHDHR_NextPVR"
ORIGIN_VERSION = "v0.5.0-beta"