Citect SCADA 2018 Disk I/O Devices and redundant servers - Migrating to Persisted Memory I/O Device

i have raised this with support but though i may use the collective knowledge on here as well.

I have Citect SCADA 2018 system with redundant servers configuration (Primary and Standby) with hard Disk Drive I/O device

Variables.

 

I have found that these 2 devices do not fully synchronise, the original project when these iO device were added was in 1996 on very early version (V3.21)

 

Reading the Help directory I now see improved performance and synchronisation is available from V7.2 onwards by using Persisted Memory I/O Device

I will implement this change as soon as I have a down day by the following procedure.

 

To migrate disk PLC devices to persisted I/O memory mode:

  1. 1.       Perform the procedures listed in Upgrading to Citect SCADA 7.20, as is appropriate. Refer to the v7.20 documentation for more information.
  2. 2.       For disk I/O devices, set the Background Poll property to TRUE and the Persist property to TRUE (the default setting). See Add an I/O Device) for more information.
  3. 3.       Start the I/O server up and wait for a few minutes so that the background poll updates every tag.
  4. 4.       Shutdown the I/O server.
  5. 5.       On the I/O Device dialog, for disk I/O devices set Background Poll back to FALSE, set Memory to TRUE and clear out the Port Name field as it is not necessary for Memory Mode.
  6. 6.       Restart the I/O server to finish the migration to persisted memory I/O mode, with your devices now containing your original values from the disk I/O device.

MY Questions are

Q1  The variables I have in these I/O devices are VERY critical to my process.  are these variable Values backed up as part of a Project backup ? if Not is there a way to back up the Values of Disk IO Device Variables

Q2 As I have redundant servers in operation. I would assume I do the above by

  1. shutting down my Standby server
  2. do the Above Migration procedure
  3. restart the  Standby server
  4. shutting down my Primary server
  5. do the Above Migration procedure
  6. restart the  Primary server

is this correct ? anything else I need to be aware of

 

 

Regards

 Alan

