Example: Touch screen cleaning script for LogicMachine visualization

Task

There needs some cleaning to be done on touch screens which are mounted, for example, on the wall and not always you can clean the screen without activating some button on visualization. The below script allows to send 1 to specific KNX group address (in this example 0/0/1) and during Screen_Clean_Time the visualization and all objects will be inactive, including right mouse clicks. After cleaning time is over, the visualization returns to its normal state.

 

Resident script

The following script needs to be added in Resident scripts, it will disable itself automatically after run once.

Source code    
  1. -- ************ Screen cleaning module version 1.0 created by Erwin van der Zwart ************** --
  2. -- ******* This script perform automaticly all needed actions to support screen cleaning ******* --
  3. -- After running script once refresh browser and write object to trigger the screen clean page --
  4. -- ****************************************** SET PARAMETERS *********************************** --
  5.  
  6. --!!! Important !!! Set 1 pc/visu page to use as template to 'Show, make default', if no page is set to 'Show, make default' the script exits without creation of page !!
  7. --!!! Important !!! Works only on iOS/Android after enabling javascript)
  8.  
  9. --Give a (not already excisting) name for the plan thats holds the screen clean page module (if already exist then script exit the creation)
  10. Screen_Clean_Page_Name = 'homeLYnk Screen Cleaning Module'
  11.  
  12. -- Group address to trigger the screen cleaning page
  13. Screen_Clean_Trigger_Group_Address = '0/0/1' -- !! MUST BE A BIT OBJECT !! false = STOP AND BACK TO ORIGIN, true = ACTIVATE
  14.  
  15. -- Set screen clean time (in seconds)
  16. Screen_Clean_Time = 60
  17.  
  18. -- Set translation for screen cleaning duration (user message)
  19. Cleaning_Message = 'You can clean the screen now'
  20. Cleaning_Time_Prefix = 'Within'
  21. Cleaning_Time_Suffix = 'seconds this screen will be closed'
  22.  
  23. -- ****************************************** END PARAMETERS ************************************ --
  24. -- ***************************** DON'T CHANGE ANYTHING UNDER THIS LINE ************************** --
  25.  
  26. -- Get default startpage
  27. query = 'SELECT id, building, layout, name, usermode_param, width, height FROM visfloors'
  28. for _, floor in ipairs(db:getall(query)) do
  29. if floor.usermode_param == "D" then
  30. default_startpage = floor.id
  31. screen_clean_page_building = floor.building
  32. screen_clean_width = floor.width
  33. screen_clean_height = floor.height
  34. end
  35. if floor.name == Screen_Clean_Page_Name then
  36. name_already_excist = true
  37. end
  38. end
  39.  
  40. -- Check if default page excists else exit script
  41. if default_startpage == nil then
  42. alert("Default page does not excists, exit screen clean page creation")
  43. -- Disable script
  44. script.disable(_SCRIPTNAME)
  45. --Exit script
  46. return
  47. end
  48.  
  49. -- Enable page adding
  50. Page_Adding = true
  51.  
  52. -- Check alert page already excists else exit script
  53. if name_already_excist == true then
  54. alert("Screen clean page already excist or name is already used, only HTML will be rewritten")
  55. -- Disable page adding
  56. Page_Adding = false
  57. end
  58.  
  59. -- Set sortorder to default sortorder value for counting
  60. highest_sortorder = 1
  61.  
  62. -- Get highest sortorder inside building part where default startpage is located
  63. query = 'SELECT sortorder FROM visfloors WHERE building == ' .. screen_clean_page_building .. ' ORDER BY sortorder DESC'
  64. for _, floor in ipairs(db:getall(query)) do
  65. if highest_sortorder <= floor.sortorder then
  66. highest_sortorder = floor.sortorder + 1
  67. end
  68. end
  69.  
  70. if Page_Adding == true then
  71. -- Create alert page if screen clean page doesn't exist
  72. db:insert('visfloors', {building = screen_clean_page_building, layout = 0, sortorder = highest_sortorder, name = Screen_Clean_Page_Name, bgrepeat = 0, bgfixed = 0, adminonly = 0, width = screen_clean_page_width, height = screen_clean_page_height,})
  73. end
  74.  
  75. -- Get page number of new created screen clean page
  76. screen_clean_page_number = db:getone('SELECT id FROM visfloors WHERE name=?', Screen_Clean_Page_Name)
  77.  
  78. -- Check if screen clean time (in seconds) is at least 1 second
  79. if Screen_Clean_Time < 1 then
  80. Screen_Clean_Time = 1
  81. end
  82.  
  83. -- Create HTML content
  84. page = [[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  85. <html xmlns="http://www.w3.org/1999/xhtml">
  86. <head>
  87. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  88. <title>homeLYnk Screen Clean Page</title>
  89. <style type="text/css">
  90. html, body {
  91. background-color: transparent;
  92. height: 100%;
  93. margin: 0px; background: #ffffff;
  94. opacity: 0.7;
  95. }
  96. .fullscreen {
  97. height: 100%;
  98. background-color: transparent;
  99. }
  100. </style>
  101. </head>
  102. <body>
  103. <div class="fullscreen" id="Wrapper" style="width:100%; margin-bottom: 0px; text-align: center; padding-bottom: 0px; min-height: 100%;">
  104. <div id="holder" style="height:20px; width:100%; resize:none; text-align: center; padding-top: 5px; font-family: Verdana, Geneva, sans-serif; font-weight: bold;">
  105. <label id="title">Screen Cleaner</label>
  106. </div>
  107. <div id="holder" style="height:20px; width:100%; resize:none; text-align: center; padding-top: 20px; font-family: Verdana, Geneva, sans-serif;">
  108. <label id="message"></label>
  109. </div>
  110. <div id="holder" style="height:20px; width:100%; resize:none; text-align: center; padding-top: 10px; font-family: Verdana, Geneva, sans-serif;">
  111. <label id="counter">0</label>
  112. </div>
  113. </div>
  114. <script type="text/javascript">
  115.  
  116. // ***** Make link to parent from iframe *****
  117. var p = window.parent, root, addr;
  118. var ip = location.host;
  119. var URL = "http://" + ip + "/scada/resources/img/";
  120. var Screen_Clean_Page_Name = "]] .. Screen_Clean_Page_Name .. [[";
  121. var Cleaning_Message = "]] .. Cleaning_Message .. [[";
  122. var Screen_Clean_Time = "]] .. Screen_Clean_Time .. [[";
  123. var Cleaning_Time_Prefix = "]] .. Cleaning_Time_Prefix .. [[";
  124. var Cleaning_Time_Suffix = "]] .. Cleaning_Time_Suffix .. [[";
  125. var Current_Plan = p.currentPlanId;
  126. var Screen_Clean_Time_Counter = Screen_Clean_Time
  127.  
  128. if (p && p.objectStore) {
  129.  
  130. document.getElementById('title').innerHTML = Screen_Clean_Page_Name;
  131. document.getElementById('message').innerHTML = Cleaning_Message;
  132. document.getElementById('counter').innerHTML = Cleaning_Time_Prefix + " " + Screen_Clean_Time_Counter + " " + Cleaning_Time_Suffix;
  133.  
  134. // Declare functions to disable mouseclicks on parent
  135. function pclickIE() {
  136. if (p.document.all) {
  137. return false;
  138. }
  139. }
  140.  
  141. function pclickNS(e) {
  142. if (p.document.layers||(p.document.getElementById &&! p.document.all)) {
  143. if (e.which==2||e.which==3) {
  144. return false;
  145. }
  146. }
  147. }
  148.  
  149. if (p.document.layers) {
  150. p.document.captureEvents(Event.MOUSEDOWN);
  151. p.document.onmousedown = pclickNS;
  152. } else {
  153. p.document.onmouseup = pclickNS;
  154. p.document.oncontextmenu = pclickIE;
  155. }
  156.  
  157. // Declare functions to disable mouseclicks on current document
  158. function clickIE() {
  159. if (document.all) {
  160. return false;
  161. }
  162. }
  163.  
  164. function clickNS(e) {
  165. if (document.layers||(document.getElementById&&!document.all)) {
  166. if (e.which==2||e.which==3) {
  167. return false;
  168. }
  169. }
  170. }
  171.  
  172. if (document.layers) {
  173. document.captureEvents(Event.MOUSEDOWN);
  174. document.onmousedown = clickNS;
  175. } else {
  176. document.onmouseup = clickNS;
  177. document.oncontextmenu = clickIE;
  178. }
  179.  
  180. // Create empty variable for loop countdown
  181. var countdown = "";
  182.  
  183. // Set user message to init value
  184. document.getElementById('counter').innerHTML = Cleaning_Time_Prefix + " " + Screen_Clean_Time_Counter + " " + Cleaning_Time_Suffix;
  185.  
  186. function countdowntimer() {
  187.  
  188. Screen_Clean_Time_Counter = Screen_Clean_Time_Counter -1 ;
  189.  
  190. if ( Screen_Clean_Time_Counter <= 0 ) {
  191. if ( countdown != "" ) {
  192. window.clearInterval(countdown);
  193. countdown = "";
  194. }
  195.  
  196. // Enable mouseclicks on parent and current document
  197. p.document.oncontextmenu=null;
  198. document.oncontextmenu=null;
  199.  
  200. Screen_Clean_Time_Counter = Screen_Clean_Time;
  201. p.setObjectValue({ address: ']] .. Screen_Clean_Trigger_Group_Address .. [[', rawdatatype: 1 }, 0, 'text');
  202. p.showPlan( Current_Plan );
  203.  
  204. // Set user message back to init value
  205. document.getElementById('counter').innerHTML = Cleaning_Time_Prefix + " " + Screen_Clean_Time_Counter + " " + Cleaning_Time_Suffix;
  206. }
  207.  
  208. if ( p.currentPlanId != ]] .. screen_clean_page_number .. [[ ) {
  209. Screen_Clean_Time_Counter = 0
  210. }
  211.  
  212. document.getElementById('counter').innerHTML = Cleaning_Time_Prefix + " " + Screen_Clean_Time_Counter + " " + Cleaning_Time_Suffix;
  213. }
  214.  
  215. // Add event listener on KNX addres for trigger screen clean function
  216. addr = p.Scada.encodeGroupAddress(']] .. Screen_Clean_Trigger_Group_Address .. [[');
  217. p.objectStore.addListener(addr, function(obj, type) {
  218.  
  219. // to avoid trigger on opening page */
  220. if (type == 'init') {
  221. // Make sure object value = false after init
  222. if ( obj.value == 1) {
  223. p.setObjectValue({ address: ']] .. Screen_Clean_Trigger_Group_Address .. [[', rawdatatype: 1 }, 0, 'text');
  224. }
  225. return;
  226. }
  227.  
  228. // close page
  229. if ( obj.value == 0) {
  230. if ( countdown != "" ) {
  231. window.clearInterval(countdown);
  232. countdown = "";
  233. }
  234.  
  235. // Enable mouseclicks on parent and current document
  236. p.document.oncontextmenu=null;
  237. document.oncontextmenu=null;
  238.  
  239. Screen_Clean_Time_Counter = Screen_Clean_Time;
  240. p.showPlan( Current_Plan );
  241.  
  242. // Set user message back to init value
  243. document.getElementById('counter').innerHTML = Cleaning_Time_Prefix + " " + Screen_Clean_Time_Counter + " " + Cleaning_Time_Suffix;
  244. }
  245.  
  246. // open page
  247. if ( obj.value == 1 ) {
  248.  
  249. // Jump to screen clean page (only if other page is showed)
  250. if ( p.currentPlanId != ]] .. screen_clean_page_number .. [[ ) {
  251. Current_Plan = p.currentPlanId;
  252. p.showPlan(]] .. screen_clean_page_number .. [[);
  253. }
  254.  
  255. // Disable mousclicks on parent and current document
  256. p.document.oncontextmenu = new Function("return false");
  257. document.oncontextmenu = new Function("return false");
  258.  
  259. // Create countdown loop
  260. if( countdown == "" ){
  261. countdown = window.setInterval("countdowntimer()",1000);
  262. }
  263. }
  264.  
  265. });
  266.  
  267. }
  268.  
  269. </script>
  270. </body>
  271. </html>
  272. ]]
  273.  
  274. -- Create temp HTML file to write to controller
  275. file = io.open("scada/resources/img/screenclean.html", "w")
  276. -- Write HTML file to controller
  277. file:write(page)
  278. -- Close temp HTML file
  279. file:close()
  280.  
  281. -- Check if HTML object already exist
  282. object_exists = false
  283. query = 'SELECT floor, type, name, params FROM visobjects'
  284. for _, visobject in ipairs(db:getall(query)) do
  285. if visobject.floor == screen_clean_page_number and (visobject.type == 9 or visobject.type == "9") and visobject.name == "screenclean" then
  286. object_exists = true
  287. end
  288. end
  289.  
  290. if Page_Adding == true then
  291. -- Create html object on alertpage
  292. db:insert('visobjects', {floor = screen_clean_page_number, type = 9, params = '{"source":"url","url":"/scada/resources/img/screenclean.html","width":' .. screen_clean_width .. ',"height":' .. screen_clean_height .. '}', locx = 0 , locy = 0 , name = "screenclean", notouch = 1, nobg = 1,})
  293. log ("Screen clean page is added")
  294. elseif object_exists == false then
  295. -- Create html object on excisiting alertpage
  296. db:insert('visobjects', {floor = screen_clean_page_number, type = 9, params = '{"source":"url","url":"/scada/resources/img/screenclean.html","width":' .. Alert_Frame_Width .. ',"height":' .. Alert_Frame_Height .. '}', locx = 0 , locy = 0 , name = "screenclean", notouch = 1, nobg = 1,})
  297. log ("HTML is added to excisiting screen clean page")
  298. else
  299. log ("HTML on screen clean page is updated")
  300. end
  301.  
  302. -- Disable script when done automaticly
  303. script.disable(_SCRIPTNAME)

 

Created by Erwin van der Zwart from Schneider Electric