13.06.2016, 09:02
You can also replace [0].innerHTML with jQuery's .html()
Custom JavaScript examples
|
13.06.2016, 09:02
You can also replace [0].innerHTML with jQuery's .html()
13.06.2016, 09:18
(This post was last modified: 13.06.2016, 09:30 by Erwin van der Zwart.)
(13.06.2016, 09:02)admin Wrote: You can also replace [0].innerHTML with jQuery's .html() Thanks Admin, The code will be like this then: Here is the final sample for changing color with css based on setpoint and actual value difference. Give the first setpoint these additional classes 'Setp Setp_1', the 2nd 'Setp Setp_2', the 3th 'Setp Setp_3' etc Give the first actual these additional classes 'Temp Temp_1', the 2nd 'Temp Temp_2', the 3th 'Temp Temp_3' etc So all setpoints will have 2 additional classes (Setp and Setp_nr) and all actuals will have 2 additional classes (Temp and Temp_nr) Make sure to use incredimental sequense 1,2,3,4,5 etc. without gaps as Temp_nr and Setp_nr (the number makes the match between both) Put this code in your custom JavaScript: Code: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546 $(function(){
// Set color values
var defaultcolor = $('.Temp').css("color") // Use color that is default set on the object
var highcolor = 'rgb(0, 153, 204)' // Blue
var lowcolor = 'rgb(204, 153, 0)' // Orange
// Function to change colors on values
function CheckSetpointandValue(){
// Check if and how many elements there are with additional class 'Temp'
if ($(".Temp").length > 0){
// Set number of items to loop through based on additional class 'Temp' items
var TempValueItems = $(".Temp").length // Determine number of compare items
// Set difference between actual and setpoint to change color
var MinimalDifference = 0.5 // Determine minnimal difference between setpoint and actual temperature
// Loop to items to set CSS
for (i = 1; (i-1) < TempValueItems; i++) {
// Set conditions for Setp_nr and Temp_nr
if ( Number( $(".Temp_" + i).html() ) > ( Number( $(".Setp_" + i).html() ) + MinimalDifference ) ){
$(".Temp_" + i).css("color", highcolor);
} else if ( ( Number( $(".Temp_" + i).html() ) + MinimalDifference ) < Number( $(".Setp_" + i).html() ) ){
$(".Temp_" + i).css("color", lowcolor);
} else {
$(".Temp_" + i).css("color", defaultcolor);
}
}
}
}
// Check for changes on value of item with Temp
$('.Temp').bind("DOMSubtreeModified",function(){
CheckSetpointandValue();
});
// Check for changes on value of item with Setp
$('.Setp').bind("DOMSubtreeModified",function(){
CheckSetpointandValue();
});
// Initial execution
CheckSetpointandValue();
});BR, Erwin
13.06.2016, 09:36
You are very wise
![]()
13.06.2016, 09:43
13.06.2016, 12:21
Maybe you can describe in very simple way how to:
- read from object database value of some group address, - write to object database value of some group address(with or without write to the bus), - read some additional object's info like "updatetime". And also if there is a possibility to prepare the OR and AND gates for a few objects for calculating the room statuses and central statuses or something else.
13.06.2016, 13:09
(This post was last modified: 13.06.2016, 13:29 by Erwin van der Zwart.)
(13.06.2016, 12:21)buuuudzik Wrote: Maybe you can describe in very simple way how to: Hi Buuuudzik, All your questions are possible and are used in many of the custom JavaScript samples on this forum. Please try to create some scripts based on those samples. I'm happy to give samples / solutions that are not on the forum yet. The idea is that the users are helped with our samples, not to do the work for them (; Why do you want to create the logic client side? The logic won't work when visu is not active. I would advice to keep logic server side with LUA Here are the answers on your question: // Look at possible values from objects (updatetime is not there) It's possible to get that info when using a APP with .lp files but not from Custom Javascript console.log(objectStore.objects) // Get values from object(s) value = objectStore.objects[Scada.encodeGroupAddress('1/1/3')].value value1 = objectStore.objects[Scada.encodeGroupAddress('1/1/3')].value name = objectStore.objects[Scada.encodeGroupAddress('1/1/3')].name console.log(value) console.log(name) // Write to object var id = Scada.encodeGroupAddress('1/1/3'), obj = objectStore.objects[ id ], value = 10; setObjectValue({ address: obj.address , rawdatatype: obj.rawdatatype }, value, "text"); // AND fuction if ( value == 1 && value1 == 1 ) { // dosomething) } // OR function if ( value == 1 || value1 == 1 ) { // dosomething) } BR, Erwin
13.06.2016, 13:43
(13.06.2016, 13:09)Erwin van der Zwart Wrote:(13.06.2016, 12:21)buuuudzik Wrote: Maybe you can describe in very simple way how to: I want use this function on client side because when you have a house which has much more than few rooms using tags and event-based scripts on regular LM is not the best solution(in my opinion). Maybe I can improve something in my scripts but maybe it is optimal way and LM can't deal with a lot of changes in a very little time e.g. central off. Central statuses e.g. "Room_n status" or "Floor_n status" or "All_Floors status" are used general on the visualisation so preparing them by the client is also good and much faster than the regular LM.
13.06.2016, 14:09
(This post was last modified: 13.06.2016, 14:14 by Erwin van der Zwart.)
Hi Buuuudzik,
I would definitly check your scripts, we use our controller for buildings up to 20 floors where we have approx 500 KNX devices behind each controller (as zone coupler) and those have much more data then a single house. We run all scripts server side... Also be aware when you open your visu on multiple locations your logic runs multiple times, don't write to the controller on those cases, but keep client side logic inside visu only. BR, Erwin
13.06.2016, 16:52
(13.06.2016, 14:09)Erwin van der Zwart Wrote: Hi Buuuudzik, I know this and I am aware about that in such case logic can run multiple times. I can show my mechanism which is based on this: http://forum.logicmachine.net/showthread...l+statuses This is what I do: This lamps has tag "Room1" and change the status of Room1_status: Lamp1.1_status Lamp1.2_status Lamp1.3_status... The same is with rooms which have tags e.g. "Floor1_status": Room1_status Room2_status Room3_status... Third level is "Central_status" which is configured in the same way. All of this functions are based on the function tag_or(tag) which is included in user-libraries: Code: 123456789101112 function tag_or(tag)
local objects, result
result = false
objects = grp.tag(tag)
for _, object in ipairs(objects) do
result = result or object.data
end
return result
endThe advantage of this solution is that the statuses are structured and simple to change or extend with new one. I respect you Erwin, and probably there some other way to do this but I don't know in what other way I can do this. How do you do this in your big projects? Do you create also Room statuses or no?
13.06.2016, 19:59
(This post was last modified: 13.06.2016, 20:42 by Erwin van der Zwart.)
Hi Buuuudzik,
I think the iterate of the result table is taking a lot of resources, especially when having the execution of multiple scripts in parallel from the tag group You could try to do it with a direct query from DB to avoid the table iterate and speed up things a bit. Code: 12345678 function tag_or(tag)
local result = db:getall('SELECT id FROM objects WHERE datahex = "01" AND tagcache LIKE "%' .. tag .. '%"')
if #result == 0 then
return false
else
return true
end
endYou can also add this script in the start of your script to kill previous script when executed multiple times in parallel. Code: 1234567891011121314151617 --check for earlier started scrips
storagename = 'TAG_OR' -- Must be unique for every script
--check storage for tpid value
tpid = storage.get(storagename)
--check if tpid has a value
if tpid == nil then
pid = os.getpid()
storage.set(storagename, pid)
else
pid = os.getpid()
-- create new pid for next time to kill
storage.set(storagename, pid)
-- kill earlier running script
os.kill(tpid, signal.SIGKILL)
endIf this doesn't do the trick you can use the semaphore library making it possible to block parallel execution of scripts See http://openrb.com/docs/semaphore.htm or http://openrb.com/event-script-which-can...rotection/ BR, Erwin van der Zwart (13.06.2016, 19:59)PErwin van der Zwart Wrote: Hi Buuuudzik, Very good tip, I will try tommorrow. Thanks, you're the best. I think this will be helpful for a lot of LM medium programmers like me?
14.06.2016, 07:04
(13.04.2016, 11:27)edgars Wrote: In the firmware starting from 4.2016 there is Custom JavaScript feature available in LogicMachine --> Scripting --> Tools --> Edit custom JavaScript. Is it possible to open a widget with the same function?
14.06.2016, 07:31
buuuudzik, have a look at this example for AND / OR status calculation:
http://forum.logicmachine.net/showthread...18#pid1518 Note: you should avoid accessing the database directly, there's no guarantee that there won't be any changes in the firmware which can completely break your scripts which are using undocumented "features" gtsamis Add a unique CSS class (open-widget in this example) to the button that open's your widget, then use this code to trigger click on the button: Code: 1 $('.open-widget').trigger('vclick')Put this after showPlan so the correct plan containing the widget is shown first.
24.06.2016, 10:31
(13.04.2016, 11:27)edgars Wrote: In the firmware starting from 4.2016 there is Custom JavaScript feature available in LogicMachine --> Scripting --> Tools --> Edit custom JavaScript. Where is the new firmware for downloading?????
25.06.2016, 10:51
(This post was last modified: 25.06.2016, 10:54 by Erwin van der Zwart.)
(24.06.2016, 10:31)AdriSaliai Wrote: Where is the new firmware for downloading????? See: http://forum.logicmachine.net/showthread.php?tid=292 BR, Erwin
01.07.2016, 07:46
Small example: play a beep sound each time 1/1/1 value is set to true. Note that it will only work with the upcoming firmware.
Code: 12345678910111213141516171819202122232425262728293031323334353637 $(function(){
var locked;
var ctx = new(window.AudioContext ||
window.webkitAudioContext ||
window.mozAudioContext ||
window.oAudioContext ||
window.msAudioContext);
function beep(duration, freq, cb) {
var osc = ctx.createOscillator();
osc.frequency.value = freq;
osc.connect(ctx.destination);
osc.start ? osc.start(0) : osc.noteOn(0);
setTimeout(function () {
osc.disconnect();
if (typeof cb == "function") {
cb();
}
}, duration);
}
/*
beep each time value of 1/1/1 is true
note that 3rd listen parameter must be set to true
to execute the callback each time new value arrives
otherwise callback is executed only when value changes
*/
grp.listen('1/1/1', function(object, state) {
if (state == 'value' && object.value && !locked) {
locked = true;
beep(200, 432, function() {
locked = false;
});
}
}, true);
});
01.07.2016, 10:12
(This post was last modified: 01.07.2016, 10:12 by Erwin van der Zwart.)
Hi Admin,
Nice feature (; There is only a small problem .. If you execute it multiple times (more then 5 time) with value 1 then it stops working, the console shows: Code: 1 Uncaught NotSupportedError: Failed to construct 'AudioContext': The number of hardware contexts provided (6) is greater than or equal to the maximum bound (6).BR, Erwin
01.07.2016, 10:18
Thanks, Erwin! I've modified the script to create an audio context only once and re-use it. See if it works for you now.
01.07.2016, 10:25
Hi,
I just wanted to post to keep the var new ctx out of the function (; BR, Erwin
01.09.2016, 08:20
(13.06.2016, 06:27)buuuudzik Wrote:(12.06.2016, 22:36)Erwin van der Zwart Wrote: Hi Buuudzik, Unfortunately this script isn't working on LM Load Balancer ![]() |
« Next Oldest | Next Newest »
|