Parents
  • Sorry, I forgot about that. As the toolbox post says, "Most of the functions are stand-alone, but some do call other functions in the same file or other files in this set."

    Here are the additional functions my export code calls...from the Date, File, String, and SuperGenie Tools files.

    STRING	mcCRLF = "^0x0D^0x0A";	//Carriage Return & Line Feed characters
    STRING	msFileBuffer;
    
    
    //Returns the specified string with nCharsToTrim removed from the left (beginning)
    //or "" for out of range values
    STRING FUNCTION StrTrimLeft(STRING sText, INT nCharsToTrim)
    	INT nTextLen = StrLength(sText);
    	
    	IF (nCharsToTrim >= 0) AND nCharsToTrim < nTextLen THEN
    		RETURN StrMid(sText, nCharsToTrim, StrLength(sText) - nCharsToTrim);
    	ELSE
    		RETURN "";
    	END
    END
    
    
    //Returns TRUE if the specified tag name includes a cluster name prefix
    INT FUNCTION TagHasCluster(STRING sTag)
    	RETURN StrSearch(1, sTag, ".") > 0;
    END
    
    
    //Wrapper for FileWriteLn() using FileWriteBuf to minimize disk access
    FUNCTION FileWriteLnBuf(INT hFile, STRING sText)
    	FileWriteBuf(hFile, sText + mcCRLF);
    END
    
    //Wrapper for FileWrite() uses buffering to mimimize disk access
    FUNCTION FileWriteBuf(INT hFile, STRING sText)
    	INT		cMaxChars = 254;	//In Citect 7.20 SP5 and later this can be increased to 255
    	INT		nBufferLen;
    	INT		nError;
    	STRING	sRemainingText;
    
    	nBufferLen = StrLength(msFileBuffer);
    	msFileBuffer = StrLeft(msFileBuffer + sText, cMaxChars);					//Copy whatever will fit in buffer
    	sRemainingText = StrTrimLeft(sText, StrLength(msFileBuffer) - nBufferLen);		//Remove any text that was copied to buffer
    
    	//Dump full buffer to disk
    	IF StrLength(msFileBuffer) = cMaxChars THEN
    		IsError();		//Reset error code
    		FileWrite(hFile, msFileBuffer);
    		nError = IsError();
    		
    		IF nError <> 0 THEN
    			ErrLog("FileWriteBuf() Failed to write buffer to file. Error:" + nError:#);
    			RETURN;
    		END
    		msFileBuffer = sRemainingText;
    	END
    END
    
    
    //Wrapper for FileClose() also writes any text remaining in buffer
    FUNCTION FileCloseBuf(INT hFile)
    	INT		nError;
    	
    	IsError();	//Clear last error
    	FileWrite(hFile, msFileBuffer);
    	nError = IsError();
    	
    	IF nError <> 0 THEN
    		ErrLog("FileCloseBuf() Failed to write buffer to file. Error:" + nError:#);
    	END
    
    	msFileBuffer = "";
    	FileClose(hFile);
    END
    
    
    //Convert a Citect date/time integer value into a formatted string (see Q6123)
    //Similar to TimeToStr() but allows custom formats to be specified like TimestampFormat()
    //
    //sFormat	Custom time/date format specification. Case sensitive. See below.
    //nTime		Citect integer time/date value (default is the current time)
    //nMS		Milliseconds to add to Citect time (default = 0)
    //
    //Example: sText = TimeFormat("dd/MM/yyyy hh:mm:ss.fff");
    //
    STRING FUNCTION TimeFormat(STRING sFormat, INT nTime = TimeCurrent(), INT nMS = 0)
    	RETURN TimestampFormat(TimeIntToTimestamp(nTime, nMS, TRUE), sFormat);
    END
    
    
Reply
  • Sorry, I forgot about that. As the toolbox post says, "Most of the functions are stand-alone, but some do call other functions in the same file or other files in this set."

    Here are the additional functions my export code calls...from the Date, File, String, and SuperGenie Tools files.

    STRING	mcCRLF = "^0x0D^0x0A";	//Carriage Return & Line Feed characters
    STRING	msFileBuffer;
    
    
    //Returns the specified string with nCharsToTrim removed from the left (beginning)
    //or "" for out of range values
    STRING FUNCTION StrTrimLeft(STRING sText, INT nCharsToTrim)
    	INT nTextLen = StrLength(sText);
    	
    	IF (nCharsToTrim >= 0) AND nCharsToTrim < nTextLen THEN
    		RETURN StrMid(sText, nCharsToTrim, StrLength(sText) - nCharsToTrim);
    	ELSE
    		RETURN "";
    	END
    END
    
    
    //Returns TRUE if the specified tag name includes a cluster name prefix
    INT FUNCTION TagHasCluster(STRING sTag)
    	RETURN StrSearch(1, sTag, ".") > 0;
    END
    
    
    //Wrapper for FileWriteLn() using FileWriteBuf to minimize disk access
    FUNCTION FileWriteLnBuf(INT hFile, STRING sText)
    	FileWriteBuf(hFile, sText + mcCRLF);
    END
    
    //Wrapper for FileWrite() uses buffering to mimimize disk access
    FUNCTION FileWriteBuf(INT hFile, STRING sText)
    	INT		cMaxChars = 254;	//In Citect 7.20 SP5 and later this can be increased to 255
    	INT		nBufferLen;
    	INT		nError;
    	STRING	sRemainingText;
    
    	nBufferLen = StrLength(msFileBuffer);
    	msFileBuffer = StrLeft(msFileBuffer + sText, cMaxChars);					//Copy whatever will fit in buffer
    	sRemainingText = StrTrimLeft(sText, StrLength(msFileBuffer) - nBufferLen);		//Remove any text that was copied to buffer
    
    	//Dump full buffer to disk
    	IF StrLength(msFileBuffer) = cMaxChars THEN
    		IsError();		//Reset error code
    		FileWrite(hFile, msFileBuffer);
    		nError = IsError();
    		
    		IF nError <> 0 THEN
    			ErrLog("FileWriteBuf() Failed to write buffer to file. Error:" + nError:#);
    			RETURN;
    		END
    		msFileBuffer = sRemainingText;
    	END
    END
    
    
    //Wrapper for FileClose() also writes any text remaining in buffer
    FUNCTION FileCloseBuf(INT hFile)
    	INT		nError;
    	
    	IsError();	//Clear last error
    	FileWrite(hFile, msFileBuffer);
    	nError = IsError();
    	
    	IF nError <> 0 THEN
    		ErrLog("FileCloseBuf() Failed to write buffer to file. Error:" + nError:#);
    	END
    
    	msFileBuffer = "";
    	FileClose(hFile);
    END
    
    
    //Convert a Citect date/time integer value into a formatted string (see Q6123)
    //Similar to TimeToStr() but allows custom formats to be specified like TimestampFormat()
    //
    //sFormat	Custom time/date format specification. Case sensitive. See below.
    //nTime		Citect integer time/date value (default is the current time)
    //nMS		Milliseconds to add to Citect time (default = 0)
    //
    //Example: sText = TimeFormat("dd/MM/yyyy hh:mm:ss.fff");
    //
    STRING FUNCTION TimeFormat(STRING sFormat, INT nTime = TimeCurrent(), INT nMS = 0)
    	RETURN TimestampFormat(TimeIntToTimestamp(nTime, nMS, TRUE), sFormat);
    END
    
    
Children
No Data