diff --git a/README.md b/README.md index 69da238..10fb79e 100644 --- a/README.md +++ b/README.md @@ -60,11 +60,11 @@ Click save to continue. ![3.png](files/3.png) -With the device created the next step is to initialize the device, click on the cycling arrows 'refresh icon' to bring up the initialization window. +When a new device is created, it will automatically be initialized and all input processes and feeds will be created, according to the pre-defined template. If the template needs to be applied again, as e.g. a process list was experimented on and altered, or single feeds deleted, it may be re-initialized. Clicking the cycling arrows 'refresh icon' will bring up the initialization window. ![4.png](files/4.png) -Click 'Initialize' to initialize the device which will create the input processes and feeds according to the pre-defined template. +Click 'Initialize' to re-initialize the device and to confirm the creation of missing feeds and inputs, as well as the reset of configured processes to their original state. ![5.png](files/5.png) diff --git a/Views/device.js b/Views/device.js index 4f6120d..3416e85 100644 --- a/Views/device.js +++ b/Views/device.js @@ -1,39 +1,49 @@ var device = { - 'list':function() - { + 'list':function() { var result = {}; $.ajax({ url: path+"device/list.json", dataType: 'json', async: false, success: function(data) {result = data;} }); return result; }, - 'set':function(id, fields) - { + 'get':function(id) { + var result = {}; + $.ajax({ url: path+"device/get.json", data: "id="+id, async: false, success: function(data) {result = data;} }); + return result; + }, + + 'set':function(id, fields) { var result = {}; $.ajax({ url: path+"device/set.json", data: "id="+id+"&fields="+JSON.stringify(fields), async: false, success: function(data) {result = data;} }); return result; }, - 'remove':function(id) - { - $.ajax({ url: path+"device/delete.json", data: "id="+id, async: false, success: function(data){} }); + 'setNewDeviceKey':function(id) { + var result = {}; + $.ajax({ url: path+"device/setnewdevicekey.json", data: "id="+id, async: false, success: function(data) {result = data;} }); + return result; + }, + + 'remove':function(id) { + var result = {}; + $.ajax({ url: path+"device/delete.json", data: "id="+id, async: false, success: function(data) {result = data;} }); + return result; }, - 'create':function(id) - { - $.ajax({ url: path+"device/create.json", data: "id="+id, async: false, success: function(data){} }); + 'create':function(nodeid, name, description, type) { + var result = {}; + $.ajax({ url: path+"device/create.json", data: "nodeid="+nodeid+"&name="+name+"&description="+description+"&type="+type, async: false, success: function(data) {result = data;} }); + return result; }, - 'listtemplates':function() - { + 'init':function(id, template) { var result = {}; - $.ajax({ url: path+"device/listtemplates.json", dataType: 'json', async: false, success: function(data) {result = data;} }); + $.ajax({ url: path+"device/init.json?id="+id, type: 'POST', data: "template="+JSON.stringify(template), dataType: 'json', async: false, success: function(data) {result = data;} }); return result; }, - 'inittemplate':function(id) - { + 'prepareTemplate':function(id) { var result = {}; - $.ajax({ url: path+"device/inittemplate.json", data: "id="+id, dataType: 'json', async: false, success: function(data) {result = data;} }); + $.ajax({ url: path+"device/template/prepare.json", data: "id="+id, dataType: 'json', async: false, success: function(data) {result = data;} }); return result; } } diff --git a/Views/device_api.php b/Views/device_api.php index b9e8011..61dae12 100644 --- a/Views/device_api.php +++ b/Views/device_api.php @@ -36,11 +36,26 @@ - - - - - + + + + +
device/list.json
device/get.json?id=1
device/create.json
device/delete.json?id=0
device/set.json?id=0&fields={"name":"Test","description":"Room","nodeid":"House","type":"test"}
device/listtemplates.json
device/inittemplate.json?id=0
device/create.json?nodeid=Test&name=Test
device/delete.json?id=1
device/set.json?id=1&fields={"name":"Test","description":"Room","nodeid":"House","type":"test"}
device/init.json?id=1
+ +

+ + + + +
device/auth/request.json
device/auth/check.json
device/auth/allow.json?ip=127.0.0.1
+ +

+ + + + + +
device/template/listshort.json
device/template/list.json
device/template/reload.json
device/template/get.json?type=example
device/template/prepare.json?id=1
@@ -48,7 +63,3 @@

\'\\Modules\\device\\data\\*.json\''); ?>

- - - - diff --git a/Views/device_dialog.js b/Views/device_dialog.js new file mode 100644 index 0000000..55fe514 --- /dev/null +++ b/Views/device_dialog.js @@ -0,0 +1,556 @@ +var device_dialog = +{ + templates: null, + deviceTemplate: null, + deviceType: null, + device: null, + + 'loadConfig':function(templates, device) { + this.templates = templates; + + if (device != null) { + this.deviceTemplate = null; + this.deviceType = device.type; + this.device = device; + } + else { + this.deviceTemplate = null; + this.deviceType = null; + this.device = null; + } + + this.drawConfig(); + }, + + 'drawConfig':function() { + $("#device-config-modal").modal('show'); + this.adjustConfigModal(); + this.clearConfigModal(); + + var out = ""; + + var categories = []; + var devicesByCategory = {}; + for (var id in this.templates) { + var device = this.templates[id]; + device['id'] = id; + + if (devicesByCategory[device.category] == undefined) { + devicesByCategory[device.category] = []; + categories.push(device.category); + } + devicesByCategory[device.category].push(device); + } + // Place OpenEnergyMonitor prominently at first place, while sorting other categories + if (categories.indexOf('OpenEnergyMonitor') > -1) { + categories.splice(categories.indexOf('OpenEnergyMonitor'), 1); + categories.sort() + categories = ['OpenEnergyMonitor'].concat(categories); + } + + for (var i in categories) { + var category = categories[i]; + + var groups = []; + var devicesByGroup = {}; + for (var i in devicesByCategory[category]) { + var group = devicesByCategory[category][i].group; + if (devicesByGroup[group] == undefined) { + devicesByGroup[group] = []; + groups.push(group); + } + devicesByGroup[group].push(devicesByCategory[category][i]); + } + groups.sort(); + + out += "" + out += ""; + out += ""+category+""; + out += ""; + out += ""; + + for (var i in groups) { + var group = groups[i]; + + out += "" + out += ""; + out += ""+group+""; + out += ""; + out += ""; + + out += ""; + + for (var i in devicesByGroup[group]) { + var id = devicesByGroup[group][i].id; + var name = devicesByGroup[group][i].name; + if (name.length > 25) { + name = name.substr(0, 25) + "..."; + } + + out += ""; + out += ""+name+""; + out += ""; + } + out += ""; + } + } + $("#template-table").html(out); + + if (this.deviceType != null && this.deviceType != '') { + if (this.templates[this.deviceType]!=undefined) { + var template = this.templates[this.deviceType] + + $(".group-header[category='"+template.category+"']").show(); + $(".group-body[category='"+template.category+"'][group='"+template.group+"']").show(); + $(".group-row[type='"+this.deviceType+"']").addClass("device-selected"); + + $('#template-description').html(''+template.description+''); + $('#template-info').show(); + } + } + + // Initialize callbacks + this.registerConfigEvents(); + }, + + 'clearConfigModal':function() { + $("#template-table").text(''); + + var tooltip = "Defaults, like inputs and associated feeds will be automaticaly configured together with the device." + + "

" + + "Initializing a device usualy should only be done once on installation.
" + + "If the configuration was already applied, only missing inputs and feeds will be created."; + + $('#template-tooltip').attr("title", tooltip).tooltip({html: true}); + + if (this.device != null) { + $('#device-config-node').val(this.device.nodeid); + $('#device-config-name').val(this.device.name); + $('#device-config-description').val(this.device.description); + $('#device-config-devicekey').val(this.device.devicekey).prop("disabled", false); + $("#device-config-devicekey-new").prop("disabled", false); + $('#device-delete').show(); + $("#device-save").html("Save"); + if (this.device.type != null && this.device.type != '') { + $("#device-init").show(); + } + else { + $("#device-init").hide(); + } + } + else { + $('#device-config-node').val(''); + $('#device-config-name').val(''); + $('#device-config-description').val(''); + $('#device-config-devicekey').val('').prop("disabled", true); + $("#device-config-devicekey-new").prop("disabled", true); + $('#device-delete').hide(); + $("#device-init").hide(); + $("#device-save").html("Save & Initialize"); + } + device_dialog.drawTemplate(); + }, + + 'adjustConfigModal':function() { + + var width = $(window).width(); + var height = $(window).height(); + + if ($("#device-config-modal").length) { + var h = height - $("#device-config-modal").position().top - 180; + $("#device-config-body").height(h); + } + + $("#content-wrapper").css("transition","0"); + $("#sidebar-wrapper").css("transition","0"); + if (width < 1024) { + $("#content-wrapper").css("margin-left","0"); + $("#sidebar-wrapper").css("width","0"); + $("#sidebar-open").show(); + + $("#content-wrapper").css("transition","0.5s"); + $("#sidebar-wrapper").css("transition","0.5s"); + } else { + $("#content-wrapper").css("margin-left","250px"); + $("#sidebar-wrapper").css("width","250px"); + $("#sidebar-open").hide(); + $("#sidebar-close").hide(); + } + }, + + 'registerConfigEvents':function() { + + $('#template-table .category-header').off('click').on('click', function() { + var category = $(this).attr("category"); + + var e = $(".group-header[category='"+category+"']"); + if (e.is(":visible")) { + $(".group-body[category='"+category+"']").hide(); + e.hide(); + } + else { + e.show(); + + // If a device is selected and in the category to uncollapse, show and select it + if (device_dialog.deviceType != null && device_dialog.deviceType != '') { + var template = device_dialog.templates[device_dialog.deviceType]; + if (template && category == template.category) { + $(".group-body[category='"+template.category+"'][group='"+template.group+"']").show(); + $(".group-row[type='"+device_dialog.deviceType+"']").addClass("device-selected"); + } + } + } + }); + + $('#template-table .group-header').off('click').on('click', function() { + var group = $(this).attr("group"); + var category = $(this).attr("category"); + + var e = $(".group-body[group='"+group+"'][category='"+category+"']"); + if (e.is(":visible")) { + e.hide(); + } + else { + e.show(); + + // If a device is selected and in the category to uncollapse, show and select it + if (device_dialog.deviceType != null && device_dialog.deviceType != '') { + var template = device_dialog.templates[device_dialog.deviceType]; + if (category == template.category && group == template.group) { + $(".group-row[type='"+device_dialog.deviceType+"']").addClass("device-selected"); + } + } + } + }); + + $("#template-table .group-row").off('click').on('click', function () { + var type = $(this).attr("type"); + + $(".group-row[type='"+device_dialog.deviceType+"']").removeClass("device-selected"); + if (device_dialog.deviceType !== type) { + $(this).addClass("device-selected"); + device_dialog.deviceType = type; + + var template = device_dialog.templates[type]; + $('#template-description').html(''+template.description+''); + $('#template-info').show(); + $("#device-init").hide(); + } + else { + device_dialog.deviceType = null; + + $('#template-description').text(''); + $('#template-info').hide(); + $("#device-init").show() + } + + device_dialog.drawTemplate(); + }); + + $("#sidebar-open").off('click').on('click', function () { + $("#sidebar-wrapper").css("width","250px"); + $("#sidebar-close").show(); + }); + + $("#sidebar-close").off('click').on('click', function () { + $("#sidebar-wrapper").css("width","0"); + $("#sidebar-close").hide(); + }); + + $("#device-save").off('click').on('click', function () { + + var node = $('#device-config-node').val(); + var name = $('#device-config-name').val(); + + if (name && node) { + var desc = $('#device-config-description').val(); + var devicekey = $('#device-config-devicekey').val(); + + var init = false; + if (device_dialog.device != null) { + var fields = {}; + if (device_dialog.device.nodeid != node) fields['nodeid'] = node; + if (device_dialog.device.name != name) fields['name'] = name; + if (device_dialog.device.description != desc) fields['description'] = desc; + if (device_dialog.device.devicekey != devicekey) fields['devicekey'] = devicekey; + + if (device_dialog.device.type != device_dialog.deviceType) { + if (device_dialog.deviceType != null) { + fields['type'] = device_dialog.deviceType; + init = true; + } + else fields['type'] = ''; + } + + var result = device.set(device_dialog.device.id, fields); + if (typeof result.success !== 'undefined' && !result.success) { + alert('Unable to update device fields:\n'+result.message); + return false; + } + update(); + } + else { + var type = device_dialog.deviceType; + var result = device.create(node, name, desc, type); + if (typeof result.success !== 'undefined' && !result.success) { + alert('Unable to create device:\n'+result.message); + return false; + } + if (type != null) { + device_dialog.device = { + id: result, + nodeid: node, + name: name, + type: type + }; + init = true; + } + update(); + } + $('#device-config-modal').modal('hide'); + if (init) device_dialog.loadInit(); + } + else { + alert('Device needs to be configured first.'); + return false; + } + }); + + $("#device-delete").off('click').on('click', function () { + $('#device-config-modal').modal('hide'); + device_dialog.loadDelete(device_dialog.device, null); + }); + + $("#device-init").off('click').on('click', function () { + $('#device-config-modal').modal('hide'); + device_dialog.loadInit(); + }); + + $("#device-config-devicekey-new").off('click').on('click', function () { + device_dialog.device.devicekey = device.setNewDeviceKey(device_dialog.device.id); + $('#device-config-devicekey').val(device_dialog.device.devicekey); + }); + }, + + 'drawTemplate':function() { + if (this.deviceType !== null && this.deviceType in this.templates) { + var template = this.templates[this.deviceType]; + $('#template-description').html(''+template.description+''); + $('#template-info').show(); + } + else { + $('#template-description').text(''); + $('#template-info').hide(); + } + }, + + 'loadInit': function() { + var result = device.prepareTemplate(device_dialog.device.id); + if (typeof result.success !== 'undefined' && !result.success) { + alert('Unable to initialize device:\n'+result.message); + return false; + } + device_dialog.deviceTemplate = result; + device_dialog.drawInit(result); + + // Initialize callbacks + $("#device-init-confirm").off('click').on('click', function() { + $('#device-init-modal').modal('hide'); + + var template = device_dialog.parseTemplate(); + var result = device.init(device_dialog.device.id, template); + if (typeof result.success !== 'undefined' && !result.success) { + alert('Unable to initialize device:\n'+result.message); + return false; + } + }); + }, + + 'drawInit': function (result) { + $('#device-init-modal').modal('show'); + device_dialog.adjustInitModal(); + + $('#device-init-modal-label').html('Initialize Device: '+device_dialog.device.name+''); + + if (typeof result.feeds !== 'undefined' && result.feeds.length > 0) { + $('#device-init-feeds').show(); + var table = ""; + for (var i = 0; i < result.feeds.length; i++) { + var feed = result.feeds[i]; + var row = ""; + if (feed.action.toLowerCase() == "none") { + row += ""; + } + else { + row += ""; + } + row += ""+device_dialog.drawInitAction(feed.action)+"" + row += ""+feed.tag+""+feed.name+""; + row += ""+device_dialog.drawInitProcessList(feed.processList)+""; + + table += ""+row+""; + } + $('#device-init-feeds-table').html(table); + } + else { + $('#device-init-feeds').hide(); + } + + if (typeof result.inputs !== 'undefined' && result.inputs.length > 0) { + $('#device-init-inputs').show(); + var table = ""; + for (var i = 0; i < result.inputs.length; i++) { + var input = result.inputs[i]; + var row = ""; + if (input.action.toLowerCase() == "none") { + row += ""; + } + else { + row += ""; + } + row += ""+device_dialog.drawInitAction(input.action)+"" + row += ""+input.node+""+input.name+""+input.description+""; + row += ""+device_dialog.drawInitProcessList(input.processList)+""; + + table += ""+row+""; + } + $('#device-init-inputs-table').html(table); + } + else { + $('#device-init-inputs').hide(); + $('#device-init-inputs-table').html(""); + } + + return true; + }, + + 'drawInitAction': function (action) { + action = action.toLowerCase(); + + var color; + if (action === 'create' || action === 'set') { + color = "rgb(0,110,205)"; + } + else if (action === 'override') { + color = "rgb(255,125,20)"; + } + else { + color = "rgb(50,200,50)"; + action = "exists" + } + action = action.charAt(0).toUpperCase() + action.slice(1); + + return ""+action+""; + }, + + 'drawInitProcessList': function (processList) { + if (!processList || processList.length < 1) return ""; + var out = ""; + for (var i = 0; i < processList.length; i++) { + var process = processList[i]; + if (process['arguments'] != undefined && process['arguments']['value'] != undefined && process['arguments']['type'] != undefined) { + var name = ""+process["name"]+""; + var value = process['arguments']['value']; + + var title; + var color = "info"; + switch(process['arguments']['type']) { + case 0: // VALUE + title = "Value: " + value; + break; + + case 1: //INPUTID + title = "Input: " + value; + break; + + case 2: //FEEDID + title = "Feed: " + value; + break; + + case 4: // TEXT + title = "Text: " + value; + break; + + case 5: // SCHEDULEID + title = "Schedule: " + value; + break; + + default: + title = value; + break; + } + out += ""+name+" "; + } + } + return out; + }, + + 'parseTemplate': function() { + var template = {}; + + template['feeds'] = []; + if (typeof device_dialog.deviceTemplate.feeds !== 'undefined' && + device_dialog.deviceTemplate.feeds.length > 0) { + + var feeds = device_dialog.deviceTemplate.feeds; + $("#device-init-feeds-table tr").find('input[type="checkbox"]:checked').each(function() { + template['feeds'].push(feeds[$(this).attr("row")]); + }); + } + + template['inputs'] = []; + if (typeof device_dialog.deviceTemplate.inputs !== 'undefined' && + device_dialog.deviceTemplate.inputs.length > 0) { + + var inputs = device_dialog.deviceTemplate.inputs; + $("#device-init-inputs-table tr").find('input[type="checkbox"]:checked').each(function() { + template['inputs'].push(inputs[$(this).attr("row")]); + }); + } + + return template; + }, + + 'adjustInitModal':function() { + + var width = $(window).width(); + var height = $(window).height(); + + if ($("#device-init-modal").length) { + var h = height - $("#device-init-modal").position().top - 180; + $("#device-init-body").height(h); + } + }, + + 'loadDelete': function(device, tablerow) { + this.device = device; + + $('#device-delete-modal').modal('show'); + $('#device-delete-modal-label').html('Delete Device: '+device.name+''); + + // Initialize callbacks + this.registerDeleteEvents(tablerow); + }, + + 'registerDeleteEvents':function(row) { + + $("#device-delete-confirm").off('click').on('click', function() { + device.remove(device_dialog.device.id); + if (row != null) { + table.remove(row); + update(); + } + else if (typeof device_dialog.device.inputs !== 'undefined') { + // If the table row is undefined and an input list exists, the config dialog + // was opened in the input view and all corresponding inputs will be deleted + var inputIds = []; + for (var i in device_dialog.device.inputs) { + var inputId = device_dialog.device.inputs[i].id; + inputIds.push(parseInt(inputId)); + } + input.delete_multiple(inputIds); + } + $('#device-delete-modal').modal('hide'); + }); + } +} diff --git a/Views/device_dialog.php b/Views/device_dialog.php new file mode 100644 index 0000000..88faf57 --- /dev/null +++ b/Views/device_dialog.php @@ -0,0 +1,218 @@ + + + + + + + + + + + + + diff --git a/Views/device_view.php b/Views/device_view.php index 7ea9f7f..ceadb1e 100644 --- a/Views/device_view.php +++ b/Views/device_view.php @@ -1,107 +1,84 @@ $value) - { - $devices[$key] = ((!isset($value->name) || $value->name == "" ) ? $key : $value->name); - } + + $version = 1; ?> - - - + + + +
-
-

+
+

loading...
- -
+ +


-

+

+ +

+ +
+ +

-

- -
-
- -