mirror of
https://github.com/fHDHR/fHDHR_NextPVR.git
synced 2025-12-06 11:07:01 -05:00
Add Restart Button to Web Interface
This commit is contained in:
parent
d87ef97494
commit
602e74f565
@ -21,6 +21,8 @@ class fHDHR_INT_OBJ():
|
|||||||
|
|
||||||
self.api = fHDHR_API_URLs(settings, self.web)
|
self.api = fHDHR_API_URLs(settings, self.web)
|
||||||
|
|
||||||
|
self.threads = {}
|
||||||
|
|
||||||
|
|
||||||
class fHDHR_OBJ():
|
class fHDHR_OBJ():
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
import time
|
|
||||||
import threading
|
|
||||||
|
|
||||||
from fHDHR import fHDHR_VERSION, fHDHR_OBJ
|
from fHDHR import fHDHR_VERSION, fHDHR_OBJ
|
||||||
import fHDHR.exceptions
|
import fHDHR.exceptions
|
||||||
@ -38,28 +36,24 @@ def run(settings, logger, db, script_dir, fHDHR_web, origin, alternative_epg):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
fhdhr.logger.info("HTTP Server Starting")
|
# Start Flask Thread
|
||||||
fhdhr_web = threading.Thread(target=fhdhrweb.run)
|
fhdhrweb.start()
|
||||||
fhdhr_web.start()
|
|
||||||
|
|
||||||
|
# Start SSDP Thread
|
||||||
if settings.dict["fhdhr"]["discovery_address"]:
|
if settings.dict["fhdhr"]["discovery_address"]:
|
||||||
fhdhr.logger.info("SSDP Server Starting")
|
fhdhr.device.ssdp.start()
|
||||||
fhdhr_ssdp = threading.Thread(target=fhdhr.device.ssdp.run)
|
|
||||||
fhdhr_ssdp.start()
|
|
||||||
|
|
||||||
|
# Start EPG Thread
|
||||||
if settings.dict["epg"]["method"]:
|
if settings.dict["epg"]["method"]:
|
||||||
fhdhr.logger.info("EPG Update Thread Starting")
|
fhdhr.device.epg.start()
|
||||||
fhdhr_epg = threading.Thread(target=fhdhr.device.epg.run)
|
|
||||||
fhdhr_epg.start()
|
|
||||||
|
|
||||||
# Perform some actions now that HTTP Server is running
|
# Perform some actions now that HTTP Server is running
|
||||||
fhdhr.logger.info("Waiting 3 seconds to send startup tasks trigger.")
|
|
||||||
time.sleep(3)
|
|
||||||
fhdhr.api.get("/api/startup_tasks")
|
fhdhr.api.get("/api/startup_tasks")
|
||||||
|
|
||||||
# wait forever
|
# wait forever
|
||||||
while True:
|
while fhdhr.threads["flask"].is_alive():
|
||||||
time.sleep(3600)
|
restart_code = "restart"
|
||||||
|
return restart_code
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
return ERR_CODE_NO_RESTART
|
return ERR_CODE_NO_RESTART
|
||||||
@ -92,7 +86,10 @@ def main(script_dir, fHDHR_web, origin, alternative_epg):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
args = build_args_parser()
|
args = build_args_parser()
|
||||||
return start(args, script_dir, fHDHR_web, origin, alternative_epg)
|
while True:
|
||||||
|
returned_code = start(args, script_dir, fHDHR_web, origin, alternative_epg)
|
||||||
|
if returned_code not in ["restart"]:
|
||||||
|
return returned_code
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("\n\nInterrupted")
|
print("\n\nInterrupted")
|
||||||
return ERR_CODE
|
return ERR_CODE
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import datetime
|
import datetime
|
||||||
|
import threading
|
||||||
|
|
||||||
from fHDHR.tools import channel_sort
|
from fHDHR.tools import channel_sort
|
||||||
|
|
||||||
@ -39,6 +40,8 @@ class EPG():
|
|||||||
|
|
||||||
self.epg_update_url = "/api/epg?method=update"
|
self.epg_update_url = "/api/epg?method=update"
|
||||||
|
|
||||||
|
self.fhdhr.threads["epg"] = threading.Thread(target=self.run)
|
||||||
|
|
||||||
def clear_epg_cache(self, method=None):
|
def clear_epg_cache(self, method=None):
|
||||||
|
|
||||||
if not method:
|
if not method:
|
||||||
@ -294,19 +297,25 @@ class EPG():
|
|||||||
self.fhdhr.db.set_fhdhr_value("update_time", method, time.time())
|
self.fhdhr.db.set_fhdhr_value("update_time", method, time.time())
|
||||||
self.fhdhr.logger.info("Wrote %s EPG cache. %s Programs for %s Channels" % (epgtypename, total_programs, total_channels))
|
self.fhdhr.logger.info("Wrote %s EPG cache. %s Programs for %s Channels" % (epgtypename, total_programs, total_channels))
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.fhdhr.logger.info("EPG Update Thread Starting")
|
||||||
|
self.fhdhr.threads["epg"].start()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.fhdhr.logger.info("EPG Update Thread Stopping")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
time.sleep(1800)
|
time.sleep(1800)
|
||||||
try:
|
while True:
|
||||||
while True:
|
for epg_method in self.epg_methods:
|
||||||
for epg_method in self.epg_methods:
|
last_update_time = self.fhdhr.db.get_fhdhr_value("update_time", epg_method)
|
||||||
last_update_time = self.fhdhr.db.get_fhdhr_value("update_time", epg_method)
|
updatetheepg = False
|
||||||
updatetheepg = False
|
if not last_update_time:
|
||||||
if not last_update_time:
|
updatetheepg = True
|
||||||
updatetheepg = True
|
elif time.time() >= (last_update_time + self.sleeptime[epg_method]):
|
||||||
elif time.time() >= (last_update_time + self.sleeptime[epg_method]):
|
updatetheepg = True
|
||||||
updatetheepg = True
|
if updatetheepg:
|
||||||
if updatetheepg:
|
self.fhdhr.api.get("%s&source=%s" % (self.epg_update_url, epg_method))
|
||||||
self.fhdhr.api.get("%s&source=%s" % (self.epg_update_url, epg_method))
|
time.sleep(1800)
|
||||||
time.sleep(1800)
|
|
||||||
except KeyboardInterrupt:
|
self.stop()
|
||||||
pass
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
import time
|
import time
|
||||||
|
import threading
|
||||||
|
|
||||||
from .ssdp_detect import fHDHR_Detect
|
from .ssdp_detect import fHDHR_Detect
|
||||||
from .rmg_ssdp import RMG_SSDP
|
from .rmg_ssdp import RMG_SSDP
|
||||||
@ -15,6 +16,8 @@ class SSDPServer():
|
|||||||
|
|
||||||
self.detect_method = fHDHR_Detect(fhdhr)
|
self.detect_method = fHDHR_Detect(fhdhr)
|
||||||
|
|
||||||
|
self.fhdhr.threads["ssdp"] = threading.Thread(target=self.run)
|
||||||
|
|
||||||
if (self.fhdhr.config.dict["fhdhr"]["discovery_address"] and
|
if (self.fhdhr.config.dict["fhdhr"]["discovery_address"] and
|
||||||
self.fhdhr.config.dict["ssdp"]["enabled"]):
|
self.fhdhr.config.dict["ssdp"]["enabled"]):
|
||||||
self.setup_ssdp()
|
self.setup_ssdp()
|
||||||
@ -32,6 +35,21 @@ class SSDPServer():
|
|||||||
self.do_alive()
|
self.do_alive()
|
||||||
self.m_search()
|
self.m_search()
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.fhdhr.logger.info("SSDP Server Starting")
|
||||||
|
self.fhdhr.threads["ssdp"].start()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.fhdhr.logger.info("SSDP Server Stopping")
|
||||||
|
self.sock.close()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while True:
|
||||||
|
data, address = self.sock.recvfrom(1024)
|
||||||
|
self.on_recv(data, address)
|
||||||
|
self.do_alive()
|
||||||
|
self.stop()
|
||||||
|
|
||||||
def do_alive(self, forcealive=False):
|
def do_alive(self, forcealive=False):
|
||||||
|
|
||||||
send_alive = False
|
send_alive = False
|
||||||
@ -132,15 +150,6 @@ class SSDPServer():
|
|||||||
|
|
||||||
return data.encode("utf-8")
|
return data.encode("utf-8")
|
||||||
|
|
||||||
def run(self):
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
data, address = self.sock.recvfrom(1024)
|
|
||||||
self.on_recv(data, address)
|
|
||||||
self.do_alive()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
self.sock.close()
|
|
||||||
|
|
||||||
def setup_ssdp(self):
|
def setup_ssdp(self):
|
||||||
self.sock = None
|
self.sock = None
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
from gevent.pywsgi import WSGIServer
|
from gevent.pywsgi import WSGIServer
|
||||||
from flask import Flask, request, session
|
from flask import Flask, request, session
|
||||||
|
import threading
|
||||||
|
import uuid
|
||||||
|
|
||||||
from .pages import fHDHR_Pages
|
from .pages import fHDHR_Pages
|
||||||
from .files import fHDHR_Files
|
from .files import fHDHR_Files
|
||||||
@ -23,6 +25,7 @@ class fHDHR_HTTP_Server():
|
|||||||
self.fhdhr.logger.info("Loading Flask.")
|
self.fhdhr.logger.info("Loading Flask.")
|
||||||
|
|
||||||
self.fhdhr.app = Flask("fHDHR", template_folder=self.template_folder)
|
self.fhdhr.app = Flask("fHDHR", template_folder=self.template_folder)
|
||||||
|
self.instance_id = str(uuid.uuid4())
|
||||||
|
|
||||||
# Allow Internal API Usage
|
# Allow Internal API Usage
|
||||||
self.fhdhr.app.testing = True
|
self.fhdhr.app.testing = True
|
||||||
@ -63,11 +66,24 @@ class fHDHR_HTTP_Server():
|
|||||||
self.fhdhr.app.after_request(self.after_request)
|
self.fhdhr.app.after_request(self.after_request)
|
||||||
self.fhdhr.app.before_first_request(self.before_first_request)
|
self.fhdhr.app.before_first_request(self.before_first_request)
|
||||||
|
|
||||||
|
self.fhdhr.threads["flask"] = threading.Thread(target=self.run)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.fhdhr.logger.info("Flask HTTP Thread Starting")
|
||||||
|
self.fhdhr.threads["flask"].start()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.fhdhr.logger.info("Flask HTTP Thread Stopping")
|
||||||
|
self.http.stop()
|
||||||
|
|
||||||
def before_first_request(self):
|
def before_first_request(self):
|
||||||
self.fhdhr.logger.info("HTTP Server Online.")
|
self.fhdhr.logger.info("HTTP Server Online.")
|
||||||
|
|
||||||
def before_request(self):
|
def before_request(self):
|
||||||
|
|
||||||
|
session["session_id"] = str(uuid.uuid4())
|
||||||
|
session["instance_id"] = self.instance_id
|
||||||
|
|
||||||
session["is_internal_api"] = self.detect_internal_api(request)
|
session["is_internal_api"] = self.detect_internal_api(request)
|
||||||
if session["is_internal_api"]:
|
if session["is_internal_api"]:
|
||||||
self.fhdhr.logger.debug("Client is using internal API call.")
|
self.fhdhr.logger.debug("Client is using internal API call.")
|
||||||
@ -84,6 +100,8 @@ class fHDHR_HTTP_Server():
|
|||||||
|
|
||||||
session["tuner_used"] = None
|
session["tuner_used"] = None
|
||||||
|
|
||||||
|
session["restart"] = False
|
||||||
|
|
||||||
self.fhdhr.logger.debug("Client %s requested %s Opening" % (request.method, request.path))
|
self.fhdhr.logger.debug("Client %s requested %s Opening" % (request.method, request.path))
|
||||||
|
|
||||||
def after_request(self, response):
|
def after_request(self, response):
|
||||||
@ -96,7 +114,10 @@ class fHDHR_HTTP_Server():
|
|||||||
# tuner.close()
|
# tuner.close()
|
||||||
|
|
||||||
self.fhdhr.logger.debug("Client %s requested %s Closing" % (request.method, request.path))
|
self.fhdhr.logger.debug("Client %s requested %s Closing" % (request.method, request.path))
|
||||||
return response
|
if not session["restart"]:
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
return self.stop()
|
||||||
|
|
||||||
def detect_internal_api(self, request):
|
def detect_internal_api(self, request):
|
||||||
user_agent = request.headers.get('User-Agent')
|
user_agent = request.headers.get('User-Agent')
|
||||||
@ -165,8 +186,8 @@ class fHDHR_HTTP_Server():
|
|||||||
self.http = WSGIServer(self.fhdhr.api.address_tuple,
|
self.http = WSGIServer(self.fhdhr.api.address_tuple,
|
||||||
self.fhdhr.app.wsgi_app,
|
self.fhdhr.app.wsgi_app,
|
||||||
log=self.fhdhr.logger)
|
log=self.fhdhr.logger)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.http.serve_forever()
|
self.http.serve_forever()
|
||||||
except KeyboardInterrupt:
|
self.stop()
|
||||||
self.http.stop()
|
except AttributeError:
|
||||||
|
self.fhdhr.logger.info("HTTP Server Offline")
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from flask import request, redirect
|
from flask import request, redirect, session
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
|
|
||||||
@ -34,6 +34,11 @@ class Settings():
|
|||||||
|
|
||||||
self.fhdhr.config.write(config_section, config_name, config_value)
|
self.fhdhr.config.write(config_section, config_name, config_value)
|
||||||
|
|
||||||
|
elif method == "restart":
|
||||||
|
instance_id = request.args.get('instance_id', default=None, type=str)
|
||||||
|
if instance_id == session["instance_id"]:
|
||||||
|
session["restart"] = True
|
||||||
|
|
||||||
if redirect_url:
|
if redirect_url:
|
||||||
return redirect(redirect_url + "?retmessage=" + urllib.parse.quote("%s Success" % method))
|
return redirect(redirect_url + "?retmessage=" + urllib.parse.quote("%s Success" % method))
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -2,67 +2,72 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h4 style="text-align: center;">fHDHR Settings</h4>
|
<h4 style="text-align: center;">fHDHR Settings</h4>
|
||||||
|
|
||||||
<h4 style="text-align: center;">Settings will require a manual restart.</h4>
|
<h4 style="text-align: center;">Some Settings will require a manual restart.</h4>
|
||||||
|
|
||||||
{% for config_section in list(web_settings_dict.keys()) %}
|
<div style="text-align: center;">
|
||||||
|
<button onclick="OpenLink('/api/settings?method=restart&instance_id={{ session["instance_id"] }}&redirect=%2Fsettings')">Restart fHDHR</a></button><p> Note: This may take some time, and you will have to refresh your page.</p>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
|
||||||
{% if config_section == "origin" %}
|
{% for config_section in list(web_settings_dict.keys()) %}
|
||||||
<h4 style="text-align: center;">{{ fhdhr.config.dict["main"]["dictpopname"] }}</h4>
|
|
||||||
{% else %}
|
{% if config_section == "origin" %}
|
||||||
<h4 style="text-align: center;">{{ config_section }}</h4>
|
<h4 style="text-align: center;">{{ fhdhr.config.dict["main"]["dictpopname"] }}</h4>
|
||||||
{% endif %}
|
{% else %}
|
||||||
|
<h4 style="text-align: center;">{{ config_section }}</h4>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<table class="table-settings center action-col text-edit-cols">
|
<table class="table-settings center action-col text-edit-cols">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Config Name</th>
|
<th>Config Name</th>
|
||||||
<th>Config Default Value</th>
|
<th>Config Default Value</th>
|
||||||
<th>Config Value</th>
|
<th>Config Value</th>
|
||||||
<th>Action</th>
|
<th>Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
||||||
{% for config_item in list(web_settings_dict[config_section].keys()) %}
|
{% for config_item in list(web_settings_dict[config_section].keys()) %}
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ config_item }}</td>
|
<td>{{ config_item }}</td>
|
||||||
|
|
||||||
<td>{{ web_settings_dict[config_section][config_item]["value_default"] }}</td>
|
<td>{{ web_settings_dict[config_section][config_item]["value_default"] }}</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<form method="post" action="/api/settings?method=update&redirect=%2Fsettings">
|
<form method="post" action="/api/settings?method=update&redirect=%2Fsettings">
|
||||||
<input type="hidden" name="config_section" value="{{ config_section }}">
|
<input type="hidden" name="config_section" value="{{ config_section }}">
|
||||||
<input type="hidden" name="config_name" value="{{ config_item }}">
|
<input type="hidden" name="config_name" value="{{ config_item }}">
|
||||||
<input type="hidden" name="config_default" value="{{ web_settings_dict[config_section][config_item]["value_default"] }}">
|
<input type="hidden" name="config_default" value="{{ web_settings_dict[config_section][config_item]["value_default"] }}">
|
||||||
{% if web_settings_dict[config_section][config_item]["hide"] %}
|
{% if web_settings_dict[config_section][config_item]["hide"] %}
|
||||||
<input type="text" size="25" name="config_value" value="**************">
|
<input type="text" size="25" name="config_value" value="**************">
|
||||||
{% else %}
|
{% else %}
|
||||||
<input type="text" size="25" name="config_value" value="{{ web_settings_dict[config_section][config_item]["value"] }}">
|
<input type="text" size="25" name="config_value" value="{{ web_settings_dict[config_section][config_item]["value"] }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td style="display:flex;">
|
<td style="display:flex;">
|
||||||
<span style="margin:auto">
|
<span style="margin:auto">
|
||||||
<input type="submit" value="Update">
|
<input type="submit" value="Update">
|
||||||
</form>
|
</form>
|
||||||
</span>
|
</span>
|
||||||
<form style="margin:auto">
|
<form style="margin:auto">
|
||||||
<input type="hidden" name="config_section" value="{{ config_section }}">
|
<input type="hidden" name="config_section" value="{{ config_section }}">
|
||||||
<input type="hidden" name="config_name" value="{{ config_item }}">
|
<input type="hidden" name="config_name" value="{{ config_item }}">
|
||||||
<input type="hidden" name="config_value" value="{{ web_settings_dict[config_section][config_item]["value_default"] }}">
|
<input type="hidden" name="config_value" value="{{ web_settings_dict[config_section][config_item]["value_default"] }}">
|
||||||
<input type="hidden" name="config_default" value="{{ web_settings_dict[config_section][config_item]["value_default"] }}">
|
<input type="hidden" name="config_default" value="{{ web_settings_dict[config_section][config_item]["value_default"] }}">
|
||||||
<input type="submit" value="Reset">
|
<input type="submit" value="Reset">
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user