Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating block by device Name rather than device idx #1155

Open
JRB202 opened this issue Feb 5, 2024 · 26 comments
Open

Creating block by device Name rather than device idx #1155

JRB202 opened this issue Feb 5, 2024 · 26 comments

Comments

@JRB202
Copy link

JRB202 commented Feb 5, 2024

I would need to be able to create block from domoticz device Name rather than from domoticz device idx

I noticed existence of Domoticz.getAllDevices() function but calling this function with:
var mydevices = Domoticz.getAllDevices()
in dashticz/custom/CONFIG.js
is apparently not recognized
and I do not known if Domoticz.getAllDevices()[DeviceName] is allowed for this function.

==> How can I manage to get a variable containing equivalent of domoticz.devices syntax in dashticz/custom/CONFIG.js
and parse it by name ?

@JRB202
Copy link
Author

JRB202 commented Feb 7, 2024

  1. Doc is stating in :
    https://dashticz.readthedocs.io/en/master/develop/design.html#getalldevices
    That this code could be used :
    var alldevices = Domoticz.getAllDevices();
    var device = alldevices[123]; //To get device 123

But this code generates error when inserted in dashticz/custom/CONFIG.js.
I need to be able to get idx from name as my domoticz config cointains different devices/idx on different domoticz sites

  1. What is object structure returned by Domoticz.getAllDevices() ?

@JRB202
Copy link
Author

JRB202 commented Feb 7, 2024

This code is able to generate Device Table by name :
var DeviceTable = {}
$.each(Domoticz.getAllDevices(), function (idx, device) {
var idx_n = parseInt(idx);
if (idx_n ) {
DeviceTable[device.Name] = device }
})

This code works fine in dashticz/custom/custom.js

==> How can I make it accepted or generate equivalent in dashticz/custom/CONFIG.js ?

@lokonli
Copy link
Collaborator

lokonli commented Feb 11, 2024

  1. Doc is stating in :
    https://dashticz.readthedocs.io/en/master/develop/design.html#getalldevices
    That this code could be used :
    var alldevices = Domoticz.getAllDevices();
    var device = alldevices[123]; //To get device 123

But this code generates error when inserted in dashticz/custom/CONFIG.js. I need to be able to get idx from name as my domoticz config cointains different devices/idx on different domoticz sites

The Domoticz object can only be accessed from custom.js

It doesn't exist yet when CONFIG.js is executed.

  1. What is object structure returned by Domoticz.getAllDevices() ?

It's a dictionary (object) containing all elements (devices, groups, config) obtained from Domoticz.

@lokonli
Copy link
Collaborator

lokonli commented Feb 11, 2024

Using names for device selection was not implemented, because device names may not be unique.

A work around could be to use the following in CONFIG.js:

//Dashticz url: http://dashticz/?myConfig=0
//or
//http://dashticz/?myConfig=1

var firstDevices = [12, 15, 18];
var secondDevices = [13, 16, 19];

var myConfig = _PARAMS['myConfig']
var firstDevice = firstDevices[myConfig]
var secondDevice = secondDevices[myConfig];

var blocks = {}

blocks['firstdevice'] = {
    idx: firstDevice,
}
blocks['seconddevice'] = {
    idx: secondDevice,
}

The Dashticz url can contain query parameters which end up in the _PARAMS object. This object can be read from CONFIG.js.

@JRB202
Copy link
Author

JRB202 commented Feb 12, 2024

Thanks for answer.
This will not fit my needs because idx are not predictable at all in my case
Only Name (Generated by my code) based on final config of each customer site are predictable.

How can I, at least, dynamically get a table like DeviceTable[idx] = device.Name available in CONFIG.js ?

I could solve my needs starting from that table and my own js code in CONFIG.js

@lokonli
Copy link
Collaborator

lokonli commented Feb 12, 2024

In CONFIG.js it will be difficult, since at that moment the Domoticz connection is not active yet, so no device information is available.

Is it a read-only device? Then you could use the deviceHook function in custom.js

I will check how much effort it is to use device names instead of device idx.

@JRB202
Copy link
Author

JRB202 commented Feb 12, 2024

Device related are :

  1. Virtual On/Off Switch that can be toggled On/Off in Dashticz
  2. Text read-only and updated by Domoticz dzvent code
  3. Meters read-only and updated by Domoticz dzvent code

With an unpredictable number of occurrences of these 3 blocks
unpredictable idx and predictable device names generated by my own Domoticz dzvent code.

@lokonli
Copy link
Collaborator

lokonli commented Feb 12, 2024

ok, try latest beta.

You should be able to use device names instead of device idx.

   blocks['example'] = {
     idx: 'my device'
  }

Please report any strange behavior you encounter, because I only did some minimal regression testing yet.

@JRB202
Copy link
Author

JRB202 commented Feb 12, 2024

Fantastic, it works for block !
but not yet for graph .
==> Any hope with graph definition by device name ?

@lokonli
Copy link
Collaborator

lokonli commented Feb 12, 2024

Can you post the block definition your graph?

@lokonli
Copy link
Collaborator

lokonli commented Feb 12, 2024

Can you test latest beta?

@JRB202
Copy link
Author

JRB202 commented Feb 12, 2024

Now it also works for graph blocks :
At least for this one:
blocks['graph_test'] = {
devices: ['ActivityMonitor-LifeEvent'], //idx = 46
graph: 'line', // bar or line
debugButton: true,
zoom: true,
datasetColors: ['red'],
lineFill: [true],
legend: true,
}
Please note that legend shows l_46 instead of expected l_ActivityMonitor-LifeEvent

But this one is failing:
when I replace 'd.l_46' by 'd.l_ActivityMonitor-LifeEvent' in custom data as below

blocks['graph_ActivityMonitor-LifeEvent'] = {
devices: ['ActivityMonitor-LifeEvent'], //idx = 46
graph: ['line'], // bar or line
legend: true,
aggregate: ['avg'], // sum or avg
ylabels: ['Life Event'],
datasetColors:['blue'],
graphTypes: ['l'],
custom : {
"Last hours": {
range: 'last',
filter: '12 hours',
data: {
'Life Event': 'd.l_ActivityMonitor-LifeEvent', // 'd.l_46'
},
},
},
}

@JRB202
Copy link
Author

JRB202 commented Feb 12, 2024

I intend to use the following prototype of code in CONFIG.js to dynamically build blocks

But I miss a function giving the device idx from device name if this domoticz device exist
This function should be usable in CONFIG.js and custom.js
The idea:
function deviceName (deviceName) returning device.idx

Then we could use :

var EnergyLineSwitchLine = [];
var MaxOccur = 30; // unpredictable value based on customer site config
for (let i = 1; i <= MaxOccur; i++) {
if (deviceName ('VirtLineSwitch'+i)) {
EnergyLineSwitchLine[i] = deviceName ('VirtLineSwitch'+i); // VirtLineSwitch1 VirtLineSwitch2 ... are domoticz devices
} else {
break;
} // end if
} // end for

BlockList = []
var LineCount = Object.keys(EnergyLineSwitchLine).length;
for (let i = 1; i <= LineCount; i++) {
SwitchBlockName = 'EnergyLineSwitchLine'+i
blocks[SwitchBlockName ] = {
idx: EnergyLineSwitchLine[i],
width: 3, //The width of the block relative to the column width
flash: 500,
}
BlockList.push(SwitchName);
} // End For

columns['C1-Energy-Lines'] = {
blocks: BlockList,
width: 12,
}
screens['default']['S1-Energy']['columns'] = ['C1-Energy-Lines']

@lokonli
Copy link
Collaborator

lokonli commented Feb 12, 2024

In latest beta you now can use Domoticz.getAllDevices('Device name') to get a device with a specific name.
This doesn't work in CONFIG.js, only in custom.js.

I think you can use a dummy block and set the blocks parameter from custom.js. I'll try ...

@JRB202
Copy link
Author

JRB202 commented Feb 12, 2024

Domoticz.getAllDevices('Device name') usable in custom.js is clearly a plus and will help.

But blocks are generated in CONFIG.js and not in custom.js which is mainly used for cosmetic and effects only
and using Domoticz.getAllDevices('Device name') in custom.js which is based on values updates will lead to big overload by rebuilding blocks at a abnormaly high frequency.

So the solution is simple to express, but perhaps morecomplicated to implement :

==>Make Domoticz.getAllDevices('Device name') returning idx usable in CONFIG.js and users like me will do the rest !
Is that feasible ?

@lokonli
Copy link
Collaborator

lokonli commented Feb 12, 2024

No, not really.

Alternative:
Create all blocks that may exist, like:

blocks['block1'] = {
    idx: 'switch1',
    addClass: 'hidden'
}

Then in custom.js, if the device exists:

var initial=true;
function afterGetDevices(){
    if(initial) {
       if(Domoticz.getAllDevices('switch1'))
           Dashticz.setBlock('block1', {addClass: ""});
        initial = false;
    }
}

@lokonli
Copy link
Collaborator

lokonli commented Feb 12, 2024

or, maybe cleaner/easier: add a beforeFirstRender() hook, in which you still can modify the blocks object.

@JRB202
Copy link
Author

JRB202 commented Feb 12, 2024

Clearly this last solution would be efficient :
cleaner/easier: add a beforeFirstRender() hook, in which you still can modify the blocks object.

  1. Domoticz.getAllDevices('switch1') and Domoticz.getAllDevices('idx1') must be usable inside this hook beforeFirstRender()
  2. Creation of new blocks and update of existing blocks must be possible in this hook

Feasible ?

@lokonli
Copy link
Collaborator

lokonli commented Feb 13, 2024

ok.
In latest beta I've implemented beforeFirstRenderHook()

See:
https://dashticz.readthedocs.io/en/beta/customjs/customjs.html#before-first-render-hook

@JRB202
Copy link
Author

JRB202 commented Feb 13, 2024

Thanks lokonli for this superb demonstration of reactivity and light speed implementation !
You did open a door on new automatisation level of dynamic user interface building using Dashticz and domoticz !

Let me have a try with my own needs and I will get back to you for feed back.

@JRB202
Copy link
Author

JRB202 commented Feb 13, 2024

How can we fix this last problem with custom graph with device name ?

The graph below is failing when I replace 'd.l_46' by 'd.l_ActivityMonitor-LifeEvent' in custom data as below.

I get error during Dashticz interface generation because d.l_46 is probably still automatically generated
then cannot be replaced by something else like d.l.name
Unfortunately this 'd.l_idx' is unpredictable if using device names
and custom graph deserve to be used with device names !

Solution fix suggestion for your code :
Replace d.l_ by d.l_ where DataSetId is an integer from 1 to n
that will be allocated when reading the device name list and corresponding data sets
Then if the graph is multidevice sourced by n devices declared in :
devices: ['DeviceName1',DeviceName2, ..., Devicen];

The Dashticz user will just have to know that d.l_ from d.l_1 to d.l_n
correspond to order of devices declaration in this line

Feasible ?

My test is here :

blocks['graph_ActivityMonitor-LifeEvent'] = {
devices: ['ActivityMonitor-LifeEvent'], //idx = 46
graph: ['line'], // bar or line
legend: true,
aggregate: ['avg'], // sum or avg
ylabels: ['Life Event'],
datasetColors:['blue'],
graphTypes: ['l'],
custom : {
"Last hours": {
range: 'last',
filter: '12 hours',
data: {
'Life Event': 'd.l_ActivityMonitor-LifeEvent', // Works with 'd.l_46' but fails with 'd.l_ActivityMonitor-LifeEvent'
},
},
},
}

@lokonli
Copy link
Collaborator

lokonli commented Feb 13, 2024

I'm working on quite a big update of the graph module, including upgrade to latest chart.js version.

I've made some changes already: for single device graphs the '_' part is removed.
It's a good suggestion to use the _2 and _3 etc. to select the right data: I'll implement it like that.

@JRB202
Copy link
Author

JRB202 commented Feb 13, 2024

Keep me informed, I will be happy to test this new d.l_1 to d.l_n mode.

@JRB202
Copy link
Author

JRB202 commented Feb 14, 2024

I just successfully used new beforeFirstRenderHook() function to implement :

  1. dynamic blocks creation from domoticz device names
  2. dynamic block color coding using afterGetDevices() on blocks dynamically created just before with beforeFirstRenderHook()

So the test is clearly passed OK.

Thanks again for you reactivity !
I am sure other Dashticz users and will take advantage of dynamic block creation in beforeFirstRenderHook()

@JRB202
Copy link
Author

JRB202 commented Feb 16, 2024

I just successfully used new beforeFirstRenderHook() function to implement :
1 Dynamic Graph buiding from a variable number of Domoticz device

I confirm everything works fine.

Can you please advice me when you will have replace device idx by dataset indice in custom graph (d.dataset_1 to d.dataset_n)
I will modify my code to use this new mode and test it.

@lokonli
Copy link
Collaborator

lokonli commented Feb 18, 2024

For a test version of the new graph module, see:
#1172

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants