CS 2018R2 - Check if Variable Tag is also in trend table

Hi,

Do we have an "easy" way to check if a variable tag is also defined in the trend table?

I've been looking through the help file and it seems TrnBrowse functions would be way to perform the search. Before I implement I just want to check if there was another option as well. 

Thanks for any input,

Rune

  • Hi Rune,

    The easy way is to use Citect Studio.

    • Make your main project active
    • Select "System Model" view
    • Select "Trends" from the menu bar
    • Go to the "Tag Name" column and click on the filter icon
    • Enter the trend name you would like to check and then click on the "Apply" button
    • You could also use multiple columns for filtering

    Note that you could change the filter criteria, eg, use "Starts with" instead of "Contains".

    Hope this would help.

    Regards,

    Jacky

  • Hi,

    I'm going to use it for dynamic Runtime functionality so need to do it with Cicode functions. 

    Rune

  • In that case, Cicode function trnBrowse is the way to go.

  • Hello Rune

    I use a different aproach from Jacky, may be not the easyest one. But I don't know exactly your goal, so I share my 5 cents.

    I use this for commissioning, like create bulk trends, alarms, clean unused tags or repeated tags, etc. So I read and write the variables, trends and alarms dbf tables. It's dangerous as if you do it wrong the project may became uncompilable due to errors. But if you just read there is no problem.

    I always define devices for the equipments, variable tags, local variables, trends, digital alarms and advanced alarms, sometimes other tables. You will just need variables and trends.

    Here is an example of a real function that I use to create trends (I used before the equipment can do it for me). It uses another funcion My_DevFind, that is also in the end. This can be called from cicode kernel or from a cicode function with a loop of variables that need trends (ie, all tags with PT, TT, PV, ENG in the name), when its called from a loop I open the devices outside to have better performance.

    Feel free to use it or ask any question about it.

    Regards,

    Nuno Ventura

    // *************************************************
    // Function to create a trend tag basead on a variable tag
    // *************************************************
    My_CreateTrend(STRING sTagName, STRING sEngUnits="", REAL rEngZero=0, REAL rEngFull=100, STRING sExpression="", STRING sFormat = "##.#", STRING sSamplePeriod = "00:00:10", STRING sSubFolder = "", STRING sStoreMethod = "Scaled (2-byte samples)", STRING sComment = "", INT hDevVar=-1, INT hDevTrn = -1)

    INT bCloseDevVar = 0;
    INT bCloseDevTrn = 0;
    INT NewRec = 0;
    STRING sTrnName = sTagName+"_TREND";
    STRING VARName, VARType, VAREquip, VARunit, VARAddr, VARItemName="", sFileName = "";

    IF hDevVar < 0 THEN
     hDevVar = DevOpen("Vars",1);
     bCloseDevVar = 1;
     IF hDevVar < 0 THEN
      Message("My_CreateTrend","Error openning Vars: "+IntToStr(IsError()),16);
      RETURN;
     END
    END

    IF hDevTrn < 0 THEN
     hDevTrn = DevOpen("Trns",1);
     bCloseDevTrn = 1;
     IF hDevTrn < 0 THEN
      Message("My_CreateTrend","Error openning Trends: "+IntToStr(IsError()),16);
      IF bCloseDevVar THEN
       DevClose(hDevVar, 0);
       END
      RETURN;
     END
    END

    NewRec = My_DevFind(hDevTrn, sTrnName, "NAME");

    IF (NOT NewRec) OR (My_DevFind(hDevVar, sTagName, "NAME") <> 0) THEN 
     // Trend already exists OR variable Tag doesn't exist, not possible read necessary data to Trend
     IF bCloseDevVar THEN
      DevClose(hDevVar, 0);
     END
     IF bCloseDevTrn THEN
      DevClose(hDevTrn, 0);
     END
     RETURN;
    END

    //read variable tag
    VARName=DevGetField(hDevVar,"NAME");
    VARType=DevGetField(hDevVar,"TYPE");
    VARUNIT=DevGetField(hDEVVar,"UNIT");
    VAREquip=DevGetField(hDEVVar,"EQUIP");
    VARItemName=DevGetField(hDEVVar,"ITEM");
    VARAddr=DevGetField(hDEVVar,"ADDR");
    IF sComment = "" THEN
     sComment = DevGetField(hDevVar,"COMMENT");
    END

    IF sExpression = "" THEN
     sExpression = sTagName;
    END

    IF StrTrim(sSubFolder) <> "" THEN
     sFileName = "[Data]:TRENDS\"+StrTrim(sSubFolder)+"\"+sTrnName;
    ELSE
     sFileName = "[Data]:TRENDS\"+sTrnName;
    END

    DevAppend(hDevTrn);

    DevSetField (hDevTrn,"NAME",sTrnName);
    DevSetField (hDevTrn,"FORMAT",sFormat);
    DevSetField (hDevTrn,"COMMENT",sComment);

    IF sExpression <> "" THEN
     DevSetField (hDevTrn,"EXPR",sExpression);
    ELSE
     DevSetField (hDevTrn,"EXPR",VARName);
    END
    DevSetField (hDevTrn,"ENG_UNITS",sEngUnits);
    DevSetField (hDevTrn,"ENG_ZERO",rEngZero);
    DevSetField (hDevTrn,"ENG_FULL",rEngFull);
    DevSetField (hDevTrn,"EQUIP", VAREquip);

    IF VAREquip <> "" THEN
     DevSetField(hDevTrn,"ITEM",VARItemName);
    END

    DevSetField (hDevTrn,"STORMETHOD",sStoreMethod);
    DevSetField (hDevTrn,"SAMPLEPER",sSamplePeriod);
    DevSetField (hDevTrn,"FILENAME",sFileName);
    DevSetField (hDevTrn,"FILES",52); // 52 weeks
    DevSetField (hDevTrn,"CLUSTER",cDefCluster);

    //Also update the scales in Variable Tag database
    DevSetField (hDevVar,"ENG_UNITS",sEngUnits);
    DevSetField (hDevVar,"ENG_ZERO",rEngZero);
    DevSetField (hDevVar,"RAW_ZERO",rEngZero);
    DevSetField (hDevVar,"ENG_FULL",rEngFull);
    DevSetField (hDevVar,"RAW_FULL",rEngFull);

    IF bCloseDevVar THEN
     DevClose(hDevVar, 0);
    END

    IF bCloseDevTrn THEN
     DevClose(hDevTrn, 0);
    END
    END

    // *************************************************
    // Function to find a record, starting from the begin of the table, except if is already in correct position
    // *************************************************
    INT FUNCTION My_DevFind(INT hDev, STRING sValue, STRING sField = "NAME")

    IF StrTrim(DevGetField(hDev,sField)) = StrTrim(sValue) THEN
     RETURN 0; // the cursor ir already in the wanted record
    ELSE
     DevFirst(hDev);//Go to begin
     RETURN DevFind(hDev, sValue, sField)
    END
    END

  • How about TrnInfo()? It returns a few different trend properties, or an empty string if the trend doesn't exist. Here's an example function using it to check if a trend tag exists:

    //Returns TRUE if the specified trend tag exists
    INT FUNCTION TrnExists(STRING sTag)
    	RETURN TrnInfo(sTag, 1) <> "";
    END