This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Alarm page demo using javascript and tag
#1
Hello!

I haven't found any slim alarm notification example so I created one (using forum magic search button and all kind of code examples). I bet there is quite many good programmers who maybe want to add some additional features. Would be nice to see these in this thread...

About page. It gonna check alarms by tags and shows in two separate table. One is active alarm table and another is event table. It's possible to delete all past events as well. 
Integration should take less than few minutes.
Alarm page date and time is actual alarm variable update time. Event date and time is time when system checked event variable (not actual alarm time).

Common functions:
Code:
123456
function eventlog(text)   local max = 30                             -- MAX NUMBER OF ENTRIES   text = os.date('%d/%m/%Y %T ') .. text   storage.exec('lpush', 'eventlog', text)   storage.exec('ltrim', 'eventlog', 0, max - 1) end

Resident script 3s:

1. Define group address base
2. Add tag-s what to check periodically
3. On first run change first three lines to true. Later change back to false
4. Activate script


Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
create_eventlog_file = false                 --Execute on first run to create lp file create_all_log_file = false                --Execute on first run to create lp file create_group_addresses = false                --Execute on first run to create group addresses group_address_base = '51/1/'                    --System generates two group addresses. Make sure that addresses are free (x/x/1 and x/x/2). alarm_tags = {'SV1','SV2','SV3','EMAIL','HEATING'}        --These are alarm tags what is gonna checked constantly ------------------------------------------------------- data1 = {    type = 'event',    name = 'ALARM PAGE - Update frontend',    active = 1,    params = group_address_base .. '1',    subparams = 0,    script = [[val = event.getvalue()       if val then            grp.checkupdate("]] .. group_address_base .. [[1", 0)         end]],    category = '',    description = 'Automatically generated', } data2 = {    type = 'event',    name = 'ALARM PAGE - Delete eventlog',    active = 1,    params = group_address_base .. '2',    subparams = 0,    script = [[val = event.getvalue()       if val then   storage.delete('eventlog')   grp.update(']]..group_address_base .. [[2',0)   grp.update(']]..group_address_base .. [[1',1) end]],    category = '',    description = 'Automatically generated', } function create_scripts(data)   exists = script.get(data.name)   if not exists then      db:insert('scripting', data)      data.id = db:getlastautoid()      script.save(data, true)      script.reloadsingle(data)   end end function createga(groupaddress,datatype2,name2)   exist = grp.alias(groupaddress)   if exist == nil then     address = grp.create({     datatype = datatype2,     address = groupaddress,     name = name2,     comment = 'Automatically created object',     units = '',     tags = { },     })   end end if create_group_addresses then     createga(group_address_base .. 1,dt.bool,'ALARM PAGE - Update frontend')   createga(group_address_base .. 2,dt.bool,'ALARM PAGE - Delete eventlog')   os.sleep(0.5)   create_scripts(data1)   create_scripts(data2) end function file_exists(name)   local f = io.open(name, "r")   return f ~= nil and io.close(f) end if create_eventlog_file then     fil_name = '/www/user/eventlog.lp'     if file_exists(fil_name) == false then     dst = fil_name     io.writefile(dst, [[<?     require('apps')     items = storage.exec('lrange', 'eventlog', 0, 999)     text = table.concat(items, '\r\n')     print(text)     ?>]])   end end if create_all_log_file then     fil_name = '/www/user/all_alarms.lp'     if file_exists(fil_name) == false then     dst = fil_name     io.writefile(dst, [[<?     require('json')     require('genohm-scada')     mydata =storage.get('ALL_ALARMS')     mydata = json.encode(mydata)     print(mydata)     ?>]])     end end function check_events(tag, GA)   index = 1   all_alarms = {}   update_table = false   for it=1, #tag, 1 do     old = {}     old_val = storage.get(tag[it] .. '_sent')     update_storage = false     events = grp.tag(tag[it])     for i=1, #events, 1 do       if old_val == nil then                            --if no info - update it to latest info         update_storage = true         update_table = true       end       old[i] = {sent =events[i].value}       all_alarms[index] = {status =events[i].value, description =events[i].name, date =os.date('%d/%m/%Y', events[i].updatetime), time =os.date(' %T ', events[i].updatetime), tag =events[i].tagcache }       index = index + 1       if events[i].value == true then         if old_val ~= nil then           if old_val[i].sent == false then             eventlog('1 ' .. events[i].tagcache .. ' ' .. events[i].name) -- 1 means alarm             update_storage = true             update_table = true           end         end       elseif events[i].value == false then         if old_val ~= nil then           if old_val[i].sent == true then             eventlog('0 ' .. events[i].tagcache .. ' ' .. events[i].name ) -- 0 means ok             update_storage = true             update_table = true           end         end       end     end     if update_storage then       storage.set(tag[it] ..'_sent',old)     end    end   if update_table then       storage.set('ALL_ALARMS',all_alarms)     os.sleep(0.5)     grp.update(group_address_base .. '1', 1)   end end check_events(alarm_tags)

