commit
bf95d7b553
16
README.md
16
README.md
|
|
@ -33,9 +33,11 @@ Just one config is used to configure Domoboard. A example can be found the appli
|
|||
- top_tiles
|
||||
- switches
|
||||
- switch
|
||||
- Selector Switch
|
||||
- dimmer
|
||||
- rgb
|
||||
- setpoint
|
||||
- setpoint_slider
|
||||
- pushon
|
||||
- pushoff
|
||||
- group
|
||||
|
|
@ -78,31 +80,31 @@ Check out the page https://github.com/wez3/domoboard-plugins for all plugins.
|
|||
|
||||
Here are some screenshots from Domoboard:
|
||||
|
||||

|
||||

|
||||
|
||||
Above screenshot shows the components top_tiles, line_charts, switches and weather.
|
||||
|
||||

|
||||

|
||||
|
||||
Above screenshot shows the mobile view of the Dashboard.
|
||||
|
||||

|
||||

|
||||
|
||||
Above screenshot shows the Raspberry Pi 7" Touch screen view of the Dashboard.
|
||||
|
||||

|
||||

|
||||
|
||||
Above the components domoticz_smart_charts, domoticz_counter_charts and domoticz_temp_charts.
|
||||
|
||||

|
||||

|
||||
|
||||
Above screenshot shows the components bar_charts, donut_charts, switches and power_usage components.
|
||||
|
||||

|
||||

|
||||
|
||||
Above screenshots shows the server log component
|
||||
|
||||

|
||||

|
||||
|
||||
Above screenshots shows the settings page.
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
1.0.0
|
||||
1.0.10
|
||||
|
|
|
|||
12
example.conf
12
example.conf
|
|
@ -9,6 +9,8 @@
|
|||
username = password # Add users for Domoboard here. In this case login with username "username" and password "password"
|
||||
[[domoboard]]
|
||||
time = False # True/False: show time in top bar
|
||||
date = False # True/False: show date in top bar
|
||||
language = "gb" # Change this to display date/time in local language and format
|
||||
google_maps_api_key = X # Google Maps Embed API key
|
||||
|
||||
# Add Navbar items here. The key is the navbar link name. The first value is the URI name, second value can be any font awesome logo to be displayed.
|
||||
|
|
@ -32,11 +34,11 @@
|
|||
[[top_tiles]]
|
||||
Temperatuur tuin = 31, fire
|
||||
Temperatuur auto = 22, car
|
||||
Stroomverbruik TV = 13, plug
|
||||
Stroomverbruik TV = 13, plug, Usage, Watt
|
||||
Temperatuur Eindhoven = 54, fire
|
||||
Temperatuur tuin BMP = 55, fire
|
||||
Totaal Playstation = 25, plug
|
||||
Totaal slaapkamer lamp = 12, plug
|
||||
Totaal Playstation = 25, plug, Usage, Watt
|
||||
Totaal slaapkamer lamp = 12, plug, CounterToday, kWh
|
||||
Temperatuur raspberry = 1, car
|
||||
[[line_charts]]
|
||||
Temperatuur Slaapkamer = 14, month, temp
|
||||
|
|
@ -52,6 +54,8 @@
|
|||
Close Garage door = 567, pushoff
|
||||
Scene Home = 4, scene
|
||||
Group kitchen lights = 5, group
|
||||
Thermostaat_slider = 71, setpoint_slider, 18, 28
|
||||
Selector = 201, selector
|
||||
[[power_usage]]
|
||||
Totaal slaapkamer lamp = 12
|
||||
Totaal playstation = 71
|
||||
|
|
@ -130,7 +134,7 @@
|
|||
[[[Frontdoor]]]
|
||||
url = http://x.x.x.x:88/cgi-bin/CGIStream.cgi?cmd=GetMJStream&usr=xxx&pwd=xxx
|
||||
[[[Backdoor]]]
|
||||
url = http://x.x.x.x:88/cgi-bin/CGIStream.cgi?cmd=GetMJStream&usr=xxx&pwd=xxx
|
||||
url = rtsp://x.x.x.x:88/cgi-bin/CGIStream.cgi?cmd=GetMJStream&usr=xxx&pwd=xxx
|
||||
|
||||
[server]
|
||||
[[display_components]]
|
||||
|
|
|
|||
291
modules/api.py
291
modules/api.py
|
|
@ -3,273 +3,72 @@
|
|||
|
||||
from flask import request
|
||||
from flaskext.auth import login_required
|
||||
import git
|
||||
import security
|
||||
import requests, json, re
|
||||
import os, sys, imp, shutil
|
||||
import json, os, sys
|
||||
import security, charts, plugins, webconfig, domoticz
|
||||
|
||||
apiDict = {}
|
||||
indexes = {}
|
||||
modules = {}
|
||||
|
||||
def init():
|
||||
global modules
|
||||
modules = loadPlugins()
|
||||
return 0
|
||||
modules = plugins.loadPlugins()
|
||||
return
|
||||
|
||||
def addToApi(custom, module, function):
|
||||
apiDict[custom] = [module, function]
|
||||
|
||||
@login_required()
|
||||
def gateway():
|
||||
requestedUrl = request.url.split("/api")
|
||||
custom = request.args.get('custom', '')
|
||||
if custom == "bar_chart":
|
||||
result = charts.barChart()
|
||||
elif custom == "donut_chart":
|
||||
result = charts.donutChart()
|
||||
elif custom == "modify_config":
|
||||
idx = request.args.get('idx', '')
|
||||
page = request.args.get('page', '')
|
||||
component = request.args.get('component', '')
|
||||
description = request.args.get('description', '')
|
||||
extra = request.args.get('extra', '')
|
||||
webconfig.writeToConfig(idx, page, component, description, extra)
|
||||
elif custom == 'indexPlugins':
|
||||
result = json.dumps(plugins.indexPlugins(request.args))
|
||||
elif custom == "performUpgrade":
|
||||
result = json.dumps(webconfig.performUpgrade())
|
||||
elif custom in apiDict:
|
||||
module = apiDict.get(custom)[0]
|
||||
function = apiDict.get(custom)[1]
|
||||
call = getattr(modules[module], function)
|
||||
result = call(request.args)
|
||||
else:
|
||||
result = domoticz.queryDomoticz(requestedUrl[1])
|
||||
try:
|
||||
if not isJson(result):
|
||||
result = json.dumps(result)
|
||||
return security.sanitizeJSON(json.loads(result))
|
||||
except:
|
||||
return "No results returned"
|
||||
|
||||
def setConfig(cfg, orig_cfg):
|
||||
global config
|
||||
global originalCfg
|
||||
config = cfg
|
||||
originalCfg = orig_cfg
|
||||
|
||||
def setModules(modulesList):
|
||||
global modules
|
||||
modules = modulesList
|
||||
|
||||
def getConfig():
|
||||
global config
|
||||
return config
|
||||
|
||||
def loadPlugins():
|
||||
plugin = {}
|
||||
plugin_dir = os.getcwd() + '/plugins/'
|
||||
for i in os.listdir(plugin_dir):
|
||||
if not i == '__init__.py' and i.endswith('.py'):
|
||||
name = i.replace('.py', '')
|
||||
try:
|
||||
plugin[name] = imp.load_source(name, plugin_dir + i)
|
||||
plugin[name].init()
|
||||
except ImportError as msg:
|
||||
sys.exit("Error occured during loading imports for the plugin {}: {}".format(name, msg))
|
||||
return plugin
|
||||
def getOriginalConfig():
|
||||
return originalCfg
|
||||
|
||||
@login_required()
|
||||
def gateway():
|
||||
requestedUrl = request.url.split("/api")
|
||||
custom = request.args.get('custom', '')
|
||||
if custom == "bar_chart":
|
||||
idxs = request.args.get('idxs', '')
|
||||
idxArray = idxs.split(",")
|
||||
resultArray = []
|
||||
resultDict = {}
|
||||
for i in idxArray:
|
||||
qResults = queryDomoticz("?type=devices&rid=" + i)
|
||||
jsonObj = json.loads(qResults)
|
||||
resultDict["y"] = jsonObj["result"][0]["Name"]
|
||||
resultDict["a"] = jsonObj["result"][0]["Data"]
|
||||
resultArray.append(resultDict.copy())
|
||||
result = json.dumps(resultArray)
|
||||
elif custom == "donut_chart":
|
||||
idxs = request.args.get('idxs', '')
|
||||
idxArray = idxs.split(",")
|
||||
resultArray = []
|
||||
resultDict = {}
|
||||
for i in idxArray:
|
||||
qResults = queryDomoticz("?type=devices&rid=" + i)
|
||||
jsonObj = json.loads(qResults)
|
||||
resultDict["label"] = jsonObj["result"][0]["Name"]
|
||||
resultDict["value"] = re.findall("\d+\.?\d+", jsonObj["result"][0]["Data"])
|
||||
resultArray.append(resultDict.copy())
|
||||
result = json.dumps(resultArray)
|
||||
elif custom == "modify_config":
|
||||
idx = request.args.get('idx', '')
|
||||
page = request.args.get('page', '')
|
||||
component = request.args.get('component', '')
|
||||
description = request.args.get('description', '')
|
||||
extra = request.args.get('extra', '')
|
||||
writeToConfig(idx, page, component, description, extra)
|
||||
elif custom == 'indexPlugins':
|
||||
result = json.dumps(indexPlugins(request.args))
|
||||
elif custom in apiDict:
|
||||
module = apiDict.get(custom)[0]
|
||||
function = apiDict.get(custom)[1]
|
||||
call = getattr(modules[module], function)
|
||||
result = call(request.args)
|
||||
else:
|
||||
result = queryDomoticz(requestedUrl[1])
|
||||
try:
|
||||
if not is_json(result):
|
||||
result = json.dumps(result)
|
||||
return security.sanitizeJSON(json.loads(result))
|
||||
except:
|
||||
return "No results returned"
|
||||
|
||||
def is_json(myjson):
|
||||
def isJson(myjson):
|
||||
try:
|
||||
json_object = json.loads(str(myjson))
|
||||
except ValueError, e:
|
||||
return False
|
||||
return True
|
||||
|
||||
def queryDomoticz(url):
|
||||
try:
|
||||
r = requests.get('http://' + config["general_settings"]["server"]["url"] + '/json.htm' + url,
|
||||
auth=(config["general_settings"]["server"].get("user"), config["general_settings"]["server"].get("password")), timeout=5.00)
|
||||
except:
|
||||
return
|
||||
return r.text
|
||||
|
||||
def writeToConfig(idx, page, component, description, extra):
|
||||
section = dict(originalCfg[page][component])
|
||||
section[description] = idx
|
||||
originalCfg[page][component] = section
|
||||
originalCfg.write()
|
||||
|
||||
def checkDomoticzStatus(config):
|
||||
domoticzDevices = []
|
||||
domoticzScenes = []
|
||||
try:
|
||||
result = json.loads(queryDomoticz("?type=devices&filter=all"))
|
||||
resultScene = json.loads(queryDomoticz("?type=scenes&filter=all"))
|
||||
except:
|
||||
sys.exit("Domoticz is not reachable.")
|
||||
for device in result["result"]:
|
||||
domoticzDevices.append(device["idx"])
|
||||
if 'result' in resultScene:
|
||||
for device in resultScene["result"]:
|
||||
domoticzScenes.append(device["idx"])
|
||||
configuredDevicesInDomoticz(config, domoticzDevices, domoticzScenes)
|
||||
|
||||
def configuredDevicesInDomoticz(config, domoticzDevices, domoticzScenes):
|
||||
for k, v in config.iteritems():
|
||||
if isinstance(v, dict):
|
||||
configuredDevicesInDomoticz(v, domoticzDevices, domoticzScenes)
|
||||
else:
|
||||
if isinstance(v, int):
|
||||
if v not in domoticzDevices and v not in domoticzScenes:
|
||||
sys.exit("Device and/or scene with IDX {} is not available in Domoticz".format(v))
|
||||
elif isinstance(v, list):
|
||||
if (v[0].isdigit()) and (v[0] not in domoticzDevices and v[0] not in domoticzScenes):
|
||||
sys.exit("Device and/or scene with IDX {} is not available in Domoticz".format(v[0]))
|
||||
|
||||
def getPluginDict():
|
||||
global indexes
|
||||
return indexes
|
||||
|
||||
def setPluginDict(d):
|
||||
global indexes
|
||||
indexes = d
|
||||
|
||||
def getPluginVersion(loc):
|
||||
f = open(loc, 'r').read().split('\n')
|
||||
v = None
|
||||
for l in f:
|
||||
t = l.split('=')
|
||||
if t[0] == '@version':
|
||||
_tmp_v = t[1].split('.')
|
||||
c = 1
|
||||
_version = _tmp_v[0] + '.'
|
||||
while(c < len(_tmp_v)):
|
||||
_version += _tmp_v[c]
|
||||
c += 1
|
||||
return float(_version)
|
||||
|
||||
def indexPlugins(params={}):
|
||||
tmpFolder = 'static/tmp'
|
||||
indexFolderPath = 'static/tmp/pluginsIndex/'
|
||||
docsFolderPath = 'static/docs/'
|
||||
installedPlugins = []
|
||||
staticFolder = ['css/', 'images/', 'fonts/', 'js/']
|
||||
indexes = getPluginDict()
|
||||
pluginParts = ['templates/', 'plugins/']
|
||||
|
||||
if 'action' in params:
|
||||
if not params['action'] == 'getPlugins':
|
||||
try:
|
||||
if not int(params['folid']) in indexes:
|
||||
return "No valid plugin id specified."
|
||||
except:
|
||||
return "Please specify integers only."
|
||||
|
||||
if 'action' in params:
|
||||
if params['action'] == 'getPlugins':
|
||||
folders = filter(lambda x: os.path.isdir(os.path.join(indexFolderPath, x)),
|
||||
os.listdir(indexFolderPath))
|
||||
for i in folders:
|
||||
i = security.sanitizePathBasename(i)
|
||||
if i != '.git':
|
||||
fol = {}
|
||||
fol['id'] = len(indexes)
|
||||
fol['folder'] = i
|
||||
fol['status'] = 'install'
|
||||
for filename in os.listdir('plugins/'):
|
||||
installedPlugins.append(filename)
|
||||
|
||||
for filename in os.listdir(indexFolderPath + i + '/plugins'):
|
||||
if filename in installedPlugins:
|
||||
installed_version = getPluginVersion(docsFolderPath + i + '_readme.md')
|
||||
indexed_version = getPluginVersion(indexFolderPath + i + '/' + docsFolderPath + 'readme.md')
|
||||
if indexed_version > installed_version:
|
||||
fol['update'] = 'yes'
|
||||
else:
|
||||
fol['update'] = 'no'
|
||||
fol['status'] = 'remove'
|
||||
readme = open(indexFolderPath + i + '/' + docsFolderPath + 'readme.md', 'r').read().split('\n')
|
||||
sumList = {}
|
||||
for s in readme:
|
||||
t = s.split('=')
|
||||
if len(t) > 1:
|
||||
fol[t[0].replace('@', '')] = t[1]
|
||||
if not i in (f['folder'] for f in indexes.itervalues()):
|
||||
indexes[len(indexes)] = fol
|
||||
else:
|
||||
for tmp in indexes.itervalues():
|
||||
if i == tmp['folder']:
|
||||
for k in fol:
|
||||
if k != 'id':
|
||||
indexes[tmp['id']][k] = fol[k]
|
||||
setPluginDict(indexes)
|
||||
return indexes
|
||||
elif params['action'] == 'installPlugin':
|
||||
if 'folid' in params:
|
||||
if indexes[int(params['folid'])]['status'] == 'install':
|
||||
src_path = indexFolderPath + indexes[int(params['folid'])]['folder'] + '/'
|
||||
for part in pluginParts:
|
||||
for filename in os.listdir(src_path + part):
|
||||
shutil.copy(src_path + part + filename, part + filename)
|
||||
for f in staticFolder:
|
||||
if os.path.exists(src_path + 'static/' + f):
|
||||
for filename in os.listdir(src_path + '/static/' + f):
|
||||
shutil.copy(src_path + 'static/' + f + filename, 'static/' + f + filename)
|
||||
for filename in os.listdir(src_path + '/' + docsFolderPath):
|
||||
shutil.copy(src_path + '/' + docsFolderPath + filename, docsFolderPath + indexes[int(params['folid'])]['folder'] + '_' + filename)
|
||||
indexes[int(params['folid'])]['status'] = 'remove'
|
||||
global modules
|
||||
modules = loadPlugins()
|
||||
return indexes[int(params['folid'])]['folder'] + ' installed.'
|
||||
else:
|
||||
return "This plugin is already installed."
|
||||
elif params['action'] == 'removePlugin':
|
||||
if 'folid' in params:
|
||||
if indexes[int(params['folid'])]['status'] == 'remove':
|
||||
src_path = indexFolderPath + indexes[int(params['folid'])]['folder'] + '/'
|
||||
for part in pluginParts:
|
||||
for filename in os.listdir(src_path + part):
|
||||
os.remove(part + filename)
|
||||
for f in staticFolder:
|
||||
if os.path.exists(src_path + 'static/' + f):
|
||||
for filename in os.listdir(src_path + 'static/' + f):
|
||||
os.remove('static/' + f + filename)
|
||||
for filename in os.listdir(src_path + '/' + docsFolderPath):
|
||||
shutil.copy(src_path + '/' + docsFolderPath + filename, docsFolderPath + indexes[int(params['folid'])]['folder'] + '_' + filename)
|
||||
indexes[int(params['folid'])]['status'] = 'install'
|
||||
return indexes[int(params['folid'])]['folder'] + ' removed.'
|
||||
else:
|
||||
return "This plugin was already removed."
|
||||
setPluginDict(indexes)
|
||||
else:
|
||||
if not os.path.exists(tmpFolder):
|
||||
os.makedirs(tmpFolder)
|
||||
if not os.path.exists(indexFolderPath):
|
||||
os.makedirs(indexFolderPath)
|
||||
|
||||
if not os.path.isfile(indexFolderPath + 'README.md'):
|
||||
shutil.rmtree(indexFolderPath)
|
||||
try:
|
||||
git.Repo.clone_from("https://github.com/wez3/domoboard-plugins.git", indexFolderPath)
|
||||
except:
|
||||
print 'indexed'
|
||||
else:
|
||||
git.cmd.Git(indexFolderPath).pull("https://github.com/wez3/domoboard-plugins.git")
|
||||
folders = filter(lambda x: os.path.isdir(os.path.join(indexFolderPath, x)),
|
||||
os.listdir(indexFolderPath))
|
||||
return indexPlugins({'action': 'getPlugins'})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/python
|
||||
# Provides all charts functionality
|
||||
|
||||
import json, re, domoticz
|
||||
from flask import request
|
||||
|
||||
def barChart():
|
||||
idxs = request.args.get('idxs', '')
|
||||
idxArray = idxs.split(",")
|
||||
resultArray = []
|
||||
resultDict = {}
|
||||
for i in idxArray:
|
||||
qResults = domoticz.queryDomoticz("?type=devices&rid=" + i)
|
||||
jsonObj = json.loads(qResults)
|
||||
resultDict["y"] = jsonObj["result"][0]["Name"]
|
||||
resultDict["a"] = jsonObj["result"][0]["Data"]
|
||||
resultArray.append(resultDict.copy())
|
||||
result = json.dumps(resultArray)
|
||||
return result
|
||||
|
||||
def donutChart():
|
||||
idxs = request.args.get('idxs', '')
|
||||
idxArray = idxs.split(",")
|
||||
resultArray = []
|
||||
resultDict = {}
|
||||
for i in idxArray:
|
||||
qResults = domoticz.queryDomoticz("?type=devices&rid=" + i)
|
||||
jsonObj = json.loads(qResults)
|
||||
resultDict["label"] = jsonObj["result"][0]["Name"]
|
||||
resultDict["value"] = re.findall("\d+\.?\d+", jsonObj["result"][0]["Data"])
|
||||
resultArray.append(resultDict.copy())
|
||||
result = json.dumps(resultArray)
|
||||
return result
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/python
|
||||
# This file contains all Domoticz related Python functions
|
||||
|
||||
import requests, json, sys
|
||||
import api
|
||||
|
||||
def queryDomoticz(url):
|
||||
config = api.getConfig()
|
||||
try:
|
||||
r = requests.get('http://' + config["general_settings"]["server"]["url"] + '/json.htm' + url,
|
||||
auth=(config["general_settings"]["server"].get("user"), config["general_settings"]["server"].get("password")), timeout=5.00)
|
||||
except:
|
||||
return {}
|
||||
return r.text
|
||||
|
||||
def checkDomoticzStatus(config):
|
||||
domoticzDevices = []
|
||||
domoticzScenes = []
|
||||
try:
|
||||
result = json.loads(queryDomoticz("?type=devices&filter=all"))
|
||||
resultScene = json.loads(queryDomoticz("?type=scenes&filter=all"))
|
||||
except:
|
||||
sys.exit("Domoticz is not reachable.")
|
||||
for device in result["result"]:
|
||||
domoticzDevices.append(device["idx"])
|
||||
if 'result' in resultScene:
|
||||
for device in resultScene["result"]:
|
||||
domoticzScenes.append(device["idx"])
|
||||
configuredDevicesInDomoticz(config, domoticzDevices, domoticzScenes)
|
||||
|
||||
def configuredDevicesInDomoticz(config, domoticzDevices, domoticzScenes):
|
||||
for k, v in config.iteritems():
|
||||
if isinstance(v, dict):
|
||||
configuredDevicesInDomoticz(v, domoticzDevices, domoticzScenes)
|
||||
else:
|
||||
if isinstance(v, int):
|
||||
if v not in domoticzDevices and v not in domoticzScenes:
|
||||
sys.exit("Device and/or scene with IDX {} is not available in Domoticz".format(v))
|
||||
elif isinstance(v, list):
|
||||
if (v[0].isdigit()) and (v[0] not in domoticzDevices and v[0] not in domoticzScenes):
|
||||
sys.exit("Device and/or scene with IDX {} is not available in Domoticz".format(v[0]))
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
#!/usr/bin/python
|
||||
# This file contains the functions regarding the plugin manager.
|
||||
|
||||
import git, shutil, os, imp, sys
|
||||
import security, api
|
||||
import re
|
||||
|
||||
indexes = {}
|
||||
|
||||
def loadPlugins():
|
||||
plugin = {}
|
||||
plugin_dir = os.getcwd() + '/plugins/'
|
||||
for i in os.listdir(plugin_dir):
|
||||
if not i == '__init__.py' and i.endswith('.py'):
|
||||
name = i.replace('.py', '')
|
||||
try:
|
||||
plugin[name] = imp.load_source(name, plugin_dir + i)
|
||||
plugin[name].init()
|
||||
except ImportError as msg:
|
||||
moduleName = str(msg).split(' ')[len(str(msg).split(' ')) -1]
|
||||
sys.exit("Error occured during loading imports for the plugin {}: {}. Install it with 'easy_install {}' or 'pip install {}'".format(name, msg, moduleName , moduleName))
|
||||
return plugin
|
||||
|
||||
def getPluginDict():
|
||||
global indexes
|
||||
return indexes
|
||||
|
||||
def setPluginDict(d):
|
||||
global indexes
|
||||
indexes = d
|
||||
|
||||
def getPluginVersion(loc):
|
||||
f = open(loc, 'r').read().split('@')
|
||||
v = None
|
||||
for l in f:
|
||||
t = l.split('=')
|
||||
if t[0].lower() == 'version':
|
||||
_tmp_v = t[1].split('.')
|
||||
c = 1
|
||||
_version = _tmp_v[0] + '.'
|
||||
while(c < len(_tmp_v)):
|
||||
_version += _tmp_v[c]
|
||||
c += 1
|
||||
return float(_version)
|
||||
|
||||
def indexPlugins(params={}):
|
||||
tmpFolder = 'plugins/index'
|
||||
indexFolderPath = 'plugins/index/'
|
||||
docsFolderPath = 'static/docs/'
|
||||
installedPlugins = []
|
||||
staticFolder = ['css/', 'images/', 'fonts/', 'js/']
|
||||
indexes = getPluginDict()
|
||||
pluginParts = ['templates/', 'plugins/']
|
||||
|
||||
if 'action' in params:
|
||||
if not params['action'] == 'getPlugins':
|
||||
try:
|
||||
if not int(params['folid']) in indexes:
|
||||
return "No valid plugin id specified."
|
||||
except:
|
||||
return "Please specify integers only."
|
||||
|
||||
if 'action' in params:
|
||||
if params['action'] == 'getPlugins':
|
||||
folders = filter(lambda x: os.path.isdir(os.path.join(indexFolderPath, x)),
|
||||
os.listdir(indexFolderPath))
|
||||
for i in folders:
|
||||
i = security.sanitizePathBasename(i)
|
||||
if i != '.git':
|
||||
fol = {}
|
||||
fol['id'] = len(indexes)
|
||||
fol['folder'] = i
|
||||
fol['status'] = 'install'
|
||||
for filename in os.listdir('templates/'):
|
||||
installedPlugins.append(filename)
|
||||
|
||||
for filename in os.listdir(indexFolderPath + i + '/templates'):
|
||||
if filename in installedPlugins:
|
||||
installed_version = getPluginVersion(docsFolderPath + i + '_readme.md')
|
||||
indexed_version = getPluginVersion(indexFolderPath + i + '/' + docsFolderPath + 'readme.md')
|
||||
if indexed_version > installed_version:
|
||||
fol['update'] = 'yes'
|
||||
else:
|
||||
fol['update'] = 'no'
|
||||
fol['status'] = 'remove'
|
||||
readme = re.split('@', open(indexFolderPath + i + '/' + docsFolderPath + 'readme.md', 'r').read())#.split('@')
|
||||
|
||||
sumList = {}
|
||||
for s in readme:
|
||||
if re.search('\w+=', str(s)):
|
||||
_check = re.search('\w+=', str(s)).group().replace('=', '')
|
||||
_text = re.sub('\w+=', '', s)
|
||||
if _check == 'summary' or _check == 'description':
|
||||
_text = re.sub('\n', '<br>', _text)
|
||||
fol[_check] = _text
|
||||
|
||||
if not i in (f['folder'] for f in indexes.itervalues()):
|
||||
indexes[len(indexes)] = fol
|
||||
else:
|
||||
for tmp in indexes.itervalues():
|
||||
if i == tmp['folder']:
|
||||
for k in fol:
|
||||
if k != 'id':
|
||||
indexes[tmp['id']][k] = fol[k]
|
||||
setPluginDict(indexes)
|
||||
return indexes
|
||||
elif params['action'] == 'installPlugin':
|
||||
if 'folid' in params:
|
||||
if indexes[int(params['folid'])]['status'] == 'install':
|
||||
src_path = indexFolderPath + indexes[int(params['folid'])]['folder'] + '/'
|
||||
for part in pluginParts:
|
||||
for filename in os.listdir(src_path + part):
|
||||
shutil.copy(src_path + part + filename, part + filename)
|
||||
for f in staticFolder:
|
||||
if os.path.exists(src_path + 'static/' + f):
|
||||
for filename in os.listdir(src_path + '/static/' + f):
|
||||
shutil.copy(src_path + 'static/' + f + filename, 'static/' + f + filename)
|
||||
for filename in os.listdir(src_path + '/' + docsFolderPath):
|
||||
shutil.copy(src_path + '/' + docsFolderPath + filename, docsFolderPath + indexes[int(params['folid'])]['folder'] + '_' + filename)
|
||||
indexes[int(params['folid'])]['status'] = 'remove'
|
||||
global modules
|
||||
modules = loadPlugins()
|
||||
api.setModules(modules)
|
||||
return indexes[int(params['folid'])]['folder'] + ' installed.'
|
||||
else:
|
||||
return "This plugin is already installed."
|
||||
elif params['action'] == 'removePlugin':
|
||||
if 'folid' in params:
|
||||
if indexes[int(params['folid'])]['status'] == 'remove':
|
||||
src_path = indexFolderPath + indexes[int(params['folid'])]['folder'] + '/'
|
||||
for part in pluginParts:
|
||||
for filename in os.listdir(src_path + part):
|
||||
os.remove(part + filename)
|
||||
for f in staticFolder:
|
||||
if os.path.exists(src_path + 'static/' + f):
|
||||
for filename in os.listdir(src_path + 'static/' + f):
|
||||
os.remove('static/' + f + filename)
|
||||
for filename in os.listdir(src_path + '/' + docsFolderPath):
|
||||
shutil.copy(src_path + '/' + docsFolderPath + filename, docsFolderPath + indexes[int(params['folid'])]['folder'] + '_' + filename)
|
||||
indexes[int(params['folid'])]['status'] = 'install'
|
||||
return indexes[int(params['folid'])]['folder'] + ' removed.'
|
||||
else:
|
||||
return "This plugin was already removed."
|
||||
setPluginDict(indexes)
|
||||
else:
|
||||
if not os.path.exists(tmpFolder):
|
||||
os.makedirs(tmpFolder)
|
||||
if not os.path.exists(indexFolderPath):
|
||||
os.makedirs(indexFolderPath)
|
||||
|
||||
if not os.path.isfile(indexFolderPath + 'README.md'):
|
||||
shutil.rmtree(indexFolderPath)
|
||||
try:
|
||||
git.Repo.clone_from("https://github.com/wez3/domoboard-plugins.git", indexFolderPath)
|
||||
except:
|
||||
print 'indexed'
|
||||
else:
|
||||
git.cmd.Git(indexFolderPath).pull("https://github.com/wez3/domoboard-plugins.git")
|
||||
folders = filter(lambda x: os.path.isdir(os.path.join(indexFolderPath, x)),
|
||||
os.listdir(indexFolderPath))
|
||||
return indexPlugins({'action': 'getPlugins'})
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/python
|
||||
# This file contains the functions used for web based configuration of domoboard
|
||||
|
||||
import git
|
||||
import api
|
||||
from flask import request
|
||||
|
||||
def writeToConfig(idx, page, component, description, extra):
|
||||
originalCfg = api.getOriginalConfig()
|
||||
section = dict(originalCfg[page][component])
|
||||
section[description] = idx
|
||||
originalCfg[page][component] = section
|
||||
originalCfg.write()
|
||||
|
||||
def getVersion():
|
||||
f = open('VERSION.md', 'r')
|
||||
version = f.read().rstrip()
|
||||
f.close()
|
||||
return version
|
||||
|
||||
def performUpgrade():
|
||||
git.cmd.Git('.').pull()
|
||||
return "Upgrade completed."
|
||||
|
||||
def getCurrentBranch():
|
||||
repo = git.Repo('.')
|
||||
branch = repo.active_branch
|
||||
return branch.name
|
||||
34
server.py
34
server.py
|
|
@ -6,7 +6,9 @@ from collections import OrderedDict
|
|||
import argparse, socket, re
|
||||
import hashlib, configobj, json, sys, os
|
||||
import modules.api as api
|
||||
import modules.domoticz as domoticz
|
||||
import modules.security as security
|
||||
import modules.webconfig as webconfig
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
|
@ -25,9 +27,9 @@ def init():
|
|||
def generatePage():
|
||||
requestedRoute = str(request.url_rule)[1:]
|
||||
if configValueExists(requestedRoute):
|
||||
blockValues = {}
|
||||
blockValues = OrderedDict()
|
||||
blockArray = []
|
||||
configValues = {}
|
||||
configValues = OrderedDict()
|
||||
configValues["navbar"] = config["navbar"]["menu"]
|
||||
configValues["server_location"] = config["general_settings"]["server"].get("url")
|
||||
configValues["flask_server_location"] = config["general_settings"]["server"].get("flask_url")
|
||||
|
|
@ -45,7 +47,10 @@ def generatePage():
|
|||
return render_template('index.html',
|
||||
configValues = configValues,
|
||||
blockArray = blockArray,
|
||||
_csrf_token = session['_csrf_token'])
|
||||
_csrf_token = session['_csrf_token'],
|
||||
version = webconfig.getVersion(),
|
||||
branch = webconfig.getCurrentBranch(),
|
||||
debug = app.debug)
|
||||
else:
|
||||
abort(404)
|
||||
|
||||
|
|
@ -55,18 +60,19 @@ def index():
|
|||
|
||||
@login_required()
|
||||
def retrieveValue(page, component):
|
||||
dict = {}
|
||||
dict = OrderedDict()
|
||||
try:
|
||||
match = re.search("^(.+)\[(.+)\]$", component)
|
||||
if not match:
|
||||
for k, v in config[page][component].iteritems():
|
||||
v = strToList(v)
|
||||
dict[k] = v
|
||||
l = [None]
|
||||
l.extend(strToList(v))
|
||||
dict[k] = l
|
||||
else:
|
||||
for sk, sv in config[page][match.group(1)][match.group(2)].iteritems():
|
||||
sv = strToList(sv)
|
||||
sv.append(match.group(2))
|
||||
dict[sk] = sv
|
||||
l = [match.group(2)]
|
||||
l.extend(strToList(sv))
|
||||
dict[sk] = l
|
||||
except:
|
||||
dict = {}
|
||||
return dict
|
||||
|
|
@ -86,7 +92,7 @@ def login_form():
|
|||
if g.users[username].authenticate(request.form['password']):
|
||||
security.generateCsrfToken()
|
||||
return redirect(url_for('dashboard'))
|
||||
return render_template('login.html')
|
||||
return render_template('login.html', failed = "Login failed")
|
||||
return render_template('login.html')
|
||||
|
||||
@app.errorhandler(404)
|
||||
|
|
@ -109,7 +115,7 @@ def configValueExists(value):
|
|||
|
||||
def validateConfigFormat(config):
|
||||
requiredSettings = {"general_settings/server": ["url", "flask_url", "user", "password", "secret_key"],
|
||||
"general_settings/domoboard": ["time"],
|
||||
"general_settings/domoboard": ["time", "date"],
|
||||
"navbar/menu": [None] }
|
||||
for sect, fields in requiredSettings.iteritems():
|
||||
section = sect.split('/')
|
||||
|
|
@ -150,7 +156,7 @@ if __name__ == '__main__':
|
|||
api.setConfig(config, unsanitizedConfig)
|
||||
api.init()
|
||||
validateConfigFormat(config)
|
||||
api.checkDomoticzStatus(config)
|
||||
domoticz.checkDomoticzStatus(config)
|
||||
server_location = config["general_settings"]["server"]["url"]
|
||||
flask_server_location = config["general_settings"]["server"]["flask_url"]
|
||||
auth = Auth(app, login_url_name='login_form')
|
||||
|
|
@ -166,6 +172,6 @@ if __name__ == '__main__':
|
|||
app.add_url_rule('/logout/', 'logout', logout_view, methods=['GET'])
|
||||
app.add_url_rule('/api', 'api', api.gateway, methods=['POST'])
|
||||
try:
|
||||
app.run(host=flask_server_location.split(":")[0],port=int(flask_server_location.split(":")[1]),threaded=True, extra_files=watchfiles, debug=args.debug)
|
||||
app.run(host=flask_server_location.split(":")[0],port=int(flask_server_location.split(":")[1]), threaded=True, extra_files=watchfiles, debug=args.debug)
|
||||
except socket.error, exc:
|
||||
sys.exit("Error when starting the Flask server: %s" % exc)
|
||||
sys.exit("Error when starting the Flask server: {}".format(exc))
|
||||
|
|
|
|||
|
|
@ -152,9 +152,6 @@
|
|||
}
|
||||
.slider-selection {
|
||||
position: absolute;
|
||||
background-image: -webkit-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%);
|
||||
background-image: -o-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%);
|
||||
background-image: linear-gradient(to bottom, #f9f9f9 0%, #f5f5f5 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#fff5f5f5', GradientType=0);
|
||||
-webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ body.nav-sm .main_container .top_nav {
|
|||
}
|
||||
|
||||
body.nav-sm .nav.side-menu li a {
|
||||
text-align: left !important;
|
||||
text-align: center !important;
|
||||
font-weight: 400;
|
||||
font-size: 13px;
|
||||
padding: 10px 5px;
|
||||
|
|
@ -467,7 +467,7 @@ table.no-margin .progress {
|
|||
|
||||
@media(max-width:768px) {
|
||||
.tile_stats_count .count {
|
||||
font-size: 30px !important;
|
||||
font-size: 5.5vw !important;
|
||||
}
|
||||
.tile_stats_count .right span {
|
||||
font-size: 12px;
|
||||
|
|
@ -1961,8 +1961,8 @@ span.right {
|
|||
}
|
||||
|
||||
.tile_stats_count .count {
|
||||
font-size: 40px;
|
||||
line-height: 47px;
|
||||
font-size: 2.5vw;
|
||||
/* line-height: 47px;*/
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
|
|
@ -2292,6 +2292,9 @@ button,
|
|||
margin-bottom: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.modal-footer .btn+.btn {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.btn-group-vertical .btn,
|
||||
.btn-group .btn {
|
||||
|
|
@ -6383,12 +6386,17 @@ ul.notifications {
|
|||
overflow: visible;
|
||||
}
|
||||
#time-part {
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
#date-part {
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
#version_div {
|
||||
float: right;
|
||||
margin-top:15px;
|
||||
margin-right:10px;
|
||||
}
|
||||
.show_date {
|
||||
display: inline-block;
|
||||
|
|
@ -6396,3 +6404,20 @@ ul.notifications {
|
|||
.hide_date {
|
||||
display: None;
|
||||
}
|
||||
.show_update {
|
||||
display: inline-block;
|
||||
}
|
||||
.hide_update {
|
||||
display: None;
|
||||
}
|
||||
|
||||
.slider_on {
|
||||
background-image: -webkit-linear-gradient(top, #f9f9f9 0%, green 100%);
|
||||
background-image: -o-linear-gradient(top, #f9f9f9 0%, green 100%);
|
||||
background-image: linear-gradient(to bottom, #f9f9f9 0%, green 100%);
|
||||
}
|
||||
.slider_off {
|
||||
background-image: -webkit-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%);
|
||||
background-image: -o-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%);
|
||||
background-image: linear-gradient(to bottom, #f9f9f9 0%, #f5f5f5 100%);
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
|
|
@ -410,8 +410,9 @@
|
|||
sliderTrackLow.className = "slider-track-low";
|
||||
|
||||
sliderTrackSelection = document.createElement("div");
|
||||
sliderTrackSelection.className = "slider-selection";
|
||||
|
||||
//sliderTrackSelection.className = "slider-selection";
|
||||
sliderTrackSelection.id = this.options.id + "_track";
|
||||
sliderTrackSelection.className = "slider-selection slider_" + this.options.state
|
||||
sliderTrackHigh = document.createElement("div");
|
||||
sliderTrackHigh.className = "slider-track-high";
|
||||
|
||||
|
|
@ -766,7 +767,8 @@
|
|||
scale: 'linear',
|
||||
focus: false,
|
||||
tooltip_position: null,
|
||||
labelledby: null
|
||||
labelledby: null,
|
||||
state: 'off'
|
||||
},
|
||||
|
||||
getElement: function() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
* Original author of the bootstrap template is Colorlib.
|
||||
*/
|
||||
|
||||
/** ****** left menu *********************** **/
|
||||
|
|
@ -332,4 +330,4 @@ if (typeof NProgress != 'undefined') {
|
|||
NProgress.done();
|
||||
});
|
||||
}
|
||||
/** ****** NProgress *********************** **/
|
||||
/** ****** NProgress *********************** **/
|
||||
|
|
|
|||
|
|
@ -22,6 +22,47 @@ function changeSwitch(checkboxElem, idx) {
|
|||
}
|
||||
}
|
||||
|
||||
// switchSelector
|
||||
function switchSelector(idx, lvl, bid) {
|
||||
var old_bid = bid.replace(new RegExp(lvl + '$'), '');
|
||||
url = '/api?type=devices&rid=' + idx;
|
||||
requestAPI(flask_server + url, function(d) {
|
||||
r = JSON.parse(d);
|
||||
last_active = r['result'][0]['Level'];
|
||||
if (last_active != 0) {
|
||||
last_active = last_active + 0;
|
||||
}
|
||||
$('#' + old_bid + last_active).removeClass('btn-primary');
|
||||
$('#' + bid).addClass('btn-primary');
|
||||
requestAPI(flask_server + '/api?type=command¶m=switchlight&idx=' + idx + '&switchcmd=Set%20Level&level=' + lvl + '&passcode=');
|
||||
});
|
||||
}
|
||||
// Dimmer functions
|
||||
function changeDimmer(checkboxElem, idx) {
|
||||
var chkurl = "/api?type=devices&rid=" + idx;
|
||||
requestAPI(flask_server + chkurl, function(d) {
|
||||
_json = JSON.parse(d);
|
||||
if (_json['result'][0]['Data'] != 'Off') {
|
||||
requestAPI(flask_server + "/api?type=command¶m=switchlight&idx=" + idx + "&switchcmd=Off&level=0");
|
||||
} else {
|
||||
requestAPI(flask_server + "/api?type=command¶m=switchlight&idx=" + idx + "&switchcmd=On&level=0");
|
||||
}
|
||||
setDimmerState(checkboxElem, idx);
|
||||
});
|
||||
}
|
||||
|
||||
function setDimmerState(id, idx) {
|
||||
var url = "/api?type=devices&rid=" + idx;
|
||||
requestAPI(flask_server + url, function(d) {
|
||||
_json = JSON.parse(d);
|
||||
if (_json['result'][0]['Data'] != 'Off') {
|
||||
$('#' + id).css({'background-image': '-webkit-linear-gradient(top, #f9f9f9 0%, green 100%)', 'background-image': '-o-linear-gradient(top, #f9f9f9 0%, green 100%)', 'background-image': 'linear-gradient(to bottom, #f9f9f9 0%, green 100%)'});
|
||||
} else {
|
||||
$('#' + id).css({'background-image': '-webkit-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%)', 'background-image': '-o-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%)', 'background-image': 'linear-gradient(to bottom, #f9f9f9 0%, #f5f5f5 100%)'});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Switch functions
|
||||
function changePush(idx, action) {
|
||||
if (action == 'on') {
|
||||
|
|
@ -57,7 +98,7 @@ function refreshSwitches(updateSwitches, block) {
|
|||
}
|
||||
|
||||
// Top tiles functions
|
||||
function refreshTopTiles(updateDivs, block, tilesPreviousArray) {
|
||||
function refreshTopTiles(updateDivs, block, tilesPreviousArray, updateDivsTypeArray, updateDivsUnitsArray) {
|
||||
if (tilesPreviousArray.length == 0) {
|
||||
for(var i = 0; i < updateDivs.length; i++){
|
||||
tilesPreviousArray.push(-1);
|
||||
|
|
@ -69,32 +110,47 @@ function refreshTopTiles(updateDivs, block, tilesPreviousArray) {
|
|||
requestAPI(url, function(d) {
|
||||
var obj = JSON.parse(d);
|
||||
if (obj.result != undefined) {
|
||||
var data = obj.result[0].Data;
|
||||
var data = obj.result[0][updateDivsTypeArray[i]].toString();
|
||||
} else {
|
||||
var data = "-";
|
||||
}
|
||||
var re = /(-?\d+\.?\d*) (.+)/;
|
||||
//var re = /(-?\d+\.?\d*) (.+)/; -- old regex didn't found an temp value
|
||||
var re = /(-?\d+[\.*]?\d*)(\s*.*)/;
|
||||
tilesArray = re.exec(data);
|
||||
|
||||
if (tilesArray != null) {
|
||||
if (tilesArray[1] < tilesPreviousArray[i]) {
|
||||
$("#" + block + divID).html(tilesArray[1] + "<font size='3'>" + tilesArray[2] + " <i class='fa fa-caret-down fa-lg' style='color:red'></font>");
|
||||
if (updateDivsUnitsArray[i]) {
|
||||
tilesArray[2] = updateDivsUnitsArray[i];
|
||||
}
|
||||
if (parseFloat(tilesArray[1]) < parseFloat(tilesPreviousArray[i])) {
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i]).html(tilesArray[1] + "<font size=2vw>" + tilesArray[2] + "</font>");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i] + "_arrow").removeClass("green");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i] + "_arrow").addClass("red");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i] + "_arrow").removeClass("fa-caret-up");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i] + "_arrow").addClass("fa-caret-down");
|
||||
tilesPreviousArray[i] = tilesArray[1];
|
||||
} else if (tilesArray[1] > tilesPreviousArray[i]) {
|
||||
$("#" + block + divID).html(tilesArray[1] + "<font size='3'>" + tilesArray[2] + " <i class='fa fa-caret-up fa-lg' style='color:green'></font>");
|
||||
} else if (parseFloat(tilesArray[1]) > parseFloat(tilesPreviousArray[i])) {
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i]).html(tilesArray[1] + "<font size=2vw>" + tilesArray[2] + "</font>");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i] + "_arrow").removeClass("red");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i] + "_arrow").addClass("green");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i] + "_arrow").removeClass("fa-caret-down");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i] + "_arrow").addClass("fa-caret-up");
|
||||
tilesPreviousArray[i] = tilesArray[1];
|
||||
}
|
||||
} else {
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i]).html(tilesArray[1] + "<font size=2vw>" + tilesArray[2] + "</font>");
|
||||
}
|
||||
} else {
|
||||
$("#" + block + divID).html(data);
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i]).html(data);
|
||||
}
|
||||
if(data == "On") {
|
||||
$("#" + block + divID).removeClass("red");
|
||||
$("#" + block + divID).addClass("green");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i]).removeClass("red");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i]).addClass("green");
|
||||
} else if(data == "Off") {
|
||||
$("#" + block + divID).removeClass("green");
|
||||
$("#" + block + divID).addClass("red");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i]).removeClass("green");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i]).addClass("red");
|
||||
} else {
|
||||
$("#" + block + divID).removeClass("green");
|
||||
$("#" + block + divID).removeClass("red");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i]).removeClass("green");
|
||||
$("#" + block + divID + "_" + updateDivsTypeArray[i]).removeClass("red");
|
||||
}
|
||||
});
|
||||
i = i++;
|
||||
|
|
@ -137,9 +193,25 @@ function dimmerSlider(updateDimmers, block) {
|
|||
url = "/api?type=devices&rid=" + dimmerID;
|
||||
requestAPI(url, function(d) {
|
||||
var percentage = JSON.parse(d).result[0].Level;
|
||||
$('#dimmer_' + dimmerID + "_block_" + block).slider({min:0, max:100, value: percentage}).on('slideStop', function(ev) { changeDimmerSlider($(this).attr('id'), ev.value) } ).data('slider');
|
||||
$('#dimmer_' + dimmerID + "_block_" + block).slider().on('slideStop', function(ev) { changeDimmerSlider($(this).attr('id'), ev.value) } ).data('slider');
|
||||
});
|
||||
$('#dimmer_' + dimmerID + "_block_" + block).slider({min:0, max:100, value: percentage}).on('slideStop', function(ev) {
|
||||
setDimmerState('dim_' + dimmerID + "_block_" + block + "_track", dimmerID);
|
||||
changeDimmerSlider($(this).attr('id'), ev.value)
|
||||
} ).data('slider');
|
||||
setDimmerState('dim_' + dimmerID + "_block_" + block + "_track", dimmerID);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setpointSlider(updateSetpoints, block) {
|
||||
$.each(updateSetpoints, function(i, setpoint) {
|
||||
url = "/api?type=devices&rid=" + setpoint[0];
|
||||
requestAPI(url, function(d) {
|
||||
var percentage = parseFloat(JSON.parse(d).result[0].Data);
|
||||
$('#setpoint_slider' + setpoint[0] + "_block_" + block).slider({min:parseInt(setpoint[1]), max:parseInt(setpoint[2]), value: parseFloat(percentage)}).on('slideStop', function(ev) {
|
||||
changeSetpoint(setpoint[0], parseFloat(ev.value));
|
||||
} ).data('slider');
|
||||
$('#stpnt_' + setpoint[0] + "_block_" + block + '_track').css({'background-image': '-webkit-linear-gradient(top, #f9f9f9 0%, red 100%)', 'background-image': '-o-linear-gradient(top, #f9f9f9 0%, red 100%)', 'background-image': 'linear-gradient(to bottom, #f9f9f9 0%, red 100%)'});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -169,10 +241,15 @@ function redrawLineChart(sensor, idx, range, block) {
|
|||
});
|
||||
}
|
||||
|
||||
function redrawBarChart(idxs, block) {
|
||||
function redrawBarChart(idxs, block, barChartElementsNames) {
|
||||
var url = "/api?custom=bar_chart&idxs=" + idxs.join();
|
||||
var i = 0;
|
||||
requestAPI(url, function(d){
|
||||
var data = JSON.parse(d);
|
||||
for (var key in data) {
|
||||
data[key]["l"] = barChartElementsNames[i];
|
||||
i++;
|
||||
}
|
||||
block.setData(data);
|
||||
});
|
||||
}
|
||||
|
|
@ -278,9 +355,6 @@ function modifyConfigButtonClicked(id) {
|
|||
|
||||
// Setpoint functions
|
||||
function changeSetpoint(idx, val) {
|
||||
if (val.split('.')[1] == '0'){
|
||||
val = val.split('.')[0];
|
||||
}
|
||||
requestAPI(flask_server + "/api?type=command¶m=setsetpoint&idx=" + idx + "&setpoint=" + val);
|
||||
}
|
||||
|
||||
|
|
@ -341,3 +415,85 @@ function changeDown(idx, block) {
|
|||
changeSetpoint(idx, newVal);
|
||||
}, 400);
|
||||
}
|
||||
|
||||
// Update functions
|
||||
function performUpgrade() {
|
||||
requestAPI('/api?custom=performUpgrade');
|
||||
$( "#version_div" ).removeClass("show_update");
|
||||
$( "#version_div" ).addClass("hide_update");
|
||||
$( "#updateView_available" ).removeClass("show_update");
|
||||
$( "#updateView_available" ).addClass("hide_update");
|
||||
$( "#updateView_not_available" ).removeClass("hide_update");
|
||||
$( "#updateView_not_available" ).addClass("show_update");
|
||||
}
|
||||
|
||||
function checkVersion(branch) {
|
||||
$.ajax({
|
||||
url: "https://domoboard.nl/version.md",
|
||||
cache: false,
|
||||
success: function( data ) {
|
||||
if (branch == "master") {
|
||||
dataFloat = data.split(",")[0];
|
||||
} else {
|
||||
dataFloat = data.split(",")[1];
|
||||
}
|
||||
var compare = versionCompare(dataFloat, version);
|
||||
if (compare == 1) {
|
||||
document.getElementById('curver').innerHTML = version;
|
||||
document.getElementById('newver').innerHTML = dataFloat;
|
||||
$( "#version_div" ).removeClass("hide_update");
|
||||
$( "#version_div" ).addClass("show_update");
|
||||
}
|
||||
},
|
||||
async:true
|
||||
});
|
||||
}
|
||||
|
||||
function checkVersionSettings(branch) {
|
||||
$.ajax({
|
||||
url: "https://domoboard.nl/version.md",
|
||||
cache: false,
|
||||
success: function( data ) {
|
||||
if (branch == "master") {
|
||||
dataFloat = data.split(",")[0];
|
||||
} else {
|
||||
dataFloat = data.split(",")[1];
|
||||
}
|
||||
var compare = versionCompare(dataFloat, version);
|
||||
if (compare == 1) {
|
||||
$( "#updateView_available" ).removeClass("hide_update");
|
||||
$( "#updateView_available" ).addClass("show_update");
|
||||
document.getElementById('curver_settings').innerHTML = version;
|
||||
document.getElementById('newver_settings').innerHTML = dataFloat;
|
||||
} else {
|
||||
$( "#updateView_not_available" ).removeClass("hide_update");
|
||||
$( "#updateView_not_available" ).addClass("show_update");
|
||||
}
|
||||
},
|
||||
async:true
|
||||
});
|
||||
}
|
||||
|
||||
function versionCompare(a, b) {
|
||||
if (a === b) {
|
||||
return 0;
|
||||
}
|
||||
var a_components = a.split(".");
|
||||
var b_components = b.split(".");
|
||||
var len = Math.min(a_components.length, b_components.length);
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (parseInt(a_components[i]) > parseInt(b_components[i])) {
|
||||
return 1;
|
||||
}
|
||||
if (parseInt(a_components[i]) < parseInt(b_components[i])) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (a_components.length > b_components.length) {
|
||||
return 1;
|
||||
}
|
||||
if (a_components.length < b_components.length) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -602,7 +602,6 @@ if (period == "day") {
|
|||
var minValue = 10000000;
|
||||
|
||||
$.each(data.result, function (i, item) {
|
||||
console.log(item)
|
||||
datatable1.push([GetDateFromString(item.d), parseFloat(item.v_max)]);
|
||||
datatable2.push([GetDateFromString(item.d), parseFloat(item.v_min)]);
|
||||
if (typeof item.v_avg != 'undefined') {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,13 +0,0 @@
|
|||
// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
|
||||
require('../../js/transition.js')
|
||||
require('../../js/alert.js')
|
||||
require('../../js/button.js')
|
||||
require('../../js/carousel.js')
|
||||
require('../../js/collapse.js')
|
||||
require('../../js/dropdown.js')
|
||||
require('../../js/modal.js')
|
||||
require('../../js/tooltip.js')
|
||||
require('../../js/popover.js')
|
||||
require('../../js/scrollspy.js')
|
||||
require('../../js/tab.js')
|
||||
require('../../js/affix.js')
|
||||
|
|
@ -27,9 +27,9 @@ var area_chart_block_{{count}} = Morris.Area({
|
|||
|
||||
$(document).ready(function() {
|
||||
{% for k, v in blockArray[count]["area_charts"].iteritems() %}
|
||||
redrawAreaChart("{{v[2]}}",{{v[0]}},"{{v[1]}}", area_chart_block_{{count}});
|
||||
redrawAreaChart("{{v[3]}}",{{v[1]}},"{{v[2]}}", area_chart_block_{{count}});
|
||||
$("div#title_block_{{count}} h2").html("{{k}}");
|
||||
setInterval(redrawAreaChart,9000,"{{v[2]}}",{{v[0]}},"{{v[1]}}", area_chart_block_{{count}});
|
||||
setInterval(redrawAreaChart,9000,"{{v[3]}}",{{v[1]}},"{{v[2]}}", area_chart_block_{{count}});
|
||||
});
|
||||
{% endfor %}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -15,22 +15,27 @@
|
|||
</div>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
|
||||
var bar_chart_block_{{count}} = Morris.Bar({
|
||||
element: 'morris-bar-chart-{{count}}',
|
||||
data: [],
|
||||
xkey: 'y',
|
||||
ykeys: ['a'],
|
||||
labels: ['y'],
|
||||
smooth: true,
|
||||
resize: true
|
||||
});
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
var barChartElements=[];
|
||||
var barChartElementsNames=[];
|
||||
|
||||
{% for k, v in blockArray[count]["bar_charts"].iteritems() %}
|
||||
barChartElements.push("{{v[0]}}");
|
||||
barChartElements.push("{{v[1]}}");
|
||||
barChartElementsNames.push("{{k}}");
|
||||
{% endfor %}
|
||||
redrawBarChart(barChartElements, bar_chart_block_{{count}});
|
||||
setInterval(redrawBarChart,9000,barChartElements,bar_chart_block_{{count}});
|
||||
var bar_chart_block_{{count}} = Morris.Bar({
|
||||
element: 'morris-bar-chart-{{count}}',
|
||||
data: [],
|
||||
xkey: 'l',
|
||||
ykeys: ['a'],
|
||||
labels: ['y'],
|
||||
smooth: true,
|
||||
resize: true
|
||||
});
|
||||
|
||||
redrawBarChart(barChartElements, bar_chart_block_{{count}}, barChartElementsNames);
|
||||
setInterval(redrawBarChart,9000,barChartElements,bar_chart_block_{{count}}, barChartElementsNames);
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -11,15 +11,23 @@
|
|||
<div style=";overflow: hidden">
|
||||
<br>
|
||||
{% for k, v in blockArray[count]["camera"].iteritems() %}
|
||||
{% if v[1] %}
|
||||
<script> $('#s_title_{{ count }}').html("{{ v[1] }}");</script>
|
||||
{% if v[0] %}
|
||||
<script> $('#s_title_{{ count }}').html("{{ v[0] }}");</script>
|
||||
{% endif %}
|
||||
<form class="form-horizontal form-label-left" style="width: 80%; height: 80%; ">
|
||||
<div class="form-group" style="">
|
||||
<img id="cam_{{ count }}" style="-webkit-user-select: none; width: 100%; height: 100%; " src="{{v[0]|replace('&', '&')}}" >
|
||||
<div id="cam_body_{{ count }}" class="form-group" style="">
|
||||
</div>
|
||||
</form>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
{% for k, v in blockArray[count]["camera"].iteritems() %}
|
||||
if ("{{v[1]}}".split(':')[0] == 'rtsp') {
|
||||
$('#cam_body_{{ count }}').append('<object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" codebase="http://download.videolan.org/pub/videolan/vlc/last/win32/axvlc.cab" id="vlc" name="vlc" class="vlcPlayer" events="True"> <param name="Src" value="{{v[1]}}" /> <!-- ie --> <param name="ShowDisplay" value="True" /> <param name="AutoLoop" value="True" /> <param name="AutoPlay" value="True" /> <!-- win chrome and firefox--> <embed id="vlcEmb" type="application/x-google-vlc-plugin" version="VideoLAN.VLCPlugin.2" autoplay="yes" loop="no" width="640" height="480" target="{{v[1]}}" ></embed></object>');
|
||||
} else {
|
||||
$('#cam_body_{{ count}}').append('<img id="cam_{{ count }}" style="-webkit-user-select: none; width: 100%; height: 100%; " src="{{v[1]|replace('&', '&')}}" >');
|
||||
}
|
||||
{% endfor %}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
|
||||
$(document).ready(function() {
|
||||
{% for k, v in blockArray[count]["domoticz_counter_charts"].iteritems() %}
|
||||
ShowGeneralGraph("domoticz-chart-block-{{count}}",{{v[0]}},"{{k}}", 1, "{{v[2]}}", "{{v[1]}}");
|
||||
ShowGeneralGraph("domoticz-chart-block-{{count}}",{{v[1]}},"{{k}}", 1, "{{v[3]}}", "{{v[2]}}");
|
||||
$("div#title_block_{{count}} h2").html("{{k}}");
|
||||
setInterval(ShowGeneralGraph,60000,"domoticz-chart-block-{{count}}",{{v[0]}},"{{k}}", 1, "{{v[2]}}", "{{v[1]}}");
|
||||
setInterval(ShowGeneralGraph,60000,"domoticz-chart-block-{{count}}",{{v[1]}},"{{k}}", 1, "{{v[3]}}", "{{v[2]}}");
|
||||
{% endfor %}
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
|
||||
$(document).ready(function() {
|
||||
{% for k, v in blockArray[count]["domoticz_percentage_charts"].iteritems() %}
|
||||
ShowPercentageLog("domoticz-chart-block-{{count}}",{{v[0]}},"{{k}}", "{{v[1]}}");
|
||||
ShowPercentageLog("domoticz-chart-block-{{count}}",{{v[1]}},"{{k}}", "{{v[2]}}");
|
||||
$("div#title_block_{{count}} h2").html("{{k}}");
|
||||
setInterval(ShowPercentageLog,60000,"domoticz-chart-block-{{count}}",{{v[0]}},"{{k}}", "{{v[1]}}");
|
||||
setInterval(ShowPercentageLog,60000,"domoticz-chart-block-{{count}}",{{v[1]}},"{{k}}", "{{v[2]}}");
|
||||
{% endfor %}
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
|
||||
$(document).ready(function() {
|
||||
{% for k, v in blockArray[count]["domoticz_smart_charts"].iteritems() %}
|
||||
ShowSmartLog("domoticz-chart-block-{{count}}",{{v[0]}},"{{k}}", "{{v[2]}}", "{{v[1]}}");
|
||||
ShowSmartLog("domoticz-chart-block-{{count}}",{{v[1]}},"{{k}}", "{{v[3]}}", "{{v[2]}}");
|
||||
$("div#title_block_{{count}} h2").html("{{k}}");
|
||||
setInterval(ShowSmartLog,60000,"domoticz-chart-block-{{count}}",{{v[0]}},"{{k}}", "{{v[2]}}", "{{v[1]}}");
|
||||
setInterval(ShowSmartLog,60000,"domoticz-chart-block-{{count}}",{{v[1]}},"{{k}}", "{{v[3]}}", "{{v[2]}}");
|
||||
{% endfor %}
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
|
||||
$(document).ready(function() {
|
||||
{% for k, v in blockArray[count]["domoticz_temp_charts"].iteritems() %}
|
||||
ShowTempLog("domoticz-chart-block-{{count}}",{{v[0]}},"{{k}}", "{{v[1]}}");
|
||||
ShowTempLog("domoticz-chart-block-{{count}}",{{v[1]}},"{{k}}", "{{v[2]}}");
|
||||
$("div#title_block_{{count}} h2").html("{{k}}");
|
||||
setInterval(ShowGeneralGraph,60000,"domoticz-chart-block-{{count}}",{{v[0]}},"{{k}}", "{{v[1]}}");
|
||||
setInterval(ShowGeneralGraph,60000,"domoticz-chart-block-{{count}}",{{v[1]}},"{{k}}", "{{v[2]}}");
|
||||
{% endfor %}
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ var donut_chart_block_{{count}} = Morris.Donut({
|
|||
$(document).ready(function() {
|
||||
var donutChartElements=[];
|
||||
{% for k, v in blockArray[count]["donut_charts"].iteritems() %}
|
||||
donutChartElements.push("{{v[0]}}");
|
||||
donutChartElements.push("{{v[1]}}");
|
||||
{% endfor %}
|
||||
redrawDonutChart(donutChartElements, donut_chart_block_{{count}});
|
||||
setInterval(redrawDonutChart,9000,donutChartElements, donut_chart_block_{{count}});
|
||||
|
|
|
|||
|
|
@ -9,18 +9,23 @@
|
|||
<!-- Domoboard -->
|
||||
<script src="/static/js/custom.js"></script>
|
||||
<!-- bootstrap-slider -->
|
||||
<link href="/static/css/bootstrap-slider.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="/static/js/bootstrap-slider.js"></script>
|
||||
<script type="text/javascript" src="static/js/moment.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/moment-with-locales.min.js"></script>
|
||||
{% if configValues["domoboard"].get("time") == "True" %}
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
var interval = setInterval(function() {
|
||||
var momentNow = moment();
|
||||
$('#date-part').html(momentNow.format('DD MMMM YYYY'));
|
||||
|
||||
$('#time-part').html(momentNow.format('HH:mm'));
|
||||
$('#date-part').html(momentNow.locale(local_language).format('dddd D MMMM YYYY'));
|
||||
|
||||
$('#time-part').html(momentNow.format('HH:mm'));
|
||||
|
||||
}, 100);
|
||||
{% if configValues["domoboard"].get("date") == "True" %}
|
||||
$('#date-part').removeClass('hide_date');
|
||||
$('#date-part').addClass('show_date');
|
||||
{% endif %}
|
||||
|
||||
$( "#date-part" ).click(function() {
|
||||
$('#date-part').removeClass('show_date');
|
||||
|
|
@ -36,7 +41,23 @@
|
|||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
setInterval(checkVersion, 43200000, branch);
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
var a=document.querySelectorAll("a[href^='/']");
|
||||
for(var i=0;i<a.length;i++)
|
||||
{
|
||||
a[i].onclick=function()
|
||||
{
|
||||
window.location=this.getAttribute("href");
|
||||
return false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,2 @@
|
|||
<!-- footer content -->
|
||||
<div id="custom_notifications" class="custom-notifications dsp_none">
|
||||
<ul class="list-unstyled notifications clearfix" data-tabbed_notifications="notif-group">
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
<div id="notif-group" class="tabbed_notifications"></div>
|
||||
</div>
|
||||
<!-- /footer content -->
|
||||
<!-- Domoboard -->
|
||||
<script src="/static/js/custom.js"></script>
|
||||
<!-- bootstrap-slider -->
|
||||
<link href="/static/css/bootstrap-slider.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="/static/js/bootstrap-slider.js"></script>
|
||||
<script type="text/javascript" src="static/js/moment.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
<link href="/static/images/icons/logo-114x114.png" sizes="114x114" rel="apple-touch-icon-precomposed">
|
||||
<!-- iPhone non-retina icon (iOS < 7) -->
|
||||
<link href="/static/images/icons/logo-57x57.png" sizes="57x57" rel="apple-touch-icon-precomposed">
|
||||
|
||||
|
||||
<title>Domoboard</title>
|
||||
<!-- Bootstrap core CSS -->
|
||||
<script src="/static/js/jquery-2.2.3.min.js"></script>
|
||||
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
<!-- Custom styling plus plugins -->
|
||||
<script src="/static/js/jquery.nicescroll.min.js"></script>
|
||||
|
||||
<script src="/static/js/bootstrap-switch.js"></script>
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
<script src="/static/js/colorpicker/bootstrap-colorpicker.min.js"></script>
|
||||
|
|
@ -61,6 +62,9 @@
|
|||
var flask_server = "{{ request.url_root[:-1] }}";
|
||||
var csrf_token = "{{ _csrf_token }}";
|
||||
var googleMapEmbedKey = "{{ configValues["domoboard"].get("google_maps_api_key") }}"
|
||||
var local_language = "{{ configValues["domoboard"].get("language") }}"
|
||||
var version = "{{ version }}";
|
||||
var branch = "{{ branch }}";
|
||||
</script>
|
||||
<script type="text/javascript" src="/static/js/domoboard.js"></script>
|
||||
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ var line_chart_block_{{count}} = Morris.Line({
|
|||
|
||||
$(document).ready(function() {
|
||||
{% for k, v in blockArray[count]["line_charts"].iteritems() %}
|
||||
redrawLineChart("{{v[2]}}",{{v[0]}},"{{v[1]}}", line_chart_block_{{count}});
|
||||
redrawLineChart("{{v[3]}}",{{v[1]}},"{{v[2]}}", line_chart_block_{{count}});
|
||||
$("div#title_block_{{count}} h2").html("{{k}}");
|
||||
setInterval(redrawLineChart,9000,"{{v[2]}}",{{v[0]}},"{{v[1]}}",line_chart_block_{{count}});
|
||||
setInterval(redrawLineChart,9000,"{{v[3]}}",{{v[1]}},"{{v[2]}}",line_chart_block_{{count}});
|
||||
});
|
||||
{% endfor %}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
<div class="panel-heading"> <strong class="">Login</strong>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" role="form" action="/login/" method="post">
|
||||
<form class="form-horizontal" role="form" action="/login/" method="post" autocomplete="on">
|
||||
<div class="form-group">
|
||||
<div class="form-group input-group">
|
||||
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
|
||||
|
|
@ -36,6 +36,11 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
{% if failed %}
|
||||
<div>
|
||||
<font color="red">{{failed}}</font>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="checkbox">
|
||||
<label class="">
|
||||
<input type="checkbox" class="">Remember me</label>
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@
|
|||
$(document).ready(function() {
|
||||
var location=[];
|
||||
{% for k, v in blockArray[count]["map"].iteritems() %}
|
||||
{% if v[1] %}
|
||||
$('#s_title_{{ count }}').html("{{ v[1] }}");
|
||||
{% if v[0] %}
|
||||
$('#s_title_{{ count }}').html("{{ v[0] }}");
|
||||
{% endif %}
|
||||
location.push("{{v[0]}}");
|
||||
location.push("{{v[1]}}");
|
||||
{% endfor %}
|
||||
refreshMapLocation(location, "locationIframe-{{count}}");
|
||||
setInterval(refreshMapLocation, 60000, location, "locationIframe-{{count}}");
|
||||
|
|
|
|||
|
|
@ -61,8 +61,13 @@
|
|||
<div class="nav toggle navbar-collapse" id="defaultNavbar1">
|
||||
<a id="menu_toggle"><i class="fa fa-bars"></i></a>
|
||||
</div>
|
||||
<div class="show_date" style="cursor: pointer; margin-left: -70px; min-height: 51px;" id="time-part"></div>
|
||||
<div class="show_date" style="cursor: pointer; float: right; margin-left: -70px; margin-right: 20px; min-height: 51px;" id="time-part"></div>
|
||||
<div class="hide_date" style="cursor: pointer; padding-left: 2px;" id="date-part"></div>
|
||||
<div id="version_div" class="hide_update">
|
||||
<button type="button" class="btn btn-success" data-toggle="modal" data-target="#upgradeModal">
|
||||
Update available
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
@ -70,5 +75,36 @@
|
|||
</div>
|
||||
<!-- /top navigation -->
|
||||
|
||||
<!-- Upgrade Modal -->
|
||||
<div class="modal fade" id="upgradeModal" tabindex="-1" role="dialog" aria-labelledby="upgradeModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="upgradeModalLabel">Update available</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h2>A new update is available for Domoboard.</h2><br />
|
||||
The current version is <b><span id="curver"></span></b>.<br />
|
||||
The new version available is: <b><span id="newver"></span></b>.<br />
|
||||
<br />
|
||||
{% if debug == True %}
|
||||
<p><b>Install the new version by pressing the "Upgrade" button below.</b></p>
|
||||
{% endif %}
|
||||
{% if debug == False %}
|
||||
<p><b>Upgrading through Domoboard is only possible when running in debug mode (pass "-d" parameter to server.py). Manual upgrade is possible by performing a "git pull" command.</b></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
|
||||
{% if debug == True %}
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal" onclick="javascript:performUpgrade()">Upgrade</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- page content -->
|
||||
<div class="right_col" role="main">
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<div class="col-md-6 col-sm-6 col-xs-12">
|
||||
<div class="x_panel">
|
||||
<div class="x_title">
|
||||
<h2>News</h2>
|
||||
<h2 id="s_title_{{count}}">News</h2>
|
||||
<ul class="nav navbar-right panel_toolbox">
|
||||
<li><a class="close-link"><i class="fa fa-close"></i></a>
|
||||
</li>
|
||||
|
|
@ -12,8 +12,15 @@
|
|||
</div>
|
||||
<div id="divRss-{{count}}"></div>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
{% for k, v in blockArray[count]["news"].iteritems() %}
|
||||
{% if v[0] %}
|
||||
$('#s_title_{{ count }}').html("{{ v[0] }}");
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
});
|
||||
$('#divRss-{{count}}').FeedEk({
|
||||
FeedUrl:'{{blockArray[count]['news'].get('rssfeed')[0]}}',
|
||||
FeedUrl:"{{blockArray[count]['news'].get('rssfeed')[1]}}",
|
||||
MaxCount : 5,
|
||||
ShowDesc : true,
|
||||
ShowPubDate:true,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
{% for k, v in blockArray[count]["power_usage"].iteritems() %}
|
||||
<tr>
|
||||
<td>{{k}}</td>
|
||||
<td id="power_usage_{{v[0]}}_{{count}}">{{v[1]}}</td>
|
||||
<td id="power_usage_{{v[1]}}_{{count}}">{{v[2]}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
$(document).ready(function() {
|
||||
var updatePowerUsage_{{count}}=[];
|
||||
{% for k, v in blockArray[count]["power_usage"].iteritems() %}
|
||||
updatePowerUsage_{{count}}.push("{{v[0]}}");
|
||||
updatePowerUsage_{{count}}.push("{{v[1]}}");
|
||||
{% endfor %}
|
||||
refreshPowerUsage(updatePowerUsage_{{count}}, "{{count}}");
|
||||
setInterval(refreshPowerUsage, 9000, updatePowerUsage_{{count}}, "{{count}}");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
<link href="static/css/settings.css" rel="stylesheet" type="text/css"/>
|
||||
<ul class="tab">
|
||||
<li><a href="javascript:void(0)" id="defaultOpen" class="tablinks"
|
||||
onclick="openCat(event, 'updates')">Updates</a>
|
||||
</li>
|
||||
<li><a href="javascript:void(0)" id="defaultOpen" class="tablinks"
|
||||
onclick="openCat(event, 'plugins')">Plugins</a>
|
||||
</li>
|
||||
|
|
@ -7,7 +10,27 @@
|
|||
onclick="openCat(event, 'settings')">Settings</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div id="updates" class="tabcontent">
|
||||
<div id="updateView_available" class="hide_update">
|
||||
<h2>A new update is available for Domoboard.</h2><br />
|
||||
The current version is <b><span id="curver_settings"></span></b><br />
|
||||
The new version available is: <b><span id="newver_settings"></span></b><br />
|
||||
<br />
|
||||
{% if debug == True %}
|
||||
<p><b>Install the new version by pressing the "Upgrade" button below.</b></p>
|
||||
{% endif %}
|
||||
{% if debug == False %}
|
||||
<p><b>Upgrading through Domoboard is only possible when running in debug mode (pass "-d" parameter to server.py). Manual upgrade is possible by performing a "git pull" command.</b></p>
|
||||
{% endif %}
|
||||
{% if debug == True %}
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal" onclick="javascript:performUpgrade()">Upgrade</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div id="updateView_not_available" class="hide_update">
|
||||
<h2>Hurray!</h2><br />
|
||||
There is no update available for Domoboard.<br /><br />
|
||||
</div>
|
||||
</div>
|
||||
<div id="plugins" class="tabcontent">
|
||||
<div id="pluginView">
|
||||
</div>
|
||||
|
|
@ -29,7 +52,7 @@
|
|||
<div class="dropdown">
|
||||
<select id="dropDownPage">
|
||||
{% for k, v in configValues["navbar"].iteritems() %}
|
||||
<option>{{ v }}</option>
|
||||
<option>{{ v[0] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
(Select a page to add the domoticz device to)
|
||||
|
|
@ -53,6 +76,27 @@
|
|||
<i>This page requires further development. Please use the config file for advanced changes to the dashboard.</i>
|
||||
<p id="showdevices"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Install Plugin Modal -->
|
||||
<div style="min-height: 100px;" class="modal fade" id="pluginModal" tabindex="-1" role="dialog" aria-labelledby="pluginModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 class="modal-title" id="pluginModalLabel">Install Plugin</h2>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
</button>
|
||||
</div>
|
||||
<div id="plugin_body" class="modal-body">
|
||||
<p id='plug_desc'></p>
|
||||
|
||||
<p id='plug_sum'></p>
|
||||
<p id="plug_info"></p>
|
||||
</div>
|
||||
<div id="plugModalFooter" class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
|
|
@ -86,42 +130,36 @@
|
|||
buttons = buttons + "<button onclick='updatePlugin("+ result[i].id + ")' type='button' class='btn updateBtn'>update";
|
||||
}
|
||||
buttons = buttons + "<button onclick='" + result[i].status + "Plugin(" + result[i].id + ")' name='"+ result[i].title + "' fol='" + result[i].folder + "' type='button' class='btn " + result[i].status + "Btn'>" + result[i].status + "</button>";
|
||||
$('#pluginView').append("<div class='pluginItem'><span onclick=getSummary('" + result[i].title + "_summary')>" + result[i].title + " - Author: " + result[i].author + " - version: " + result[i].version + "</span>"+ buttons + "<div id='" + result[i].title + "_summary' class='fullSummary'><span>" + result[i].description + "</span></div></div>");
|
||||
if (("structure" in result[i]) == true) {
|
||||
$('#' + result[i].title + "_summary").append('<div>');
|
||||
$('#' + result[i].title + "_summary").append('<ul>');
|
||||
for (k in result[i].structure[result[i].folder]) {
|
||||
for (l in result[i].structure[result[i].folder][k]) {
|
||||
$('#' + result[i].title + "_summary").append('<li>' + k + '/' + l + '</li>');
|
||||
}
|
||||
}
|
||||
$('#' + result[i].title + "_summary").append('</ul>');
|
||||
$('#' + result[i].title + "_summary").append('</div>');
|
||||
}
|
||||
$('#pluginView').append("<div class='pluginItem'><span id='" + result[i].title +"_summary' onclick=setPluginInfo('" + result[i].id + "') >v" + result[i].version + " - " + result[i].title + " </span>"+ buttons + "</div>");
|
||||
}
|
||||
$('.fullSummary').hide();
|
||||
}
|
||||
|
||||
function installPlugin(plugin_id) {
|
||||
$('#plugin_body').addClass("loading");
|
||||
var url = "/api?custom=indexPlugins&action=installPlugin&folid=" + plugin_id;
|
||||
requestAPI(url, function(d){
|
||||
automaticIndex();
|
||||
$('#pluginModal').modal('hide');
|
||||
});
|
||||
}
|
||||
|
||||
function removePlugin(plugin_id) {
|
||||
$('#plugin_body').addClass("loading");
|
||||
var url = "/api?custom=indexPlugins&action=removePlugin&folid=" + plugin_id;
|
||||
requestAPI(url, function(d){
|
||||
automaticIndex();
|
||||
$('#pluginModal').modal('hide');
|
||||
});
|
||||
}
|
||||
|
||||
function updatePlugin(plugin_id) {
|
||||
function updatePlugin(plugin_id, ob) {
|
||||
$('#plugin_body').addClass("loading");
|
||||
var url = "/api?custom=indexPlugins&action=removePlugin&folid=" + plugin_id;
|
||||
requestAPI(url, function(d) {
|
||||
var url = "/api?custom=indexPlugins&action=installPlugin&folid=" + plugin_id;
|
||||
requestAPI(url, function(dd) {
|
||||
automaticIndex();
|
||||
$('#pluginModal').modal('hide');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -133,22 +171,39 @@
|
|||
});
|
||||
}
|
||||
|
||||
function getSummary(div_id) {
|
||||
$('.fullSummary').hide();
|
||||
$('#' + div_id).show();
|
||||
function clearModal() {
|
||||
$('#plug_info').empty();
|
||||
$('#pluginModalLabel').empty();
|
||||
$('#plug_desc').empty();
|
||||
$('#plug_sum').empty();
|
||||
$('#plugModalFooter').empty();
|
||||
$('#plugModalFooter').append('<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>');
|
||||
}
|
||||
function setPluginInfo(id) {
|
||||
var url = "/api?custom=indexPlugins";
|
||||
$('#plugin_body').addClass("loading");
|
||||
$('#pluginModal').modal('show');
|
||||
clearModal();
|
||||
requestAPI(url, function(d){
|
||||
var res = JSON.parse(d);
|
||||
$('#pluginModalLabel').html('<b>' + res[id].title + '</b> <span style="float: right;">v' + res[id].version + '</b>');
|
||||
$('#plug_info').html('<b>Author: ' + res[id].author + '</b>');
|
||||
$('#plug_desc').html('<h4><b>Description</b></h4>' + res[id].description);
|
||||
$('#plug_sum').html('<h4><b>Summary</b></h4>' + res[id].summary);
|
||||
if (res[id].update == 'yes') {
|
||||
$('#plugModalFooter').append("<button onclick='updatePlugin("+ res[id].id + ")' type='button' class='btn updateBtn'>update");
|
||||
}
|
||||
$('#plugModalFooter').append("<button onclick='" + res[id].status + "Plugin(" + res[id].id + ", this)' name='"+ res[id].title + "' fol='" + res[id].folder + "' type='button' class='btn " + res[id].status + "Btn'>" + res[id].status + "</button>");
|
||||
$('#plugin_body').removeClass("loading");
|
||||
});
|
||||
}
|
||||
$('.pluginItem span').on('click', function() {
|
||||
console.log('Clicked on Item');
|
||||
console.log($(this));
|
||||
});
|
||||
|
||||
$(document).ready(function () {
|
||||
// Get the element with id="defaultOpen" and click on it
|
||||
document.getElementById("defaultOpen").click();
|
||||
setInterval(automaticIndex(), 9000);
|
||||
$('.fullSummary').hide();
|
||||
checkVersionSettings(branch);
|
||||
});
|
||||
|
||||
retrieveAvailableDevices();
|
||||
selected_page_settings();
|
||||
selected_component_settings();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<link href="/static/css/bootstrap-switch.css" rel="stylesheet" type="text/css" />
|
||||
<link href="/static/css/bootstrap-slider.css" rel="stylesheet">
|
||||
<link href="/static/css/buttons.css" rel="stylesheet" type="text/css" />
|
||||
<div class="col-md-6 col-sm-6 col-xs-12">
|
||||
<div class="x_panel">
|
||||
|
|
@ -16,34 +17,44 @@
|
|||
<table class="table" style="width: auto;">
|
||||
{% for k, v in blockArray[count]["switches"].iteritems() %}
|
||||
<tr>
|
||||
{% if "dimmer" in v[2] or "rgb" in v[2] %}
|
||||
<td style="border-top: none; vertical-align: middle;"><a id="Adim_{{v[1]}}_block_{{count}}" style="cursor: pointer;"><label style="cursor: pointer;" class=""> {{k}}</label></a></td>
|
||||
{% else %}
|
||||
<td style="border-top: none; vertical-align: middle;"><label class=""> {{k}}</label></td>
|
||||
{% endif %}
|
||||
<td style="border-top: none;">
|
||||
{% if "switch" in v[1] %}
|
||||
<input id="switch_{{v[0]}}_block_{{count}}" type="checkbox" checked data-size="mini">
|
||||
{% elif "dimmer" in v[1] %}
|
||||
<input id="dimmer_{{v[0]}}_block_{{count}}" data-slider-id='dimmer_{{v[0]}}' type="text" test={{ v[1] }} data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="14" />
|
||||
{% elif "pushon" in v[1] %}
|
||||
<button id="push_{{v[0]}}_block_{{count}}" class="btn btn-primary btn-circle"> <li class="fa fa-power-off" aria-hidden="true"></i> </button>
|
||||
{% elif "pushoff" in v[1] %}
|
||||
<button id="push_{{v[0]}}_block_{{count}}" class="btn btn-danger btn-circle"> <li class="fa fa-power-off" aria-hidden="true"></i> </button>
|
||||
{% elif "group" in v[1] %}
|
||||
<div><div style="float: left"><button id="groupon_{{v[0]}}_block_{{count}}" class="btn btn-primary btn-circle"> <li class="fa fa-power-off" aria-hidden="true"></i> </button></div><div style="padding-left: 20px; float: left"><button id="groupoff_{{v[0]}}_block_{{count}}" class="btn btn-primary btn-circle btn-danger"> <li class="fa fa-power-off" aria-hidden="true"></i> </button></div></div>
|
||||
{% elif "scene" in v[1] %}
|
||||
<button id="scene_{{v[0]}}_block_{{count}}" class="btn btn-primary btn-circle"> <li class="fa fa-power-off" aria-hidden="true"></i> </button>
|
||||
{% elif "setpoint" in v[1] %}
|
||||
{% if "switch" in v[2] %}
|
||||
<input id="switch_{{v[1]}}_block_{{count}}" type="checkbox" checked data-size="mini">
|
||||
{% elif "dimmer" in v[2] %}
|
||||
<input id="dimmer_{{v[1]}}_block_{{count}}" data-slider-id='dim_{{v[1]}}_block_{{count}}' type="text" test={{ v[2] }} state="on" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="14" />
|
||||
{% elif "pushon" in v[2] %}
|
||||
<button id="push_{{v[1]}}_block_{{count}}" class="btn btn-primary btn-circle"> <li class="fa fa-power-off" aria-hidden="true"></i> </button>
|
||||
{% elif "pushoff" in v[2] %}
|
||||
<button id="push_{{v[1]}}_block_{{count}}" class="btn btn-danger btn-circle"> <li class="fa fa-power-off" aria-hidden="true"></i> </button>
|
||||
{% elif "group" in v[2] %}
|
||||
<div><div style="float: left"><button id="groupon_{{v[1]}}_block_{{count}}" class="btn btn-primary btn-circle"> <li class="fa fa-power-off" aria-hidden="true"></i> </button></div><div style="padding-left: 20px; float: left"><button id="groupoff_{{v[1]}}_block_{{count}}" class="btn btn-primary btn-circle btn-danger"> <li class="fa fa-power-off" aria-hidden="true"></i> </button></div></div>
|
||||
{% elif "scene" in v[2] %}
|
||||
<button id="scene_{{v[1]}}_block_{{count}}" class="btn btn-primary btn-circle"> <li class="fa fa-power-off" aria-hidden="true"></i> </button>
|
||||
{% elif v[2] == "setpoint" %}
|
||||
<div>
|
||||
<div style="float: left; margin-right: 5px"><h1 id="setpoint_{{v[0]}}_block_{{count}}" style="font-size: 16px;"></h1></div>
|
||||
<div style="float: left; margin-right: 5px"><h1 id="setpoint_{{v[1]}}_block_{{count}}" style="font-size: 16px;"></h1></div>
|
||||
<div style="float: left">
|
||||
<div style=""><i onclick="changeUp({{ v[0] }}, {{count}})" class="fa fa-arrow-up" style="font-size: 13px; cursor: pointer;" aria-hidden="true"></i></div>
|
||||
<div style=""><i onclick="changeDown({{ v[0] }}, {{count}})" class="fa fa-arrow-down" style="font-size: 13px; cursor: pointer;" aria-hidden="true"></i></div>
|
||||
<div style=""><i onclick="changeUp({{ v[1] }}, {{count}})" class="fa fa-arrow-up" style="font-size: 13px; cursor: pointer;" aria-hidden="true"></i></div>
|
||||
<div style=""><i onclick="changeDown({{ v[1] }}, {{count}})" class="fa fa-arrow-down" style="font-size: 13px; cursor: pointer;" aria-hidden="true"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
{% elif "rgb" in v[1] %}
|
||||
<input id="dimmer_{{v[0]}}_block_{{count}}" data-slider-id='dimmer_{{v[0]}}' type="text" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="14" />
|
||||
{% elif "setpoint_slider" in v[2] %}
|
||||
<input id="setpoint_slider{{v[1]}}_block_{{count}}" data-slider-id='stpnt_{{v[1]}}_block_{{count}}' type="text" state="on" data-slider-min="{{v[3]}}" data-slider-max="{{v[4]}}" data-slider-step="0.5" />
|
||||
{% elif "selector" in v[2] %}
|
||||
<div class="btn-toolbar">
|
||||
<div id="selector_body_{{v[1]}}_block_{{count}}" class="btn-group pull-right" style="width: 100%;"> </div>
|
||||
</div>
|
||||
{% elif "rgb" in v[2] %}
|
||||
<input id="dimmer_{{v[1]}}_block_{{count}}" data-slider-id='dim_{{v[1]}}_block_{{count}}' type="text" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="14" />
|
||||
<br><br>
|
||||
<button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#myModal-{{v[0]}}-block-{{count}}">RGB colors</button>
|
||||
<button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#myModal-{{v[1]}}-block-{{count}}">RGB colors</button>
|
||||
<!-- Modal -->
|
||||
<div class="modal fade bd-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true" id="myModal-{{v[0]}}-block-{{count}}">
|
||||
<div class="modal fade bd-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true" id="myModal-{{v[1]}}-block-{{count}}">
|
||||
<div class="modal-dialog modal-sm">
|
||||
|
||||
<!-- Modal content-->
|
||||
|
|
@ -53,7 +64,7 @@
|
|||
<h4 class="modal-title">RGB Selector</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="rgb_{{v[0]}}_block_{{count}}" class="inl-bl"></div>
|
||||
<div id="rgb_{{v[1]}}_block_{{count}}" class="inl-bl"></div>
|
||||
<style>
|
||||
.inl-bl {
|
||||
display: inline-block;
|
||||
|
|
@ -61,7 +72,7 @@
|
|||
</style>
|
||||
<script>
|
||||
$(function() {
|
||||
$('#rgb_{{v[0]}}_block_{{count}}').colorpicker({
|
||||
$('#rgb_{{v[1]}}_block_{{count}}').colorpicker({
|
||||
color: '#ffaa00',
|
||||
container: true,
|
||||
inline: true
|
||||
|
|
@ -70,7 +81,7 @@
|
|||
</script>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal" onclick="changeRgbColor('rgb_{{v[0]}}_block_{{count}}')">Save</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal" onclick="changeRgbColor('rgb_{{v[1]}}_block_{{count}}')">Save</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -90,51 +101,88 @@ $(document).ready(function() {
|
|||
var updateSwitches_block_{{count}}=[];
|
||||
var updateDimmers_block_{{count}}=[];
|
||||
var updateSetpoints_block_{{count}}=[];
|
||||
var updateSetpoint_sliders_block_{{count}}=[];
|
||||
|
||||
{% for k, v in blockArray[count]["switches"].iteritems() %}
|
||||
|
||||
{% if v[2] %}
|
||||
$('#s_title_{{ count }}').html("{{ v[2] }}");
|
||||
{% if v[0] %}
|
||||
$('#s_title_{{ count }}').html("{{ v[0] }}");
|
||||
{% endif %}
|
||||
{% if v[1] == "switch" %}
|
||||
$('input[id="switch_{{v[0]}}_block_{{count}}"]').on('switchChange.bootstrapSwitch', function(event, state) {
|
||||
changeSwitch(this, {{v[0]}});
|
||||
{% if v[2] == "switch" %}
|
||||
$('input[id="switch_{{v[1]}}_block_{{count}}"]').on('switchChange.bootstrapSwitch', function(event, state) {
|
||||
changeSwitch(this, {{v[1]}});
|
||||
});
|
||||
updateSwitches_block_{{count}}.push("{{v[0]}}");
|
||||
{% elif (v[1] == "pushon") %}
|
||||
$('button[id="push_{{v[0]}}_block_{{count}}"]').click(function(e) {
|
||||
updateSwitches_block_{{count}}.push("{{v[1]}}");
|
||||
{% elif (v[2] == "pushon") %}
|
||||
$('button[id="push_{{v[1]}}_block_{{count}}"]').click(function(e) {
|
||||
e.preventDefault();
|
||||
changePush({{v[0]}}, 'on');
|
||||
changePush({{v[1]}}, 'on');
|
||||
});
|
||||
{% elif (v[1] == "pushoff") %}
|
||||
$('button[id="push_{{v[0]}}_block_{{count}}"]').click(function(e) {
|
||||
{% elif (v[2] == "pushoff") %}
|
||||
$('button[id="push_{{v[1]}}_block_{{count}}"]').click(function(e) {
|
||||
e.preventDefault();
|
||||
changePush({{v[0]}}, 'off');
|
||||
changePush({{v[1]}}, 'off');
|
||||
});
|
||||
{% elif (v[1] == "group") or (v[1] == "scene") %}
|
||||
$('button[id="groupon_{{v[0]}}_block_{{count}}"]').click(function(e) {
|
||||
{% elif (v[2] == "group") or (v[2] == "scene") %}
|
||||
$('button[id="groupon_{{v[1]}}_block_{{count}}"]').click(function(e) {
|
||||
e.preventDefault();
|
||||
changeScene({{v[0]}}, 'on');
|
||||
changeScene({{v[1]}}, 'on');
|
||||
});
|
||||
$('button[id="groupoff_{{v[0]}}_block_{{count}}"]').click(function(e) {
|
||||
$('button[id="groupoff_{{v[1]}}_block_{{count}}"]').click(function(e) {
|
||||
e.preventDefault();
|
||||
changeScene({{v[0]}}, 'off');
|
||||
changeScene({{v[1]}}, 'off');
|
||||
});
|
||||
$('button[id="scene_{{v[0]}}_block_{{count}}"]').click(function(e) {
|
||||
$('button[id="scene_{{v[1]}}_block_{{count}}"]').click(function(e) {
|
||||
e.preventDefault();
|
||||
changeScene({{v[0]}}, 'on');
|
||||
changeScene({{v[1]}}, 'on');
|
||||
});
|
||||
{% elif (v[1] == "setpoint") %}
|
||||
updateSetpoints_block_{{count}}.push("{{v[0]}}");
|
||||
{% elif (v[1] == "dimmer" or v[1] == "rgb") %}
|
||||
updateDimmers_block_{{count}}.push("{{v[0]}}");
|
||||
{% elif (v[2] == "selector") %}
|
||||
url = '/api?type=devices&rid=' + {{v[1]}};
|
||||
requestAPI(flask_server + url, function(d) {
|
||||
r = JSON.parse(d);
|
||||
btns = r['result'][0]['LevelNames'].split('|');
|
||||
if (r['result'][0]['LevelOffHidden'] == true) {
|
||||
btns.shift();
|
||||
}
|
||||
$.each(btns, function (i, lvlname) {
|
||||
activebtn = r['result'][0]['Level']
|
||||
if (i != '0') {
|
||||
i = i + '0';
|
||||
}
|
||||
if (activebtn == i) {
|
||||
btnClass = 'btn btn-primary btn-responsive';
|
||||
} else {
|
||||
btnClass = 'btn btn-responsive';
|
||||
}
|
||||
bid = 'selector_{{v[1]}}_block_{{count}}_index_';
|
||||
b = '<button id="' + bid + i + '" onclick="switchSelector({{v[1]}}, ' + i + ', this.id)" class="' + btnClass + '">' + lvlname + '</button>';
|
||||
$('#selector_body_{{v[1]}}_block_{{count}}').append(b);
|
||||
$('#' + 'selector_{{v[1]}}_block_{{count}}_index_' + i).click(function(e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
});
|
||||
{% elif (v[2] == "setpoint") %}
|
||||
updateSetpoints_block_{{count}}.push("{{v[1]}}");
|
||||
{% elif (v[2] == "setpoint_slider") %}
|
||||
updateSetpoint_sliders_block_{{count}}.push(["{{v[1]}}", "{{v[3]}}", "{{v[4]}}"]);
|
||||
{% elif (v[2] == "dimmer" or v[2] == "rgb") %}
|
||||
$('#Adim_{{v[1]}}_block_{{count}}').click(function(e) {
|
||||
e.preventDefault();
|
||||
changeDimmer('dim_{{v[1]}}_block_{{count}}_track', {{v[1]}});
|
||||
});
|
||||
updateDimmers_block_{{count}}.push("{{v[1]}}");
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
refreshSwitches(updateSwitches_block_{{count}}, {{count}});
|
||||
refreshSetpoints(updateSetpoints_block_{{count}}, {{count}});
|
||||
dimmerSlider(updateDimmers_block_{{count}}, {{count}});
|
||||
setpointSlider(updateSetpoint_sliders_block_{{count}}, {{count}});
|
||||
|
||||
setInterval(refreshSwitches, 9000, updateSwitches_block_{{count}}, {{count}});
|
||||
setInterval(dimmerSlider, 9000, updateDimmers_block_{{count}}, {{count}});
|
||||
setInterval(setpointSlider, 9000, updateSetpoint_sliders_block_{{count}}, {{count}});
|
||||
setInterval(refreshSetpoints, 9000, updateSetpoints_block_{{count}}, {{count}});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
<div class="animated flipInY col-md-2 col-sm-4 col-xs-4 tile_stats_count">
|
||||
<div class="left"></div>
|
||||
<div class="right">
|
||||
<span class="count_top"><i class="fa fa-{{v[1]}}"></i> {{k}}</span>
|
||||
<div class="count{% if v[2] == "On" %} green{% elif v[2] == "Off" %} red{% endif %} loading" id=top_tiles_block_{{count}}_{{v[0]}} style="white-space: nowrap;">{{v[2]}}</div>
|
||||
<span class="count_top"><i class="fa fa-{{v[2]}}"></i> {{k}} <i id="top_tiles_block_{{count}}_{{v[1]}}_{% if v[3] %}{{v[3]}}{% else %}Data{% endif %}_arrow" class='fa fa-lg'></i></span>
|
||||
<div class="count loading" id="top_tiles_block_{{count}}_{{v[1]}}_{% if v[3] %}{{v[3]}}{% else %}Data{% endif %}" style="white-space: nowrap"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
|
@ -14,15 +14,29 @@
|
|||
$(document).ready(function() {
|
||||
var updateDivs_block_{{count}}=[];
|
||||
var tilesPreviousArray_{{count}}=[];
|
||||
var updateDivsType_block_{{count}} = [];
|
||||
var updateDivsUnits_block_{{count}} = [];
|
||||
{% for k, v in blockArray[count]["top_tiles"].iteritems() %}
|
||||
updateDivs_block_{{count}}.push("{{v[0]}}");
|
||||
updateDivs_block_{{count}}.push("{{v[1]}}");
|
||||
{% if v[3]|length > 3 %}
|
||||
updateDivsType_block_{{count}}.push("{{v[3]}}");
|
||||
{% else %}
|
||||
updateDivsType_block_{{count}}.push("Data");
|
||||
{% endif %}
|
||||
{% if v[4] %}
|
||||
updateDivsUnits_block_{{count}}.push("{{v[4]}}");
|
||||
{% else %}
|
||||
updateDivsUnits_block_{{count}}.push(undefined);
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
tilesPreviousArray_{{count}} = refreshTopTiles(updateDivs_block_{{count}}, "top_tiles_block_{{count}}_", tilesPreviousArray_{{count}});
|
||||
|
||||
tilesPreviousArray_{{count}} = refreshTopTiles(updateDivs_block_{{count}}, "top_tiles_block_{{count}}_", tilesPreviousArray_{{count}}, updateDivsType_block_{{count}}, updateDivsUnits_block_{{count}});
|
||||
tilesPreviousArray_{{count}} = setInterval(refreshTopTiles, 9000, updateDivs_block_{{count}}, "top_tiles_block_{{count}}_", tilesPreviousArray_{{count}}, updateDivsType_block_{{count}}, updateDivsUnits_block_{{count}});
|
||||
var counter = 0;
|
||||
for (var i in updateDivs_block_{{count}}) {
|
||||
$("#top_tiles_block_{{count}}_" + updateDivs_block_{{count}}[i]).removeClass("loading");
|
||||
$("#top_tiles_block_{{count}}_" + updateDivs_block_{{count}}[i] + "_" + updateDivsType_block_{{count}}[counter]).removeClass("loading");
|
||||
counter += 1;
|
||||
}
|
||||
tilesPreviousArray_{{count}} = setInterval(refreshTopTiles, 9000, updateDivs_block_{{count}}, "top_tiles_block_{{count}}_", tilesPreviousArray_{{count}});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- /top tiles -->
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
<div class="col-md-6 col-sm-6 col-xs-12">
|
||||
<div class="x_panel">
|
||||
<div class="x_title">
|
||||
<h2>TV-Gids </h2>
|
||||
<ul class="nav navbar-right panel_toolbox">
|
||||
<li><a class="close-link"><i class="fa fa-close"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div id="tvgids" style="height: 450px;">
|
||||
<iframe frameborder=0 style="overflow: hidden; position: relative; height: 100%; width: 100%;" src='https://www.tvgids24.nl/gadget'/></iframe>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
Loading…
Reference in New Issue