Simple Change Log Chart

Hi All,

The “shift string element” example I mentioned here was part of a request I had for a little OptoScript to make a note if a certain tag changed.

For example, we’re working on some new interactive demos (be sure to sign up on for updates) that involve a “your name in lights” sign where you can change a text string and it shows up “in lights” (visible via a webcam). But we’d like to make a note when someone types in their name or other message.

I wanted to make this code a little generic/reusable since a couple of coworkers of mine wanted to add some similar logic to the controllers in their homes.

Here’s what I came up with (no pointers involved!) – do share if you have questions or other ideas. In the attached chart, which you can import into your own 9.3 Basic or better strategy, I give 2 options for the “make a note” part:

  1. You can write it to a file to get a log like the one shown below (I prefer Firefox for easy reading of a text file on your PAC):

  2. You can store this info a string table, where element [0] has the most recent entry.

(Or you can do both, which is what the attached chart currently does – adjust as needed.)

In the first OptoScript block, I initialize a list of the names of the tags I want to monitor. (Optional comment/label in the second column of string table initializations here.) I also open the local log file.

// Create a list of the values to log when they change

                              // Optional label (if you want more info than just the tag name)
stTagList[0] = "fFloat";      stLabels[0] = "My test float";
stTagList[1] = "nInt32";      stLabels[1] = "An int 32";
stTagList[2] = "di_R1_0000";  stLabels[2] = "digital input";
stTagList[3] = "sSignString"; stLabels[3] = "here's your sign";

// Open file to log to
nCHResult = OpenOutgoingCommunication(chLogFile);

In the “Check variables for changes” OptoScript block, I use the handy command GetValueFromName to grab the current value of each tag in my list (as a string) and compare it with the previous value:

// Initialize loop variables
nTableIndex = 0;

// Loop through all the tags to check, see if they're different, and make a note if they are
while ( IsVariableFalse( nDone ) )

  // See if we've reached the end of the list (the first blank or bad tag name)
  if ( GetValueFromName(stTagList[nTableIndex], stCurrentValue[nTableIndex]) <> 0 ) then
  else // we need to compare this value to the last one

    // see if it's changed
    if (  0 == CompareStrings(stCurrentValue[nTableIndex], 
                                       stLastValue[nTableIndex] ) ) then 
      // the value hasn't changed
      // the value has changed, made a note, starting w/a date/timestamp

      sLogMessage = sDate + " " + sTime + " " + stTagList[nTableIndex] + " '" + 
        stLabels[nTableIndex] + "' changed to: '" +
        stCurrentValue[nTableIndex] + "'" + chr(0xD) + chr(0xA);  


      // update "last value" 
      stLastValue[nTableIndex] = stCurrentValue[nTableIndex];



  if (nTableIndex >=  GetLengthOfTable(stTagList)) then 


In the “MAKE A NOTE” part, I give two options, shown below. But you could also send an email or something else if you’d like.

      /** "make a note" Option #1: write to file *****/
      nCHResult = TransmitString(sLogMessage, chLogFile);

      // Check number of bytes left for RAM filespace
      nResultRAMbytes = GetAvailableFileSpace(0);

      // Check to see how much room we have for the log file
      if (nResultRAMbytes < 100) then // put a warning in the queue
        AddMessageToQueue(16, "chLogFile out of file space.");
      elseif (nResultRAMbytes < 1000) then // put a warning in the queue
        AddMessageToQueue(8, "chLogFile running low on filespace");
      /** end option 1 */

      /*** option 2 (Ben's choice) - string table w/most recent entry at the top */
      // Read what's currently in the SP strings (so we can shift them down one)
      //GetIoUnitScratchPadStringTable(I/O Unit, Length, From Index, To Index, To Table)
      nSPResult = GetIoUnitScratchPadStringTable(R1, 63, 0, 1, stEventLog);

      // Load element [0] of the table
      stEventLog[0] = sLogMessage;

      // Write the updated log list to the scratch pad
      //SetIoUnitScratchPadStringTable(I/O Unit, Length, To Index, From Index, From Table)
      nSPResult = SetIoUnitScratchPadStringTable(R1, 64, 0, 0, stEventLog);
      /** end option 2 */

Of course, this will miss any changes that happen inside the scanning interval. But for a simple event log, I thought this might be handy to others out there!

-OptoMary (3.09 KB)