mirror of
https://github.com/mynodebtc/mynode.git
synced 2024-12-25 14:08:07 +00:00
Add option to show USD/BTC price ticker
This commit is contained in:
parent
ff44c5c780
commit
d93a095a08
|
@ -9,6 +9,7 @@ from device_info import *
|
|||
from thread_functions import *
|
||||
from systemctl_info import *
|
||||
from application_info import *
|
||||
from price_info import *
|
||||
from messages import *
|
||||
if isPython3():
|
||||
from io import StringIO, BytesIO
|
||||
|
@ -63,6 +64,17 @@ def api_get_lightning_info():
|
|||
|
||||
return jsonify(data)
|
||||
|
||||
@mynode_api.route("/api/get_price_info")
|
||||
def api_get_price_info():
|
||||
check_logged_in()
|
||||
|
||||
data = {}
|
||||
data["price"] = get_latest_price()
|
||||
data["delta"] = get_price_diff_24hrs()
|
||||
data["direction"] = get_price_up_down_flat_24hrs()
|
||||
|
||||
return jsonify(data)
|
||||
|
||||
@mynode_api.route("/api/get_service_status")
|
||||
def api_get_service_status():
|
||||
check_logged_in()
|
||||
|
@ -193,7 +205,7 @@ def api_toggle_setting():
|
|||
|
||||
setting = request.args.get("setting")
|
||||
if setting == "pinned_lightning_details":
|
||||
toggle_pinned_lightning_details()
|
||||
toggle_ui_setting("pinned_lightning_details")
|
||||
data["status"] = "success"
|
||||
else:
|
||||
data["status"] = "unknown_setting"
|
||||
|
|
|
@ -31,6 +31,7 @@ except:
|
|||
local_ip = "unknown"
|
||||
cached_data = {}
|
||||
warning_data = {}
|
||||
ui_settings = None
|
||||
|
||||
#==================================
|
||||
# Manage Device
|
||||
|
@ -458,7 +459,22 @@ def get_drive_info(drive):
|
|||
#==================================
|
||||
# UI Functions
|
||||
#==================================
|
||||
def init_ui_setting_defaults(ui_settings):
|
||||
if "darkmode" not in ui_settings:
|
||||
ui_settings["darkmode"] = False
|
||||
if "price_ticker" not in ui_settings:
|
||||
ui_settings["price_ticker"] = False
|
||||
if "pinned_lightning_details" not in ui_settings:
|
||||
ui_settings["pinned_lightning_details"] = False
|
||||
if "background" not in ui_settings:
|
||||
ui_settings["background"] = "none"
|
||||
return ui_settings
|
||||
|
||||
def read_ui_settings():
|
||||
global ui_settings
|
||||
if ui_settings != None:
|
||||
return ui_settings
|
||||
|
||||
ui_hdd_file = '/mnt/hdd/mynode/settings/ui.json'
|
||||
ui_mynode_file = '/home/bitcoin/.mynode/ui.json'
|
||||
|
||||
|
@ -470,19 +486,20 @@ def read_ui_settings():
|
|||
elif os.path.isfile(ui_mynode_file):
|
||||
with open(ui_mynode_file, 'r') as fp:
|
||||
ui_settings = json.load(fp)
|
||||
# if ui.json is not found anywhere, use default settings
|
||||
else:
|
||||
ui_settings = {'darkmode': False}
|
||||
|
||||
# Set reseller
|
||||
ui_settings["reseller"] = is_device_from_reseller()
|
||||
|
||||
ui_settings = init_ui_setting_defaults(ui_settings)
|
||||
|
||||
return ui_settings
|
||||
|
||||
def write_ui_settings(ui_settings):
|
||||
def write_ui_settings(ui_settings_new):
|
||||
global ui_settings
|
||||
ui_settings = ui_settings_new
|
||||
|
||||
ui_hdd_file = '/mnt/hdd/mynode/settings/ui.json'
|
||||
ui_mynode_file = '/home/bitcoin/.mynode/ui.json'
|
||||
|
||||
try:
|
||||
with open(ui_hdd_file, 'w') as fp:
|
||||
json.dump(ui_settings, fp)
|
||||
|
@ -492,42 +509,18 @@ def write_ui_settings(ui_settings):
|
|||
with open(ui_mynode_file, 'w') as fp:
|
||||
json.dump(ui_settings, fp)
|
||||
|
||||
def is_darkmode_enabled():
|
||||
def get_ui_setting(name):
|
||||
ui_settings = read_ui_settings()
|
||||
return ui_settings['darkmode']
|
||||
return ui_settings[name]
|
||||
|
||||
def disable_darkmode():
|
||||
def set_ui_setting(name, value):
|
||||
ui_settings = read_ui_settings()
|
||||
ui_settings['darkmode'] = False
|
||||
ui_settings[name] = value
|
||||
write_ui_settings(ui_settings)
|
||||
|
||||
def enable_darkmode():
|
||||
ui_settings = read_ui_settings()
|
||||
ui_settings['darkmode'] = True
|
||||
write_ui_settings(ui_settings)
|
||||
def toggle_ui_setting(name):
|
||||
set_ui_setting(name, not get_ui_setting(name))
|
||||
|
||||
def toggle_darkmode():
|
||||
if is_darkmode_enabled():
|
||||
disable_darkmode()
|
||||
else:
|
||||
enable_darkmode()
|
||||
|
||||
def toggle_pinned_lightning_details():
|
||||
ui_settings = read_ui_settings()
|
||||
if "pinned_lightning_details" not in ui_settings or ui_settings["pinned_lightning_details"] == False:
|
||||
ui_settings["pinned_lightning_details"] = True
|
||||
else:
|
||||
ui_settings["pinned_lightning_details"] = False
|
||||
write_ui_settings(ui_settings)
|
||||
|
||||
def set_background(background):
|
||||
ui_settings = read_ui_settings()
|
||||
ui_settings['background'] = background
|
||||
write_ui_settings(ui_settings)
|
||||
|
||||
def get_background():
|
||||
ui_settings = read_ui_settings()
|
||||
return ui_settings['background']
|
||||
|
||||
# def get_background_choices():
|
||||
# choices = []
|
||||
|
|
|
@ -31,6 +31,7 @@ from device_info import *
|
|||
from device_warnings import *
|
||||
from systemctl_info import *
|
||||
from application_info import *
|
||||
from price_info import *
|
||||
import pam
|
||||
import re
|
||||
import json
|
||||
|
@ -752,6 +753,9 @@ def start_threads():
|
|||
lnd_thread = BackgroundThread(update_lnd_info_thread, 60)
|
||||
lnd_thread.start()
|
||||
threads.append(lnd_thread)
|
||||
price_thread = BackgroundThread(update_price_info_thread, 30) # 5 minutes
|
||||
price_thread.start()
|
||||
threads.append(price_thread)
|
||||
drive_thread = BackgroundThread(update_device_info, 60)
|
||||
drive_thread.start()
|
||||
threads.append(drive_thread)
|
||||
|
|
60
rootfs/standard/var/www/mynode/price_info.py
Normal file
60
rootfs/standard/var/www/mynode/price_info.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
from utilities import *
|
||||
from device_info import *
|
||||
import subprocess
|
||||
import json
|
||||
import time
|
||||
import os
|
||||
|
||||
|
||||
price_data = []
|
||||
|
||||
def get_latest_price():
|
||||
global price_data
|
||||
if len(price_data) > 0:
|
||||
return price_data[len(price_data) - 1]["price"]
|
||||
return "N/A"
|
||||
|
||||
def get_price_diff_24hrs():
|
||||
global price_data
|
||||
latest = get_latest_price()
|
||||
if len(price_data) > 0:
|
||||
old = price_data[0]["price"]
|
||||
if latest != "N/A" and old != "N/A":
|
||||
return latest - old
|
||||
return 0.0
|
||||
|
||||
def get_price_up_down_flat_24hrs():
|
||||
diff = get_price_diff_24hrs()
|
||||
if diff > 10:
|
||||
return "up"
|
||||
elif diff < -10:
|
||||
return "down"
|
||||
return "flat"
|
||||
|
||||
def update_price_info():
|
||||
global price_data
|
||||
|
||||
if get_ui_setting("price_ticker"):
|
||||
price = "N/A"
|
||||
try:
|
||||
price_json_string = subprocess.check_output("torify curl https://api.coindesk.com/v1/bpi/currentprice.json", shell=True)
|
||||
data = json.loads(price_json_string)
|
||||
price = data["bpi"]["USD"]["rate_float"]
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
# Add latest price
|
||||
now = int(time.time())
|
||||
d = {}
|
||||
d["time"] = now
|
||||
d["price"] = price
|
||||
price_data.append(d)
|
||||
|
||||
# only keep 24 hours of updates
|
||||
while len(price_data) > 0:
|
||||
d = price_data[0]
|
||||
if d["time"] < now - 24*60*60:
|
||||
price_data.pop(0)
|
||||
else:
|
||||
break
|
|
@ -10,7 +10,7 @@ from threading import Timer
|
|||
from thread_functions import *
|
||||
from user_management import check_logged_in
|
||||
from lightning_info import *
|
||||
from thread_functions import *
|
||||
from price_info import *
|
||||
from utilities import *
|
||||
from application_info import *
|
||||
import pam
|
||||
|
@ -983,15 +983,24 @@ def ping_page():
|
|||
@mynode_settings.route("/settings/toggle-darkmode")
|
||||
def toggle_darkmode_page():
|
||||
check_logged_in()
|
||||
toggle_darkmode()
|
||||
toggle_ui_setting("darkmode")
|
||||
flash("Darkmode Setting Updated", category="message")
|
||||
return redirect("/settings")
|
||||
|
||||
@mynode_settings.route("/settings/toggle-darkmode-home")
|
||||
def toggle_darkmode_page_home():
|
||||
check_logged_in()
|
||||
toggle_darkmode()
|
||||
toggle_ui_setting("darkmode")
|
||||
return redirect("/")
|
||||
|
||||
@mynode_settings.route("/settings/toggle-price-ticker")
|
||||
def toggle_price_ticker_page():
|
||||
check_logged_in()
|
||||
toggle_ui_setting("price_ticker")
|
||||
update_price_info()
|
||||
flash("Price Ticker Setting Updated", category="message")
|
||||
return redirect("/settings")
|
||||
|
||||
@mynode_settings.route("/settings/set-background", methods=['POST'])
|
||||
def set_background_page():
|
||||
check_logged_in()
|
||||
|
@ -1001,8 +1010,9 @@ def set_background_page():
|
|||
return redirect("/settings")
|
||||
|
||||
bg = request.form.get('background')
|
||||
set_background(bg)
|
||||
set_ui_setting("background", bg)
|
||||
|
||||
flash("Background Updated", category="message")
|
||||
return redirect("/settings")
|
||||
|
||||
@mynode_settings.route("/settings/toggle-netdata")
|
||||
|
@ -1013,6 +1023,8 @@ def toggle_netdata_page():
|
|||
disable_service("netdata")
|
||||
else:
|
||||
enable_service("netdata")
|
||||
|
||||
flash("Netdata Setting Updated", category="message")
|
||||
return redirect("/settings")
|
||||
|
||||
@mynode_settings.route("/settings/toggle-check-external-drive")
|
||||
|
|
|
@ -249,6 +249,16 @@ td, th {
|
|||
background: #f0f0f0;
|
||||
}
|
||||
/* width of four tiles (full width) */
|
||||
.app_tile_price_ticker {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
width: 810px;
|
||||
height: 20px;
|
||||
padding: 6px 10px 6px 10px;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
.app_tile_bitcoin_recent_blocks {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
|
@ -695,10 +705,10 @@ a:link.ui-button, a:visited.ui-button, .ui-button {
|
|||
|
||||
.main_page_warning_block {
|
||||
color: #333333;
|
||||
border: 3px solid orange;
|
||||
border: 2px solid orange;
|
||||
background-color: rgb(255, 250, 238);
|
||||
width: 800px;
|
||||
border-radius: 25px;
|
||||
width: 810px;
|
||||
border-radius: 10px;
|
||||
text-align: justify;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
|
@ -709,10 +719,10 @@ a:link.ui-button, a:visited.ui-button, .ui-button {
|
|||
|
||||
.main_page_error_block {
|
||||
color: #333333;
|
||||
border: 3px solid red;
|
||||
border: 2px solid red;
|
||||
background-color: rgb(255, 238, 238);
|
||||
width: 800px;
|
||||
border-radius: 25px;
|
||||
width: 810px;
|
||||
border-radius: 10px;
|
||||
text-align: justify;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
|
@ -725,12 +735,12 @@ a:link.ui-button, a:visited.ui-button, .ui-button {
|
|||
display: none;
|
||||
position: fixed;
|
||||
color: #333333;
|
||||
border: 3px solid orange;
|
||||
border: 2px solid orange;
|
||||
background-color: rgb(255, 250, 238);
|
||||
width: 800px;
|
||||
width: 810px;
|
||||
left: 50%;
|
||||
margin-left: -400px;
|
||||
border-radius: 25px;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
padding: 20px;
|
||||
|
|
|
@ -40,6 +40,7 @@ a:active {
|
|||
.device_status_info,
|
||||
.bitcoin_block,
|
||||
.pair_wallet_text,
|
||||
.app_tile_price_ticker,
|
||||
.app_tile_lightning_details,
|
||||
.lightning_channel_container,
|
||||
.settings_block_subheader,
|
||||
|
@ -54,6 +55,7 @@ table,
|
|||
.app_tile,
|
||||
.app_tile_short,
|
||||
.app_tile_wide,
|
||||
.app_tile_price_ticker,
|
||||
.app_tile_bitcoin_recent_blocks,
|
||||
.app_tile_lightning_details,
|
||||
.info_tile {
|
||||
|
@ -62,6 +64,7 @@ table,
|
|||
|
||||
.app_tile,
|
||||
.app_tile_wide,
|
||||
.app_tile_price_ticker,
|
||||
.app_tile_bitcoin_recent_blocks,
|
||||
.app_tile_lightning_details,
|
||||
.app_tile_short {
|
||||
|
@ -140,7 +143,7 @@ th td {
|
|||
.bottom_center_alert_popup,
|
||||
.halving_message_main_page {
|
||||
color: #ddd;
|
||||
border: 3px solid orange;
|
||||
border: 2px solid orange;
|
||||
background-color: #3a4750;
|
||||
}
|
||||
|
||||
|
|
|
@ -99,9 +99,16 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Show Price Info -->
|
||||
<div class="app_tile_row" id="price_ticker" style="display: none;">
|
||||
<div class="app_tile_price_ticker" >
|
||||
<span id="price_ticker_text"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Show Bitcoin Blocks -->
|
||||
<div class="app_tile_row">
|
||||
<div class="app_tile_bitcoin_recent_blocks" id="bitcoin_blocks" style="display: none;">
|
||||
<div class="app_tile_row" id="bitcoin_blocks" style="display: none;">
|
||||
<div class="app_tile_bitcoin_recent_blocks" >
|
||||
<div class="bitcoin_block_set"></div>
|
||||
<div class="bitcoin_block">
|
||||
<div class="bitcoin_block_orange_square">
|
||||
|
@ -164,8 +171,8 @@
|
|||
</div>
|
||||
|
||||
<!-- Show Lightning Details -->
|
||||
<div class="app_tile_row">
|
||||
<div class="app_tile_lightning_details" id="lightning_details" style="display: none;">
|
||||
<div class="app_tile_row" id="lightning_details" style="display: none;">
|
||||
<div class="app_tile_lightning_details">
|
||||
|
||||
<!-- Top Wallet Section -->
|
||||
<p style="font-size: 16px; font-weight: bold;">Wallet</p>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
var is_installing_docker_images = {% if is_installing_docker_images %}true{% else %}false{% endif %};
|
||||
var lnd_last_btc_tx = "";
|
||||
var lnd_last_ln_tx = "";
|
||||
var price_data = {};
|
||||
|
||||
// Toggle enable/disable functions
|
||||
function get_custom_enable_message(short_name) {
|
||||
|
@ -96,6 +97,36 @@
|
|||
}
|
||||
}
|
||||
|
||||
var price_display_rotate_count = 0;
|
||||
function update_price_display() {
|
||||
{% if ui_settings['price_ticker'] %}
|
||||
if ("price" in price_data && "delta" in price_data && "direction" in price_data ) {
|
||||
$("#price_ticker").show();
|
||||
$("#price_ticker_text").slideUp('fast', function() {
|
||||
display_id = price_display_rotate_count % 3;
|
||||
if (display_id == 0) {
|
||||
p = price_data["price"].toLocaleString('en-US', {style: 'currency', currency: 'USD'});
|
||||
$("#price_ticker_text").html(p + " USD/BTC");
|
||||
} else if (display_id == 1) {
|
||||
sats = parseInt(100000000 / price_data["price"]);
|
||||
$("#price_ticker_text").html(sats + " SATS/USD");
|
||||
} else if (display_id == 2) {
|
||||
p = Math.abs(price_data["delta"]).toLocaleString('en-US', {style: 'currency', currency: 'USD'});
|
||||
if (price_data["direction"] == "flat") {
|
||||
$("#price_ticker_text").html("Price is flat");
|
||||
} else if (price_data["direction"] == "up") {
|
||||
$("#price_ticker_text").html("Price is up "+p);
|
||||
} else if (price_data["direction"] == "down") {
|
||||
$("#price_ticker_text").html("Price is down "+p);
|
||||
}
|
||||
}
|
||||
$("#price_ticker_text").slideDown();
|
||||
price_display_rotate_count = price_display_rotate_count + 1;
|
||||
});
|
||||
}
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
function update_sso_token(short_name, data) {
|
||||
if ("sso_token" in data && data["sso_token"] != null && data["sso_token"] != "") {
|
||||
application_data[short_name]["sso_token"] = data["sso_token"]
|
||||
|
@ -350,6 +381,17 @@
|
|||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
// Update price info
|
||||
$.getJSON("/api/get_price_info", function( data ) {
|
||||
console.log("Price Data: " + JSON.stringify(data))
|
||||
if ("price" in data && data["price"] != null) {
|
||||
price_data = data;
|
||||
if (price_display_rotate_count == 0) {
|
||||
update_price_display();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Update device info
|
||||
$.getJSON("/api/get_device_info", function( data ) {
|
||||
//console.log("Device Data: " + JSON.stringify(data))
|
||||
|
@ -572,6 +614,9 @@
|
|||
const update_interval = setInterval(update_page, 15000);
|
||||
update_page();
|
||||
|
||||
// Rotate Price Ticker every 10 seconds
|
||||
const rotate_ticker_interval = setInterval(update_price_display, 10000);
|
||||
|
||||
// If pinned lightning, auto open lightning details
|
||||
{% if lnd_wallet_exists and lnd_ready and ui_settings['pinned_lightning_details'] %}
|
||||
setTimeout(toggleLightningDetails, 1500);
|
||||
|
|
|
@ -631,6 +631,17 @@
|
|||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="settings_block_subheader">Price Ticker</div>
|
||||
Display recent Bitcoin price on the main page.
|
||||
<br/>
|
||||
{% if ui_settings['price_ticker'] %}
|
||||
<a href="/settings/toggle-price-ticker" class="ui-button ui-widget ui-corner-all settings_button">Disable</a>
|
||||
{% else %}
|
||||
<a href="/settings/toggle-price-ticker" class="ui-button ui-widget ui-corner-all settings_button">Enable</a>
|
||||
{% endif %}
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="settings_block_subheader">Background</div>
|
||||
For fun, you can set a background image.
|
||||
<br/><br/>
|
||||
|
|
|
@ -9,6 +9,7 @@ from device_info import *
|
|||
from enable_disable_functions import *
|
||||
from systemctl_info import *
|
||||
from electrum_info import update_electrs_info
|
||||
from price_info import update_price_info
|
||||
from requests import get
|
||||
import random
|
||||
|
||||
|
@ -22,7 +23,6 @@ swap_usage = "..."
|
|||
device_temp = "..."
|
||||
public_ip = "not_detected"
|
||||
|
||||
|
||||
# Getters
|
||||
def get_has_updated_btc_info():
|
||||
global has_updated_btc_info
|
||||
|
@ -160,6 +160,15 @@ def update_lnd_info_thread():
|
|||
print("CAUGHT update_lnd_info_thread EXCEPTION: " + str(e))
|
||||
|
||||
|
||||
# Updates price info every 5 minutes
|
||||
def update_price_info_thread():
|
||||
try:
|
||||
# Get Price Info
|
||||
update_price_info()
|
||||
except Exception as e:
|
||||
print("CAUGHT update_price_info_thread EXCEPTION: " + str(e))
|
||||
|
||||
|
||||
# Check every 3 hours
|
||||
def find_public_ip():
|
||||
global public_ip
|
||||
|
|
Loading…
Reference in New Issue
Block a user