Back Midas Rome Roody Rootana
  Midas DAQ System, Page 27 of 146  Not logged in ELOG logo
New entries since:Wed Dec 31 16:00:00 1969
ID Date Author Topicdown Subject
  717   08 Sep 2010 Stefan RittInfoYBOS support now optional, disabled by default
> It looks like some example drivers in .../drivers/class want to link against YBOS libraries. 
> This fails because ybos.o is missing from the MIDAS library.

I fixed the class drivers in meantime (SVN 4814).

There is however another problem: The lazylogger needs YBOS support compiled in if the FTP transfer mode is used. 
At PSI we are stuck at the moment to FTP, so we still need YBOS there (although none of the data is in YBOS format). 
Maybe there is a chance that this will be fixed some time and we can get rid of YBOS.
  718   13 Sep 2010 Konstantin OlchanskiInfomodified mhttpd history panel editor
mhttpd.c svn rev 4823 implements a modified history planel editor. all previous functions should work 
as before (minus new bugs).

New experimental functions added:

a) there is a new column "Order" containing numbers 10, 20, 30, etc. If you change "30" to (say) "15" 
and press "refresh", the history variables will be reordered according to the new values. If you change 
(say) "10" to "" (empty) or "0" and press "refresh", this variable will be deleted. (But there is a UI wart - if 
you accidentally change the order value to something non-numeric (i.e. "aaa1" or " 1" (leading space) 
and press "enter", the variable will be immediately deleted from odb - "enter" works as "refresh + save" 
- should probably work as "refresh" requiring explicit press on the "save" button).

b) there is a new button "List all" to list all existing variables - next to each variable is a checkbox - 
select any checkboxes and press "add selected" to add selected variables to the history plot. You may 
find this function useful (or not), depending on how many variables you have in your history. For 
T2K/ND280 this is still not good enough (there are still too many variables) and I want to change this to 
a 3 level (equipment, history event, history tag) expandable/collapsable tree (or whatever is simplest to 
implement) - to permit the user to quickly zoom on the interesting variables.

I may still tweak with the UI of these new functions, but the basic functionality (reorder+delete and 
selection of multiple variables from a list) seems to be solid. Comments and suggestions on how to 
make it work the best for your experiment are very welcome.

K.O.
  719   17 Sep 2010 Konstantin OlchanskiInfomodified mhttpd history panel editor
> mhttpd.c svn rev 4823 implements a modified history planel editor. all previous functions should work 
> as before (minus new bugs). New experimental functions added:
> 
> a) there is a new column "Order" containing numbers 10, 20, 30, etc. ...

While this seems to work well enough, it might remain a function for "advanced users". For novice
users, a simpler gui, i.e. with "move up" and "move down" buttons, would have been "better", or
at least more familiar. (However I have double plus negative experience using nice
looking "move up and down buttons" to rearrange something I actually need to rearrange,
so I have no interest in implementing something I do not want to use. Think about moving
an item all the way from the bottom of a 10 item list to the very top. No do this not as a mental
exercise, but on a slow loading mhttpd web page running somewhere in Japan).

> b) there is a new button "List all variables" to list all existing variables

Some improvement here (mhttpd.c svn 4823): variables are organized by equipment and by history event
into an expandable list. (I already know that this list expansion does not play well with web page
scrolling, same problem exists in the ODB inline editor).

Again, midas users who have a small number of history events may find this new function
not so useful, but the old way was pretty much unusable for T2K/ND280.

Also, for users with a large number of history events, there 2 new ODB variables
/History/MaxDisplayEvents and /History/MaxDisplayTags which limit the maximum
number of events and tags listed in the old scrollable "option" selector history editor.
For the T2K/ND280 case, this reduces the size of the web page and reduces the page load
time quite substantially. (I picked default values of 20 events and 200 tags quite arbitrary,
perhaps the default should have been "no limit", but then nobody would benefit from this
possibility to substantially reduce web page load times - unless they read documentation (yea, right!)
that is not yet written).

K.O.
  720   17 Sep 2010 Konstantin OlchanskiInfoAdded mserver host based access control
In svn rev 4825, I added host based access control to mserver (the MIDAS RPC server). The implementation 
is a verbatim copy mhttpd host based access control list (-a command line switch).

Same as for mhttpd, "mserver -a hostname" enables access control and only permits access from listed 
host names (supply multiple -a switches for multiple hostnames).

This access control does not apply yet for the MIDAS RPC socket connections between MIDAS clients used 
to do RPC callbacks, i.e. to request run transitions. Each MIDAS program is listening for MIDAS RPC 
connections on a high TCP port and at present accepts connections from anybody. To implement access 
controls one could add "-a" switches to every midas application (lot of work) or fill the access control list 
automatically from ODB. mserver still has to use the "-a" command line switches because there is no ODB 
connection when it has to accept or reject remote sockets.

svn rev 4825
K.O.
  721   20 Sep 2010 Stefan RittInfomodified mhttpd history panel editor
Just some idea:

The ultimate solution to that would be to do that completely JavaScript driven. You load ONCE the list of all 
variables into a local array, then sort this into your history panel LOCALLY. When I did the original mhttpd 
history config page, there was not much JavaScript around, but today this would be the ultimate option. It 
even supports drag-and-drop. So let's keep that in mind for the future.

- Stefan
  722   23 Sep 2010 Konstantin OlchanskiInfoFixed ODB corruption by javascript ODBGet(nonexistant)
Prior to odb.c rev 4829 and mhttpd.c rev 4830 committed a few minutes ago, HTML javascript 
ODBGet("/non_existant_odb_entry") caused ODB corruption requiring ODB reload from backup file.

It turns out that ODBGet() tries to create ODB entries if they do not already exist, but because ODBGet() was 
called without the "type", "length", etc arguments, the mhttpd "jset" command was issued with "type" set to 
zero. This resulted in a db_create_key() call with "type" set to zero which created an invalid ODB entry. 
odb.c rev 4829 adds a check for "type<=0" (check for "type>=TID_LAST" was already there).

In addition, mhttpd.c rev 4830 adds a "jset" check for type==0.
K.O.
  723   23 Sep 2010 Konstantin OlchanskiInfoExample javascript midas page
We had javascript ODBGet() and ODBSet() functions for some time now, permitting implementation of 
"page-reload-free" "self-updating" web pages. I finally got around to put all the javascript bits together 
to actually implement such a page. The main difference from a normal MIDAS "custom" page is the data 
update method - instead of fully reloading the page (via "<meta http-equiv="Refresh" content="60">" 
or javascript location.reload()) - I use ODBGet() to read new data from ODB and HTML DOM access to 
update it on the web page. Note that this is not quite AJAX because the load() function is synchronous 
and (i.e. on the MacOS 10.6 Safari web browser) completely freezes the web browser during data update 
(but no freeze on the Linux Firefox, go figure). An asynchronous ODBGet() should be easy to implement, 
but I can see how a fully asynchronous load() function would lose some of the simplicity of this 
example. (I hope elog does not mangle my example too much).
K.O.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>PostAmp control</title>
  </head>

  <body>
    <h1>PostAmp control</h1>

    <script src='mhttpd.js'></script>
    <script type="text/javascript">

var numcrates = 2;
var numpachan;
var reloadTimerId = 0;

function load()
{
  document.getElementById('LastUpdated').innerHTML = "Reloading..." + new Date;

  var crates_table = document.getElementById('crates');
  var slots_table = document.getElementById('cards');

  var Csn = ODBGet('/Equipment/PostAmp/Settings/PACtrlSerialNo[*]');
  for (var i = 0; i < numcrates; i++)
    crates_table.rows[1+i].cells[1].innerHTML = Csn[i];

  var MaxTemp = ODBGet('/Equipment/PostAmp/Variables/MaxTemp[*]');
  for (var i = 0; i < numcrates; i++)
    crates_table.rows[1+i].cells[2].innerHTML = MaxTemp[i];

  var D_TP = ODBGet('/Equipment/PostAmp/Variables/D_TP[*]');
  var M_TP = ODBGet('/Equipment/PostAmp/Variables/M_TP[*]');

  for (var i = 0; i < numcrates; i++)
    crates_table.rows[1+i].cells[3].innerHTML = D_TP[i] + " / " + M_TP[i];

  var sn = ODBGet('/Equipment/PostAmp/Settings/PASerialNo[*]');
  for (var i = 0; i < numpachan; i++)
    slots_table.rows[1+i].cells[1].innerHTML = sn[i];

  var VoltageP  = ODBGet('/Equipment/PostAmp/Variables/VoltageP[*]');
  for (var i = 0; i < numpachan; i++)
    slots_table.rows[1+i].cells[2].innerHTML = VoltageP[i];

  var VoltageM  = ODBGet('/Equipment/PostAmp/Variables/VoltageM[*]');
  for (var i = 0; i < numpachan; i++)
    slots_table.rows[1+i].cells[3].innerHTML = VoltageM[i];

  var Temp      = ODBGet('/Equipment/PostAmp/Variables/Temp[*]');
  for (var i = 0; i < numpachan; i++)
    slots_table.rows[1+i].cells[4].innerHTML = Temp[i];

  var D_VTp     = ODBGet('/Equipment/PostAmp/Variables/D_VTp[*]');
  var M_VTp     = ODBGet('/Equipment/PostAmp/Variables/M_VTp[*]');

  for (var i = 0; i < numpachan; i++)
    slots_table.rows[1+i].cells[5].innerHTML = D_VTp[i] + " / " + M_VTp[i];

  var D_Thresh  = ODBGet('/Equipment/PostAmp/Variables/D_Thresh[*]');
  var M_ThreshA = ODBGet('/Equipment/PostAmp/Variables/M_ThreshA[*]');
  var M_ThreshB = ODBGet('/Equipment/PostAmp/Variables/M_ThreshB[*]');

  for (var i = 0; i < numpachan; i++)
    slots_table.rows[1+i].cells[6].innerHTML = D_Thresh[i] + " / " + M_ThreshA[i] + " / " + M_ThreshB[i];

  document.getElementById('LastUpdated').innerHTML = "Last updated: " + new Date;
}

function reload()
{
  clearTimeout(reloadTimerId);
  load();
  reloadTimerId = setTimeout('reload()', 10000);
}

function main()
{
  clearTimeout(reloadTimerId);

  document.writeln("<p id=LastUpdated>Last updated: </p>");

  document.writeln("<input type=button value='Reload' onClick='reload();'></input>");
  document.writeln("<input type=button value='TP enable' onClick='clearTimeout(reloadTimerId); 
ODBSet(\"/Equipment/PostAmp/Settings/Command\", \"gtp 1\"); reload();'></input>");
  document.writeln("<input type=button value='TP disable' onClick='clearTimeout(reloadTimerId); 
ODBSet(\"/Equipment/PostAmp/Settings/Command\", \"gtp 0\"); reload();'></input>");
  //document.writeln("<input type=button value='Thresh 100' onClick='clearTimeout(reloadTimerId); 
ODBSet(\"/Equipment/PostAmp/Settings/Command\", \"gvth 100\"); reload();'></input>");
  //document.writeln("<input type=button value='Vtest 200' onClick='clearTimeout(reloadTimerId); 
ODBSet(\"/Equipment/PostAmp/Settings/Command\", \"gvtest 200\"); reload();'></input>");

  document.writeln("Set VTp: ");
  document.writeln("<input type=input size=5 value='200' onKeyPress='if (event.keyCode==13) { 
clearTimeout(reloadTimerId); ODBSet(\"/Equipment/PostAmp/Settings/Command\", \"gvtest \" + 
this.value); reload(); }'></input>");

  document.writeln("Set Thresh: ");
  document.writeln("<input type=input size=5 value='100' onKeyPress='if (event.keyCode==13) { 
clearTimeout(reloadTimerId); ODBSet(\"/Equipment/PostAmp/Settings/Command\", \"gvth \" + 
this.value); reload(); }'></input>");

  document.write("<table id=crates border=1>");
  
  document.writeln("<tr align=center>");
  document.writeln("<th>Crate");
  document.writeln("<th>SerialNo");
  document.writeln("<th>MaxTemp");
  document.writeln("<th>D_TP / M_TP");
  document.writeln("</tr>");
  

  for (c = 0; c < numcrates; c++) {
    document.writeln("<tr align=center>");
    document.writeln("<td>" + c);
    document.writeln("<td>sn");
    document.writeln("<td>maxtemp");
    document.writeln("<td>d_tp/m_tp");
    document.writeln("</tr>");
  }
  document.writeln("</table>");
  
  document.write("<table id=cards border=1>");
  
  document.writeln("<tr align=center>");
  document.writeln("<th>Crate/Slot");
  document.writeln("<th>SerialNo");
  document.writeln("<th>V+5");
  document.writeln("<th>V-5");
  document.writeln("<th>Temp");
  document.writeln("<th>VTp");
  document.writeln("<th>Thresh");
  document.writeln("</tr>");
  
  for (c = 0; c < numcrates; c++) {
    for (s = 1; s <= 24; s++) {
      xchan = (c*24) + (s-1);
      document.writeln("<tr align=center>");
      document.writeln("<td>" + c + "/" + s + "/" + xchan);
      document.writeln("<td>sn");
      document.writeln("<td>vp");
      document.writeln("<td>vm");
      document.writeln("<td>temp");
      document.writeln("<td>d_vtpm/m_vtp");
      document.writeln("<td>d_thresh/m_thresha/m_threshb");
      document.writeln("</tr>");
    }
  }
  document.writeln("</table>");

  numpachan = xchan+1;
}

main();
reload();

//ODBSet('/Equipment/FgdWiener01/Settings/outputSwitch[8]', value);

    </script>

    <hr>
    <address><a href="xxx@xxx">Expt S1249</a></address>
<!-- Created: Tue Sep 21 15:44:39 PDT 2010 -->
<!-- hhmts start -->
Last modified: Wed Sep 22 08:30:31 PDT 2010
<!-- hhmts end -->
  </body>
</html>
  724   23 Sep 2010 Stefan RittInfoExample javascript midas page
> We had javascript ODBGet() and ODBSet() functions for some time now, permitting 
implementation of 
> "page-reload-free" "self-updating" web pages. I finally got around to put all 
the javascript bits together 
> to actually implement such a page.

Unfortunately the page has tons of JavaScript errors, probably happened during 
copy-and-paste to elog. Note that 
such files are better places as attachment. I attached a screen dump from the JS 
debugger inside Chrome which I 
use normally to debug JS.
Attachment 1: js_error.png
js_error.png
  725   23 Sep 2010 Stefan RittInfoAnother example of a JavaScript midas page
Please find attached another example of a JavaScript (JS) page using the 
ODBGet/Set functions. 

In contrast to the previous posting, the page is not constructed via the 
document.writeln() function, but written directly in HTML and modified through the 
"innerHTML = ..." functionality. 

It is a control page for our beamline, which gets updated in the background. In 
addition, the user can set the beamline to three predefined settings which are 
stored in an array at the top of the page. As an little extra there is a progress 
bar, which is updated locally via JS since changing the beamline takes a while. 
The progress bar is implemented as a table with variable width, and dynamically 
updated by the JS program. The second attachment is a screen dump from such a 
switching process. Since only values in the ODB are changed, you can try it 
yourself without actually modifying a PSI beam line ;-)
Attachment 1: beamline.html
Attachment 2: beamline.png
beamline.png
  726   24 Sep 2010 Konstantin OlchanskiInfoExample javascript midas page
> > We had javascript ODBGet() and ODBSet() functions for some time now, permitting 
> implementation of 
> > "page-reload-free" "self-updating" web pages. I finally got around to put all 
> the javascript bits together 
> > to actually implement such a page.
> 
> Unfortunately the page has tons of JavaScript errors, probably happened during 
> copy-and-paste to elog.

The attached errors all seem to be from cut-and-paste line breaks in the long "document.writeln()" statements. 
When the page runs, there are no errors from Firefox and Safari.

This example uses "document.writeln()" because the number of PostAmp devices displayed in the table is not 
known in advance and is potentially read from ODB at page load time.

K.O.
  727   24 Sep 2010 Stefan RittInfoExample javascript midas page
> The attached errors all seem to be from cut-and-paste line breaks in the long "document.writeln()" statements. 
> When the page runs, there are no errors from Firefox and Safari.

Then it would be good if you re-submit the file as an attachment so that other people can use it.

> This example uses "document.writeln()" because the number of PostAmp devices displayed in the table is not 
> known in advance and is potentially read from ODB at page load time.

This was not a criticism but just to show that there are different ways of constructing such a page, depending on the 
needs. So people have the choice. Anyhow I think it's very good to have some working examples for people to start 
with.
  729   29 Oct 2010 Konstantin OlchanskiInfomlogger.c 4858-4862 busted
Please note that mlogger does not work (crashes on run start) starting with svn
rev 4858, fixed in svn 4862. If you have to use this busted version of mlogger,
the crash is fixed by update of history_midas.c to svn rev 4862 or set ODB
/Logger/WriteFileHistory to 'n'. Sorry for the inconvenience. K.O.
  730   02 Nov 2010 chris pearsonInfomhttpd: Extra entries on status page
   A couple of experiments at triumf wanted certain important odb variables
displayed on their status page.  (There was already the possibility to show the
run comment)
   A new folder "/Experiment/Status Items" was created containing links to the
variables of interest, these items are show on the status page, under the run
comment (if any), in 3 columns.

the code from mhttpd.c:show_status_page()
between
   /*---- run comment ----*/
and
   /*---- Equipment list ----*/
is attached
Attachment 1: status.c
   /*---- run comment ----*/

   /* Also Status items values (including run comment)               */
   /* want Run Comment to be shown first but, instead of             */
   /* storing everything and then displaying in our chosen order     */
   /* find comment first, and then show other items as they are seen */
   db_find_key(hDB,0,"/Experiment/Status Items", &hkey);
   if( hkey ){                               /* If this Directory exists ... */
      char status_data[1000];              /* same size as str defined above */
      db_find_key(hDB,0,"/Experiment/Status Items/comment", &hsubkey);
      if( hsubkey ){               /* Show Run comment before other items ...*/
         db_get_key(hDB, hsubkey, &key);
         size = sizeof(status_data);
         if( (status = db_get_data(hDB, hsubkey, status_data, &size, key.type))
	     == DB_SUCCESS && key.num_values == 1 && key.type != TID_KEY ){
            db_sprintf(str, status_data, key.item_size, 0, key.type);
            rsprintf("<tr align=center><td colspan=6 bgcolor=#E0E0FF><b>%s</b></td></tr>\n", str);
	 }
     }
     /* each key can also be a link: we want link data and original key name */
     /* => get key twice: follwing links(for data) not follow (for org name) */
     int item_count=0;                       /* Total number of things shown */
     for(i=0; ; i++){                       /* Loop over status-item subkeys */
        db_enum_key(hDB, hkey, i, &hsubkey);/*get ith key data, follow links */
        if( ! hsubkey ){ break; }                        /* (end of subkeys) */
        db_get_key(hDB, hsubkey, &key);     /*          ...                  */
        /* key data has unknown type, copy to status_data then conv -> string*/
        size = sizeof(status_data);   /* Don't try to display arrays/subdirs */
        if( (status=db_get_data(hDB,hsubkey, status_data, &size, key.type)) != 
           DB_SUCCESS || key.num_values>1 || key.type == TID_KEY ){ continue; }
        db_sprintf(str, status_data, key.item_size, 0, key.type); /*->string */

        db_enum_link(hDB, hkey, i, &hsubkey);    /* Get ith subkey link name */
        db_get_key(hDB, hsubkey, &key);          /*           ...            */
        if( strstr(key.name,"comment") ){ continue; } /* skip comment (done) */

        if( ! (item_count % 3) ){ rsprintf("<tr>"); }
        rsprintf("<td colspan=2 align=center bgcolor=#%06X>%s: <b>%s</b></td>",
           0xD0D0FF, key.name, str );
        if( ! (++item_count % 3) ){ rsprintf("</tr>\n"); }
     }
     while( (item_count % 3) ){         /* complete any partial row of 3 ... */
        rsprintf("<td colspan=2 bgcolor=#%06x></td>", 0xD0D0FF );
        if( (++item_count % 3) == 0 ){ rsprintf("</tr>\n"); }
     }
   } /* end of if existence of "status items" hkey */

   // Original Run Comment Section ...
   //   size = sizeof(str);
   //   if (db_get_value(hDB, 0, "/Experiment/Run parameters/Comment", str,
   //                    &size, TID_STRING, FALSE) == DB_SUCCESS)
   //      rsprintf("<tr align=center><td colspan=6 bgcolor=#E0E0FF><b>%s</b></td></tr>\n", str);

   /*---- Equipment list ----*/
  733   15 Dec 2010 Stefan RittInfoNew source file structure of MSCB tree
A long planned modification of the source file structure of the MSCB subsystem has been implemented. This is however only for those people who do actively participate in micro controller programming with MSCB. The idea behind this is tha the central include file mscbemb.h had a section for each new project. So whenever a new project was added, this file had to be modified which is clumsy and hard to maintain. Therefore I took the project specific sections out of this file and put it into a config.h file, which is separate for each project (very similar to VxWorks). So the folder tree now looks like this:
midas\mscb\embedded
  \include                <- place for framework include file mscbemb.h
  \lib                    <- precompiled TCP/IP library for SCS-260 submaster
  \src                    <- framework sources mscbmain.c and mscbutil.c
  \<project1>             <- separate folder for project1
      config.h            <- config file for project1
  \<project2>             <- separate folder for project2
      config.h            <- config file for project2
  ...
  \experiment
     \<experiment1>
     \<experiment2>

So each project has it's own config.h, which is included from the central mscbemb.h and can be used to enable certain features of the framework without having to change the framework itself. The "projectx" folders contain devices which are used across several experiments and sometimes also between institutes (PSI and TRIUMF). If you make a device which is only used in a specific experiment, this should go under \experiment with the name of the device or the experiment as a subdirectory. I encourage everybody to submit even specific projects to the subversion system since they can sometimes be useful for others to look at some example code.

A few other things have to be changed in order to adapt to the new structure:

  • The framework files mscbmain.c mscbutil.c and mscbemb.h have moved and therefore they have to be re-added to the projects in the Keil MicroVision Development Environment.
  • The name of the device should not be defined under compiler settings (Project Options/C51/Preprocessor Symbols), but put directly into the config.h file associated with the project.
  • The include paths in the compile have to be changed and point to \midas\mscb\embedded\include
  • The file config.h has to be copied from a similar project and adjusted to fit the new project.

I did remove all project specific sections from mscbemb.h in the current SVN version, so certain projects (FDB_008 at TRIUMF, CRATE_MONITOR and PT100X8 at PSI) have to retrieve the settings (like LED ports etc.) from the old mscbemb.h and put it into the config.h file.

Furthermore there is a new STARTUP_VDDMON.A51 file in the src directory which should be added to each project. This was recommended by the micro controller manufacturer and fixes cases where the EEPROM contents of the CPU gets lost from time to time during power up.

The last thing is that PSI switched to MicroVision 4 as the development environment, so I added new project files (*.uvproj and *.uvopt instead *.Uv2), but I left the old ones there in case someone still has the uV2 environment. They are however not maintained any more.

If there is any problem with the new structure or you have some comments, please don't hesitate to contact me.


- Stefan
  745   16 Feb 2011 Konstantin OlchanskiInfoNotes on MIDAS history
Some notes on the MIDAS history.

MIDAS documentation at
http://midas.psi.ch/htmldoc/F_History_logging.html
describes:

- midas equipment concepts
- midas equipment event ids
- midas data banks
- midas history concepts
- history records (correspond to data banks)
- history record ids (correspond to equipment ids)
- history tags (describe the structure
- describes the code path from the user read function through odb to the mlogger to the history file
- midas history file internal data format
- documents the tool for looking inside history files - mhdump

But some things remain unclear after reading the documentation - where are the history definitions 
saved? what happens if an equipment is deleted or renamed? what's all the mumbling about 
/History/Events and /History/Tags? what's this /History/PerVariableHistory?

As I go through my review of the MIDAS history code, I will attempt to clarify some of this information.

1) PerVariableHistory.

The default value of 0 is intended to operate the midas history in "traditional" mode. In this mode:
- there is one history record for each equipment
- history record id is equal to the equipment id
- /History/Events and /History/Tags are not required and can be safely deleted

The downside of this history mode is that there is only one history record per equipment. If some 
equipment has many banks not all of which are updated all at the same time, every time one bank is 
updated, data for all banks is written to the history file, even if data in all those other banks had not 
changed. The result is undesired duplication of data in midas history files. In turn, this leads to slow 
down while making history plots (mhttpd has to read more data from bigger data files, which takes time) 
and for long running experiments may pose problems with disk space for storing history files.

In addition, when logging history data into an SQL database, each history record is mapped into an SQL 
table, so all variables from all banks of an equipment end up in the same SQL table - and in addition to 
data duplication described above, a data presentation problem is created - database users and 
administrators dislike having SQL tables with "too many" columns!

To solve both problems - reduce data duplication and avoid creating over-large SQL tables - per-
variable history has been implemented.

to be continued...

K.O.
  749   16 Feb 2011 Konstantin OlchanskiInfoNotes on MIDAS history
> 
> 1) PerVariableHistory.
> 
> The default value of 0 is intended to operate the midas history in "traditional" mode. In this mode:
> - there is one history record for each equipment
> - history record id is equal to the equipment id
> - /History/Events and /History/Tags are not required and can be safely deleted
>

I now commited an example experiment for testing and using non-per-variable history:
.../midas/examples/history1

I confirm that this example does work as expected after src/history_midas.cxx is updated to latest rev 4979 (today). I guess it also worked just 
fine before breakage in svn rev 4827 last September.

svn rev 4980.



Here is the README file:

Example experiment "history1"

Purpose:
example and test of a simple periodic frontend writing slow controls data into midas history

To run:
use bash shell
assuming MIDAS is installed in $HOME/packages/midas on linux, otherwise edit setup.sh and Makefile
run make to build feslow.exe
run source ./setup.sh
when starting this experiment for the very first time, load experiment settings from odb.xml: odbedit -c "load odb.xml"
run ./start_daq.sh
mlogger and mhttpd should now be running
connect to the midas status page at http://localhost:8080 (port number is set in start_daq.sh
start the example frontend from the "programs" page
observe event number of equipment "slow" is incrementing
go to the "Slow" equipment page (click on "Slow" on the midas status page)
observe numbers are changing when you refresh the web page
from the midas status page, go to "history" -> "slow" - observe history plot for "SLOW[2]" shows a sine wave
from shell, examine contents of history file: "mhdump *.hst"
study feslow.cxx

Enjoy,
K.O.
  753   28 Feb 2011 Konstantin OlchanskiInfojavascript example experiment
I just committed a MIDAS example for using most mhttpd html and javascript functions: ODBGet(), 
ODBSet(), ODBRpc() & co.

Please checkout .../midas/examples/javascript1, and follow instructions in the README file.

For your enjoyment, the example html file is attached to this message.

(to use the function ODBRpc_rev1 - the midas rpc call that returns data to the web page - you need 
mhttpd svn rev 4994 committed today. Other functions should work with any revision of mhttpd)

svn rev 4992.
K.O.
Attachment 1: example.html
  766   20 Jun 2011 Stefan RittInfoJavascript ODB interface revised
The Javascript interface to the ODB has been revised. This extends the capabilities of custom web pages requesting data from the ODB. By grouping several request together, the number of round-trips is minimized and the response time is reduced. Following functions are new or extended:

  • ODBGet(path[, format]): This functions works now also with subdirectories in the ODB. The command ODBGet('/Runinfo') returns for example:
    1
    1
    1024
    0
    0
    0
    Mon Jun 20 09:40:14 2011
    1308588014
    Mon Jun 20 09:40:46 2011
    1308588046
    

  • ODBGetRecord(path), ODBExtractRecord(key): While ODBGet can be used for subdirectories, an easier way is to use ODBGetRecord and ODBExtractRecord. The first function retrieves the subtree (record), while the second one can be used to extract individual items. Here is an example:
    result = ODBGetRecord('/Runinfo');
    run_number = ODBExtractRecord(result, 'Run number');
    start_time = ODBExtractRecord(result, 'Start time');
    

  • ODBMGet(paths[, callback, formats]): This function ("Multi-Get") can be used to obtain ODB values from different paths in one call. The ODB paths have to be supplied in an array, the result is again an array. An optional callback routine might be supplied for asynchronous operation. Optional formats might be supplied if the resulting number should be formatted in a specific way. Here is an example:
       var req = new Array();
       req[0] = "/Runinfo/Run number";
       req[1] = "/Equipment/Trigger/Statistics/Events sent";
       var result = ODBMGet(req);
       run_number = result[0];
       events_sent = result[1];
    

The new functions are implemented in mhttpd revision 5075.
  767   21 Jun 2011 Stefan RittInfoNew MIDAS sequencer
A new sequencer for starting and stopping runs has been implemented. Although it is till kind of in a preliminary phase, it is usable, so I would like to share the syntax with you.

The sequencer runs inside mhttpd, and creates a new ODB subdirectory "/Sequencer". There is a new button on the status page called "Sequencer". In can run scripts in XML format, which reside on the server (where mhttpd is running). The sequencer is stateless, that means even if mhttpd is stopped and restarted, it resumes operation from where it has been stopped. Following statements are implemented:

  • <Comment>comment</Comment>
    a comment for this XML file, for information only

  • <ODBSet path="path">value</ODBSet>
    to set a value in the ODB

  • <ODBInc path="path">delta</ODBInc>
    to increment a value in the ODB

  • <RunDescription>Description</RunDescription>
    a run description which is stored under /Experiment/Run Parameters/Run Description.

  • <Transition>Start | Stop</Transition>
    to start or stop a run

  • <Loop n="n"> ... </Loop>
    to execute a loop n times. For infinite loops, "infinit" can be specified as n

  • <Wait for="events | ODBvalue | seconds" [path="ODB path"]>x</Wait>
    wait until a number of events is acquired (testing /Equipment/Trigger/Statistics/Events sent), or until a value in the ODB exceeds x, or wait for x seconds.

  • <Script [loop_counter="1"]>Script</Script>
    to call a script on the server side. Optionally, the loop counter(s) are passed to the script

Attached is a simple script which can be used as a starting point.
Attachment 1: seqtest.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<RunSequence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="">
<Comment>This is the XML test file</Comment>

<ODBSet path="/Experiment/Run Parameters/Comment">Test comment</ODBSet>
<RunDescription>Test Run</RunDescription>

<!-- do 10 runs -->
<Loop n="10">
   <!-- increment high voltage and wait for some time to settle -->
   <ODBInc path="/Equipment/HV/Variables/Demand[0]">10</ODBInc>
   <Wait for="seconds">10</Wait>

   <!-- start a run, acquire 3000 events -->
   <Transition>Start</Transition>
   <Wait for="events">3000</Wait>
   <Transition>Stop</Transition> -->
</Loop>
</RunSequence>
  770   27 Jun 2011 Konstantin OlchanskiInfoupdated mhttpd history "export" function
The mhttpd history "export" function has been converted to the new midas history
interface and should now work for SQL-based history systems. In the process,
improvements by Eoin Butler (CERN AD-5/ALPHA) were merged - adding a UNIX
timestamp and a better text timestamp. Also now "export" outputs the actual
values from the history file - the scaling values from the definition of the
history plot panel are no longer applied.

Here is an example of the new file format:

Time, Timestamp, Run, Run State, SLOW
2011.06.21 15:45:21, 1308696321, 13292, 3, -89.1007

svn rev 5104
K.O.
ELOG V3.1.4-2e1708b5