Custom Javascript:

1. Define your plan ID where alarm and event table gonna be placed
2. Edit updateTableGA address. 
Do that on both scripts...

Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////ALARM PAGE - ALARM LOG///////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// $(function() {   var planID = 7                                ////change this   var updateTableGA = '51/1/1'                  ////change this   $('body').on('showplan', function(event, id) {       var planid = window.currentPlanId;         grp.listen(updateTableGA, function(object) {       if (object.value == true || planid == planID ){         $(function() {           const tableArray = [];           var DataArray = []           $.get( "/user/eventlog.lp", function( data ) {             chartdata = data           });           setTimeout(() => {    //little delay because reading chart data file             const lines = chartdata.split('\n');             lines.forEach(line => {               // Split the line by space               const parts = line.split(' ');               // Extract date, time, and description               const date = parts[0];               const time = parts[1];               const status = parts[2];               const tag = parts[3];               const description = parts.slice(4).join(' '); // Join the remaining parts as description               // Push the data to the table array               if (date != ''){                 tableArray.push({ date, time, description,tag, status });               }             });             for (var i = 0; i <= tableArray.length-1; i++) {               DataArray[i] = { date: tableArray[i].date, time: tableArray[i].time, description: tableArray[i].description, status:tableArray[i].status, tag:tableArray[i].tag }             }             console.log(DataArray)             // Function to generate the HTML structure for the table             function generateTable(data, statusIconColor1, statusIconColor0) {               var tableHtml =   '<table id="data-table" style="background-color: #212120;" >' +                                 '<thead >' +                                     '<tr>' +                                     '<th class="align-left text-col">DATE</th>' +                                     '<th class="align-left text-col">TIME</th>' +                                     '<th class="align-left text-col">DESCRIPTION</th>' +                                     '<th class="align-center text-col">SYSTEM</th>' +                                     '<th class="align-center text-col">STATUS</th>' +                                     '</tr>' +                                 '</thead>' +                                 '<tbody >';               data.forEach(function(item, index) {                 var statusIconColor = (item.status === "1") ? statusIconColor1 : statusIconColor0;                 var statusIconStyle = 'color:' + statusIconColor + '; text-align: center;';   console.log(item)                 tableHtml += '<tr>' +                   '<td class="align-left  text-col">' + item.date + '</td>' +                   '<td class="align-left  text-col">' + item.time + '</td>' +                   '<td class="align-left  text-col">' + item.description + '</td>' +                   '<td class="align-center  text-col">' + item.tag + '</td>' +                   '<td class="align-center"><span style="' + statusIconStyle + '">' + ((item.status === true) ? "⬤" : "⬤") + '</span></td>' +                   '</tr>';               });               tableHtml += '</tbody></table>';               // Create a style element and append it to the document head               var styleElement = document.createElement('style');               styleElement.innerHTML = '#data-table td.align-center {text-align: center;} #data-table td.align-left {text-align: left;}  #data-table th.align-center {text-align: center;}'+                 '.text-col { color: #E5E5E5 }';               document.head.appendChild(styleElement);               return tableHtml;             }                         $('#data-table').remove();             html_code = generateTable(DataArray, '#FF0000', "#00ff00")             var el = $('<div>' + html_code + '</div>').css({                 position: 'absolute',                 width: '750px',                 //height: '300px',                 left: '1050px',                 bottom: '100px',                 top: '250px',                 zIndex: 999,             }).appendTo('#plan-'+planID);           }, 500);         })       }     })   }) }) ////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////ALARM PAGE - ACTIVE ALARMS///////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// $(function() {   var planID = 7                               ///change this   var updateTableGA = '51/1/1'                 ///change this   $('body').on('showplan', function(event, id) {     var planid = window.currentPlanId;     grp.listen(updateTableGA, function(object) {       if (object.value == true || planid == planID ){         // Fetch alarm data         $.get( "/user/all_alarms.lp", function( data ) {           var chartdata = JSON.parse(data);           // Generate table with alarm data after a delay           setTimeout(function() {             generateTable(chartdata);           }, 500); // Adjust the delay time as needed         });       }     });     // Function to generate the HTML structure for the table     function generateTable(data) {       // Filter out data where value is false       var filteredData = data.filter(function(item) {         return item.status === true;       });     // Format date and time strings for proper parsing       filteredData.forEach(function(item) {         // Convert date from "DD/MM/YYYY" to "YYYY-MM-DD"         var dateParts = item.date.split('/');         item.date = dateParts[2] + '-' + dateParts[1] + '-' + dateParts[0];         // Trim and remove leading whitespace from time         item.time = item.time.trim();       });       // Sort filteredData by date and time in ascending order       filteredData.sort(function(a, b) {         var dateA = new Date(a.date + ' ' + a.time);         var dateB = new Date(b.date + ' ' + b.time);         return dateB - dateA; // Reverse order to sort newest first       });       var tableHtml =   '<table id="data-table2" style="background-color: #212120;" >' +                         '<thead >' +                             '<tr>' +                               '<th class="align-left text-col">DATE</th>' +                               '<th class="align-left text-col">TIME</th>' +                               '<th class="align-left text-col">DESCRIPTION</th>' +                                                      '<th class="align-center text-col">SYSTEM</th>' +                               '<th class="align-center text-col">STATUS</th>' +                             '</tr>' +                         '</thead>' +                         '<tbody >';       filteredData.forEach(function(item) {         console.log(item)         var statusIconColor = (item.status === true) ? '#FF0000' : '#00ff00';         var statusIconStyle = 'color:' + statusIconColor + '; text-align: center;';         tableHtml += '<tr>' +             '<td class="align-left text-col">' + item.date + '</td>' +             '<td class="align-left text-col">' + item.time + '</td>' +             '<td class="align-left text-col">' + item.description + '</td>' +               '<td class="align-center text-col" >' + item.tag + '</td>' +             '<td class="align-center"><span style="' + statusIconStyle + '">' + ((item.status === "1") ? "⬤" : "⬤") + '</span></td>' +             '</tr>';       });       tableHtml += '</tbody></table>';       // Remove existing table if it exists       $('#data-table2').remove();       // Create the table and append it to the same location       var $table = $(tableHtml);       $table.css({         position: 'absolute',         width: '790px',         left: '105px',         bottom: '100px',         top: '640px',         zIndex: 1       });       $('#plan-' + planID).append($table);       // Create a style element and append it to the document head       var styleElement = document.createElement('style');       styleElement.innerHTML = '#data-table2 td.align-center {text-align: center;} #data-table2 td.align-left {text-align: left;}  #data-table2 th.align-center {text-align: center;}'+         '.text-col { color: #E5E5E5; }'       document.head.appendChild(styleElement);     }   }); });

Email notification part is running on another script right now but maybe I'm gonna integrate into this script in future.

Attached Files Thumbnail(s)
   
Reply


Forum Jump: