Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-

Write Cicode and Create Citect

Name: SCADA 2013-04-12 5:30

Practical 1 : Introduction to SCADA

OBJECTIVES:

1. To understand the concept of SCADA and familiarize with the CITECT SCADA environment

2. To create and manage projects using Citect Explorer


Creating and managing projects with Citect Explorer

The Citect Explorer is the application from which you organise your projects and launch the configuration and run-time applications. Tasks such as creating, deleting, backing up and restoring projects are fundamental to any Citect application.

Creating a new Project

The first thing you need to do when configuring Citect is to create a new project in which to store your project information.

⇨ To create a new project:

1. In the Citect Explorer, select File ǀ New Project or click on the New button

2. The following dialog will appear - fill in the relevant details: e.g : Name : Training, Description : Training Project

Hints & Tips:

To go to the next field, use the mouse cursor or press the TAB key. To go back a field press SHIFT-TAB

3. Click on OK.

Citect will now create the configuration databases that will be the building blocks of your project.

Note the new entry called Training in the Project List- this entry will contain all of the configuration information for your project.

Backing Up & Restoring a Project

⇨ To backup a project:

1. Select Tools ǀ Backup ... from the menus or click on the icon

2. The following dialog will appear- fill in the details as required

To restore a project

1. Select Tools ǀ Restore ... from the menus or click on the icon

2. The following dialog will appear- fill in the details as required.

NOTE: When backing up a project, the project is backed up to a file called ctbackup.ctz. When restoring a project look for the file that you have backep up (with the .ctz extension)

Deleting a Project

⇨ To delete a project:

1. In the Citect Explorer, click on the project that you want to delete from the Project List.

2. Select File ǀ Delete Project from the menus or select Delete Project from the context menu.

See Also:

Delete a Project in the Projects' category in Help Direct.

Exercise

1. In the Citect Explorer, backup your project to the directory C:\Temp.

NOTE: You should do this after every lab session so that you will have a backup copy in case it is accidentally deleted.

2. To simulate an accidental delete, delete your project called Training.

3. To simulate the recovery of your lost project, restore the project from C:\Temp to a new Training project that was lost. Notice that all the component of your 'lost' training project was recovered.

4. To prepare for the next part of the lab, delete your Training project.

Citect can communicate with any control or monitoring 1/0 Device that has a communication port or data highway - including PLCs (Programmable Logic Controllers), loop controllers, bar code readers, scientific analyzers, remote terminal units (RTUs), and distributed control systems (DCS). Citect communicates directly with the 1/0 Devices in your plant or factory.

Express Communications Wizard

The Express Communications Wizard enables you to quickly setup communication with a new or existing 1/0 Device:

⇨ To run the Express Communications Wizard:

1. In the Citect Explorer select the project you are working on.

2. Click on the Communications folder in the Project List.

3. Double click on the Express 110 Device Setup item in the Contents Area:

The following dialog is displayed:

By filling in the relevant information and clicking on the Next button, the Express Communications Wizard will guide you through the setup process.

Exercise

1. First, create a new project and call it TEST. The location should be C:\Temp.

2. Setup communication to an external Omron C200HE PLC using serial communication (accept the default name for the 1/0 Device - i.e. 10Dev1 ). If you are using a different type of PLC then select it instead.

The Communications Dialogs

After running the Express Communications Wizard, a set of communications dialogs are created that can be found in the Communications folder in the Citect Explorer.

The dialogs that would have been created in the previous exercise for Omron C200HS PLC connected serially are shown below:

Boards :

Board Name : BOARD1

Ports :

Board Name : BOARD1

I/O Devices

Port Name : PORT_BOARD1

Exercise

1. Open up each of the dialogs shown above from the Citect Explorer. Do this by highlighting the Communications folder in the Project List and then double clicking on the 1/0 Servers, Boards, Ports and 1/0 Devices items in
the Contents Area.

2. Go to Citect Editor and click on to the Communication menu. Select Port and change the baud rate from 19200 to 9600 (the baud rate for Omron PLC serial comm).

3. Click on the Help button for each of the communications dialogs for more information.


Testing Communications

To test that the server and 1/0 Device are communicating.

We will first define a variable tag called Green_Lamp and display its value on a graphics page. Here, we will control the green lamp ON or OFF through the Citect system.

⇨ To define a variable tag :

1. In the Citect Explorer click on the Tags folder in the Project List and double click on the Variable Tags item in the Contents Area:

2. The following dialog will be displayed:

Variable Tags

Fill in the fields of the dialog as follows:

Variable Tag Name : Green_Lamp

IO DEVICE NAME : IODev

Data Type : DIGITAL

Address : 301

If you are using a PLC other than a Omron then the Address field will be different. Check the Citect Help Topics for the correct address.

See Also:

Click on the Help button on the Variable Tags dialog to get information about each field.

3. Click Add.

⇨ To display the value of the variable tag on a graphics page:

1. Double click on the Create a new page button in Citect Explorer

or

Click on the New button in the Graphics Builder.

2. If you double clicked Create a new page then go straight to step 3, otherwise, click the Page button when the following dialog is displayed:

3. Make your selection from the Use Template dialog:

For a test page, select :

Style : standard

Linked : tick

Title Bar : tick

Resolution : Default

Template : Normal

4. Click on OK.

5. Draw a button on the page by selecting the Button tool from the toolbox.

6. Move the mouse to where you want the button to start and press (and hold) the mouse button. Drag the mouse to where you want the button to finish and release the mouse button.

 ↘

7. The following dialog will be displayed (if it is not displayed then use the mouse to double click on the button you just drew):

In the Text field type ON Green Lamp as shown above.

8. Click on the Input tab (at the top of the dialog) and the following dialog will be displayed:

In the Action list click the Up check box and in the Up command field type Green_Lamp = 1.

9. Click on OK.

10. Draw another button by repeating steps 5 to 9- for this button type OFF Green Lamp in the Text field and Green_Lamp = 0 in the Up command field.

11. Select the Text tool from the toolbox and move the cursor to a point near the buttons you drew- by doing this we will draw some text to display the value of the Green_lamp tag.

12. Press the space bar once and then click the left mouse button. A dialog will be displayed (if it is not displayed then use the mouse to double click on the object you just drew).

13. Click on the Appearance tab along the top of the dialog and then click on the Display Value tab at the right of the dialog.

In the ON text when field type Green_Lamp (as a defautt the Type should already be set as On / Off), in the OFF text field type OFF and in the ON text field type ON.

14. Click on OK.

15. Click on the Save button on the tool bar to save the page. Select Test from the Project list and then type Test in the Page field.

16. Click on OK. Remember to set to Memory 10 before testing the project

17. Run the Computer Setup Wizard.

18. Click on the Run Project button to run and test the project. Click on the ON and then the OFF buttons to see the effect.

Exercise

1. Now, create a lamp on the graphics editor to monitor the red lamp status from Citect. First, create and add another variable tag (Refer to earlier section To define a variable tag) with the followings:

Variable Tag Name : Red_Lamp I/O Device Name : IODEV1, Data Type : DIGITAL, ADDRESS : 300

2. Select the Symbol Set to create an indicator lamp to represent the physical red lamp. Add Red_Lamp to the dialog box ON symbol when as indicated in the diagram below. Click Apply and OK.

3. Create two buttons : one to turn ON the Red lamp and one to turn OFF the Red lamp.

4. Click on the Save button on the tool bar to save the page.

5. Click on the Run Project button to run and test the project. Clicking on the buttons will activate the Red lamp ON or OFF according to which button is being clicked.

Name: Anonymous 2013-04-12 7:19

stop making up words

Name: Anonymous 2013-04-12 12:48

What is this "click" of which you speak?

Name: SCADA 2013-04-17 5:45

Practical 2: Design and monitor a coupled cylinder using CITECT.

OBJECTIVES:

1. To create graphics page for a coupled cylinder using Citect.

2. To create Digital Alarms and configure Keyboard Commands for the coupled cylinder under Citect.

1 . Create new Citect Project and Configure Communication Settings

a. Open Citect Explorer and click on new project from File Menu to create a new project.

Enter the name of the new project as Cyi_XX
(where XX is your prefer number; e.g. Cyi_B1 or Cyi_B2).

b. Use the Express Communications Wizard to setup IODev so that it is a Memory I/O Device using OMRON C200HS , Sysmac serial protocol in the same way you have done in previous practical.

2. Create Variable Tags

a. At the explorer, click on the tag folder to add on all the variable tags as listed in the table below

S/NO  Variable Tag Name  I/O Device  Type  Address

1     Cylinder 1          IODev     Digital  001
2     Cylinder 2          IODev     Digital  003
3     Cylinder 3          IODev     Digital  005

3. Create new graphic page.

a. Click on the graphic/pages folders and then create a new page icon to give a blank canvass for the graphic builder.

b. Create 3 buttons on the top right hand corner of the page as shown in the figure below. Name them as Cylinder1, Cylinder2 and Cylinder3 respectively in the Appearance I General properties. At the Input / Touch properties, check the Up box at the Action column and enter Toggle(cylinder1), Toggle(cylinder2) and Toggle(cylinder3) into the Up command box respectively.

c. Select the rectangle tool from the toolbox to draw the structure and the plunger for Cylinder 1. Check the fill box and select the color in the Appearance / General property box.

d. Enter the following Movement properties for the cylinder rod 1 only as shown below :

Rectangle Properties-Movement-Movement expression : cylinder1
√ Specify Range, Minimum : 0.0, Maximum : 1

e. Add on the second cylinder as shown in the figure below. Check the fill box and select the calor in the Appearance / General property box.

f. Enter the following Movement / horizontal and vertical properties for cylinder 2 (body and rod) as shown below.


Rectangle Properties-Movement-Movement expression : cylinder1

√ Specify Range, Minimum : 0.0, Maximum : 1

Offset:

At maximum 100 pixels (right)


Rectangle Properties-Movement-Movement expression : cylinder2

√ Specify Range, Minimum : 0.0, Maximum : 1

Offset:

At maximum -45 pixels (up)

g. Save the graphic page with the name Cylinder.

h. Click new at the file folder and select symbol to create a new symbol.

i. Using the rectangle tool to design an open gripper as shown in the figure below. Ensure that the drawing is placed close to the base point ◊. Highlight the entire graphic and select tool convert to bitmap to convert it as a bitmap symbol. For each of the symbol, save in as Cyl3_open under a new library with the name as cylinders.

j. Create another symbol of a close gripper. Convert the symbol bitmap and save it with the name Cyl3_close under the same library cylinders.

k. Open the cylinder graphic page again and select the set symbol tool from the toolbox. Edit the properties as shown in below.

Symbol Set Properties-Appearance-General

Type • On/off
ON symbol when cylinder3

OFF symbol: cyl3_open  ON symbol: cyl3_close

Symbol Set Properties-Movement-Movement expression : cylinder1

√ Specify Range, Minimum : 0.0, Maximum : 1

Offset

At maximum 100 pixels (right)


Symbol Set Properties-Movement-Movement expression : cylinder2

√ Specify Range, Minimum : 0.0, Maximum : 1

Offset

At maximum -45 pixels (up)

I. The final graphic page should look the figure below. Save the page.

cylinder1 button

cylinder2 button

cylinder3 button

4. Running the Project

a. Click on the Run Project button in the Project Editor.

b. If the compiler reports any errors, select Go To to display the dialog where an error exists. When you have corrected all errors, click on Run Project again.

c. Test the movement by clicking on the 3 buttons.

5. Digital Alarms

a. Create the variable tags as listed in the table below :

S/NO  Variable Tag Name  I/O Device  Type     Address
1      EStop              IODev     Digital    0203

b. Create an E-Stop button (as shown below) :

E-Stop button

c. At the Input / Touch properties, check the Up box at the Action column and enter Toggle(EStop)- EStop is the variable tag created earlier, into the Up command box.

d. Under Citect Project Editor, select Digital Alarms in the Alarms menu :

Citect Project Editor [ test1 ] UNCOMPILED

Alarms-Digital Alarms-Digital Alarms [ test 1 ]

e. Key in the relevant information for the digital alarms as shown below:

Alarms-Digital Alarms-Digital Alarms [ test 1 ]

Alarm Tag : EStop

Alarm Name : EmerStop

Alarm Desc : Emergency stop button activated

Var TagA : E Stop

f. Create a graphic page to display the above digital alarm.

In the Citect Graphics Builder, select New under the File menu.

Click on Create a new graphics page icon. Select alarm template and click OK as below :

Use Template-alarm

Save the new page as Alarm.

6. Testing the Project with Digital alarms

a. Click on the Run Project button in the Project Editor.

b. Test the alarm by clicking on the E-Stop button in run-time environment.

7. Keyboard Commands

Keyboard commands allows user to issue commands or control operations using key sequences from the keyboard versus clicking on pre-defined button. Can be used as shortcuts
or for frequently used functions/controls.

a. To define a keyboard key name.

Click on the System folder under Citect Explorer and then double-click on Keyboard Keys in the Contents Area. Fill in the required information and click Add.

Keyboard Keys [ test1 ]

Key Name : ShutDown

Key Code : KEY_END

Comment : END key on keybd used as shutdown key

b. To define a system keyboard command.

Click on the System folder under Citect Explorer and then double-click on Keyboard Commands in the Contents Area. Fill in the required information and click Add

System Keyboard Commands [ test 1 ]

Key Sequence : ShutDown

Command : Shutdown();

Comment : Shuts down Citect during run-time

c. Click on the Run Project button in the Project Editor. Test the newly created Keyboard Command by pressing the END key on your keyboard- it should shutdown the project in run-time environment and return to editor mode.

Exercise

a. Define the following keyboard key and keyboard command. Follow the steps outlined in example above.

Key Name         Key Code            Comment

F1                KEY_F1              F1 Key

Key Sequence    Execute Command

F1              Toggle(Cylinder1)

b. Click on the Run Project button in the Project Editor. Test the newly created Keyboard Command by pressing the F1 key on your keyboard - it should toggle
Cylinder1 ON and OFF every time F1 key is pressed.

c. Repeat the above steps using F2 for Cylinder2 and F3 for Cytinder3.

d. Back up and save your project.

Name: Anonymous 2013-04-17 8:12



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-17 8:16



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-17 8:20



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-17 8:24



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-17 8:28



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-17 8:32



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-17 8:36



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-17 8:40



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-17 8:44



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-17 8:48



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-17 9:23



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-17 9:27



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-17 15:32



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: SCADA 2013-04-18 6:00

Practical 3: CITECT function to control and monitor a coupled cylinder.


OBJECTIVES:

1. To understand how Cicode can be used to write user defined functions in Citect.

2. Write Cicode functions to control the movement of a coupled cylinder.


1. Restore new Citect Project from a back up copy.

a. Open Citect Explorer and click on Restore under the Tools Menu.

b. Restore to a new project the back up file that was previously saved.
( e.g. Restore from C:\temp\Your No XXX\ CyLB 1.ctz ).

2. Create Clcode function to control the Cylinders.

a. Open Citect Project Editor and select Cicode Editor under tools (as shown).

b. Select New from the File menu. Select Cicode and click OK

c. Type in the Cicode function listed below :

-----------------------------------------------------------

//Cicode function to control movement of coupled cylinders

FUNCTION

MoveCyl()           //function to move the cylinders

   Cylinder1 = 1   //To extend Cylinder1
 
   SleepMS(300)   //Wait for 0.3 sec (300 millisecond)

   Cylinder2 = 1  //To extend Cylinder2

   SleepMS(300)

   Cylinder3 = 1  //To close Cylinder3

   SleepMS(300)
 
   Cylinder2 = 0  //To retract Cylinder2

   SleepMS(300)

   Cylinder1 = 0  //To retract Cylinder1

   SleepMS(300)

   Cylinder2 = 1  //To extend Cylinder2

   SleepMS(300)

   Cylinder3 = 0  //To open Cylinder3

   SleepMS(300)

   Cylinder2 = 0  //To retract Cylinder2

   SleepMS(300)

End

-----------------------------------------------------------

d. Save the Cicode as MoveCyl (make sure ifs saved in your project).

e. Select compile from File menu in the Cieode Editor. Correct the errors, if any.

3. Using the Cicode function in the graphic page.

a. Open the Cylinder page inside Citect Graphics Editor.

b. Create a button on the bottom right hand corner of the page and name it as Start. Select 1nput and click on Insert Functions (as shown).

Button Properties-Input

Action

√ Up

c. Insert the MoveCyl() function which we have written earlier and click OK.


√ Touch-Insert Function



MoveCyl[]

√ Insert arguments

d. Click OK and the screen should be as shown :

Citect Graphics Builder - [Cyl_Proj - Cylinder]

Cylinder1 Button

Cylinder2 Button

Cylinder3 Button

Start Button

e. Save the page under your project and Click on the Run button to test the project. Click on the Start button to see the Cylinders 1, 2 & 3 in action.

Sequence of movement

1 Cylinder1 Extend

2 Cylinder2 Extend

3 Cylinder3 Close

4 Cylinder2 Retract

5 Cylinder1 Retract

6 Cylinder2 Extend

7 Cylinder3 Open

8 Cylinder2 Retract

f. lt can be seen that it followed the sequence of movement as in the table above.

g. Back up and save your project.

4. Using a variable to control number of cycles.

a. Open Citect Project Editor and select Variable Tags :

Citect Project Editor [ Cyl_Proj ] - UNCOMPILED

Tags-Variable Tags

Variable Tags [ Cyl_Proj ]

Variable Tag Name : Cylinder1

I/O Device Name : IODev

Data Type : DIGITAL

Address : 0001

b. Create a new variable tag as follows :

Var. Tag Name  Data Type  I/O Device  Address
NumCycles       INT        IODev      DM0001

Variable Tag Name : NumCycles

I/O Device Name : IODev

Data Type : INT

Address : DM0001

c Open Citect Project Editor and select Cicode Editor under tools. Select New from the File menu. Select Cicode and click OK. Type in the Cicode function listed below:

----------------------------------------------------------

//Cicode function to control movement of coupled cylinders

FUNCTION

  AutoMoveCyl()        //function to move the cylinders
  
    INT counter= 0;

   WHILE counter< NumCycles DO //NumCycles, var tag for no. of cycles

      Cylinder1 = 1   //To extend Cylinder1

      SleepMS(300)    //Wait for 0.3 second

      Cylinder2 = 1   //To extend Cylinder2

      SleepMS(300)
 
      Cylinder3 = 1   //To close Cylinder3

      SleepMS(300)


      Cylinder2 = 0   //To retract Cylinder2

      SleepMS(300)

      Cylinder1 = 0   //To retract Cylinder1

      SleepMS(300)

      Cylinder2 = 1   //To extend Cylinder2

      S1eepMS(300)

      Cylinder3 = 0   //To open Cylinder3

      SleepMS(300)

      Cylinder2 = 0   //To retract Cytinder2

      SleepMS(300)

      counter= counter+ 1
 
   END

End

-----------------------------------------------------------

d. Save it as Autorun and then compile the above Cicode function.

e. Open the Cylinder page inside Citect Graphics Editor.

f. Create a button on the bottom right hand corner of the page and name it as Auto Run. Select Input and click on Insert Functions (as shown).

Button Properties-Input

Action

√ Up

√ Touch-Insert Function

Up command

AutoMoveCyl[]

g. Insert the AutoMoveCyl() function which we have written earlier and click OK.

Cylinder1 Button

Cylinder2 Button

Cylinder3 Button

Start Button

Auto Run

h. Select Text tool and type in "Number of Cycles :" as shown and click OK :

Text Properties-Appearance

General-Font: Arial

Style: Regular

Size: 11

Alignment

• Left

Text : Number of Cycles :

Cylinder1 Button

Cylinder2 Button

Cylinder3 Button

Start Button

Auto Run

Number of Cycles :


i. Next, select Number tool as shown.

j. Insert variable tag NumCycles inside Numeric expression as shown:

Text Properties-Appearance

Display Value

Type

• Numeric

Insert Tag : NumCycles


k. Select Input, Keyboard Commands and type in following as shown :

Input-Keyboard Commands

Key sequence : ####ENTER

'####ENTER' command : NumCycles=ArgValue1

Security

√ Same area as object √ Same privilege as object

I. Click OK and move above numeric text next to Number of Cycles :

Cylinder1 Button

Cylinder2 Button

Cylinder3 Button

Start Button

Auto Run

Number of Cycles : ##

m. Click Save and then Run button to test above project.

n. Move mouse cursor close to the number (there will be a small square around the number), key in a number (say 3 or 5) and hit the Enter key.


Cylinder1 Button

Cylinder2 Button

Cylinder3 Button

Start Button

Auto Run

Number of Cycles : 5

o. Next, click on Auto Run button to start the cylinder sequence. Notice that the cylinders cycle will repeat according to the number of times entered.

p. Save and backup the project.


Exercise

1. Create a Pause button (with the necessary variable tag) which will stop the running sequence when clicked. At the same time it will trigger off an alarm showing Pause button had been activated.

Name: Anonymous 2013-04-18 18:41



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-18 18:47



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-18 18:52



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: SCADA 2013-04-19 6:11


Practical 4: Using CITECT to access Databases

OBJECTIVES:

1. To create Citect project that can access a Database.

2. Setup ODBC for Citect project to work with a relational database.

3. Write Cicode functions to Read and Write to a Database


1. Create new Citect Project and Configure Communication Settings

a. Open Citect Explorer and click on new project from File Menu to create a new project.

b. Enter the name of the new project as Emp._XX (Where XX is your prefer number; e.g. Emp_1 or Emp_2).

c. Configure Communication using Express Device I/O Setup for the new project

- select OMRON C200HS PLC and set to tnternal Memory.

2. Create Variable Tags

a. At the explorer, click on the tag folder to add on all the variable tags as listed in the table below

S/NO  Variable Tag Name   I/O Device   Type   Address

 1      ENum                IODev       INT   DM0001

 2      Sal                 IODev       INT   DM0002

3. Create new graphic page.

a. Click on the graphic/pages folders and then create a new page icon to give a blank canvass for the graphic builder.

b. Select the Text tool and typed in Employee Number, Employee Name and Salary as shown:

Citect Graphics Builder

Sample - EmpPage

Employee Number

Employee Name

Salary

c. Select the Number tool from the toolbar and place it next to Employee Number (as shown below). Select Appearance and Display Value. Under Type, select Select Numeric and insert variable tag, ENUM (as shown).

Text Properties-Appearance-Display Value

Type:

• Numeric

Numeric expression : ENum

Insert Tag : ENum


d. Repeat the same for variable tag Sal (Next to Salary, as shown below) :

Text Properties-Appearance-Display Value

Type:

• Numeric

Numeric expression : Sal

Insert Tag : Sal


e. Save the page as EmpPage under your own Citect project.


4. Create Cicode function to Read data from Access database.

a. Open Citect Project Editor and select Cicode Editor under tools (as shown).

Citect Project Editor [ Employee ] - COMPILED

Tools-Cicode Editor


b. In Cicode Editor select New under File menu (as shown).

Cicode Editor-File-New


c. Type in the Cicode function listed below :

------------------------------------------------------------

//Cicode function to read data from Employees database

GLOBAL STRING empName = "";

STRING FUNCTION

getName()        //function to get & display employee name

  RETURN empName

END

FUNCTION

dbRead()        //function to access and read from database

INT hSQL, iResult, iResult1;

hSQL = SQLConnect("DSN=Db1"); //ODBC : DSN set to db1 in ODBC setting

IF hSQL <> -1 THEN  //Test for connection to database

iResult = SQLExec(hSQL, "SELECT * FROM Employees where EmpNo = 2");

IF iResult = 0 THEN

IF SQLNext(hSQL) = 0 THEN

  ENum = SQLGetField(hSQL, "EmpNo"); //ENum- Citect var tag

empName = SQLGetField(hSQL, "EmpName"); //EmpName from database

Sal= SQLGetField(hSQL, "Salary"); //Sal - Citect Var tag

   END                           //Salary from database

 ELSE

 Message("SQLExec Error (dbRead)", SQLErrMsg(), 48); //DB execution error msg

   END

 ELSE

Message("SQLConnect Error (dbRead)", SQLErrMsg(), 48); //DB connection error msg

  END

 SQLEnd(hSQL);

END

-----------------------------------------------------------

d. Save the Cicode as EmpRead (make sure it's saved in your project).

e. Select compile from File menu in the Cicode Editor. Correct the errors, if any.

f. From the Citect Graphics Editor, select Text tool and place it next to Employee Name. Select Appearance and Display Value (as shown). Under Type; select String and click on Insert Function (as shown).

Text Properties-Appearance-Display Value

Type:

• String

Insert Function

g. Select getName() function which we have written earlier (as shown) and click OK.

Insert Function-getName

getName()

√ Insert arguments


Employee Number   #####.##

Employee Name  =getName()

Salary   #####.##


h. Select Button tool and create a button below Salary (as shown).

Button Properties-Appearance-General

Type:

• Text

Text: Get Employee Details

Font: ButtonFont

i. Select Input and click on Insert Functions, insert the dbRead() fucntion which we have written earlier (as shown below) and click OK.


Button Properties-Input-Touch

Action:

√ Up

Up command: dbRead()

Repeat rate: 500 milliseconds

Insert Function-dbRead

dbRead()

√ Insert arguments

j. Click OK and the screen should be as shown :

Employee Number   #####.##

Employee Name  =getName()

Salary   #####.##

Get Employee Details Button

Save the page under your project and go to section 6 "ODBC and Access database setup" on page 12 to setup ODBC with the Access database. Click on the Run button to test the project. Click on the Get Emplyee Details button and see the data from database being displayed on the screen.

Open the Employees table in Access database and modify the second record (change the name or salary) to test the Citect project.

Microsoft Access

db1: Database (Access 2000 file format)

Employees

Employees : Table

EmpNo       EmpName   Salary   Status

1           Albert     1100      E
2           Benjamin   1300      E
3           Charlie     990      E
(AutoNumber)              0

Create Cicode function to Write data into Access database.

Open a new page inside Cicode Editor.

Cicode Editor - empRead.ci

File-New

b. Type in the Cicode listed below :

------------------------------------------------------------

FUNCTION

dbUpdate()  //function to write or update database

INT hSQL, iResult, cSal;

STRING SQLString, SQLString1, sSal;

hSQL = SQLConnect("DSN=Db1");

IF hSQL <> -1 THEN   //Test for connection to database

  iResult = SQLExec(hSQL," SELECT * FROM Employees where EmpNo = 2");

IF iResult = 0 THEN  //Test for access & execution of SQL statement

IF SQLNext(hSQL) = 0 THEN

cSal = SQLGetField(hSQL, "Salary");

  cSal = cSal + 50;  //increase salary by 50

  sSal= cSal;        //convert interger to string variable

  SQLString = "UPDATE Employees SET Salary=" + sSal;

     END

SQLExec(hSQL, SQLString);

   ELSE

Message("SQLExec Error (dbUpdate)", SQLErrMsgQ, 48); //Display SQL error

      END
 
  ELSE

Message("SQLConnect Error (dbread)", SQLErrMsg(), 48); //DB Connection error

SQLEnd(hSQL);

   END

-----------------------------------------------------------

c. Save the Cicode as EmpWrite (make sure it's saved in your project).

d. Select compile from File menu in the Cicode Editor and correct any errors.

e. Under Citect Graphics Editor, create another button, select Input and Insert Functions-insert dbUpdate function which we have written earlier (as shown below) and click OK.

Button Properties-Input-Touch

Action:

√ Up

Repeat rate: 500 milliseconds

Up command: dbUpdate()

Insert Function-dbUpdate

dbUpdate()

√ Insert arguments

Repeated 500 milliseconds

Citect Graphics Builder - [Employee - EmpPage]

Employee Number   #####.##

Employee Name  =getName()

Salary   #####.##

Get Employee Details Button   Increase Salary by 50 Button

f. Save the page under your project and click on the Run button to test the project.

g. Click on the "Get Employee Details" button and see the data from database being displayed on the screen. Next click on the "Increase Salary by 50" button to update the database then click on "Get Employee Details" button again - see that the data has been changed on the screen. Modify the records in the Access database and test the Citect project again.

6. ODBC and Access database setup

a. Create myCitectDB folder and copy to C Drive
(C:\temp\XX directory), where XX is your prefer no

b. Open Control Panel and double-click on BDE Administrator icon and then select ODBC Administrator from Object menu (as shown below) :

Control Panel-BDE Administrator-Object-ODBC Administrator

Under User DSN, click Add.

User DSN

Create New Data Source

Select a driver for which you want to set up a data source

Name : Driver do Microsoft Access [*.mdb]

Finish button

Under Window 7

Control Panel-System and Security-Administrative Tools-Data Sources (ODBC)

User DSN

Name: MS Access Database

Driver: Microsoft Access Driver(*.mdb. *.accdb)


Select Microsoft Access Driver [*.mdb] and click Finish.

Type db1 inside Data Source Name and click on Select under databases :

ODBC: Microsoft Access Setup

Data Source Name: db1

Select Database

Database Name: *.mdb


Select C drive, myCitectDB directory (C:\temp\XX\myCitectDB)

ODBC Microsoft Access Setup

Data Source Name: db1

Select Database

Database Name: db1.mdb

Directories

c:\...\wwwroot\mycitectdb

List Files of Type: Access Databases [*.mdb]

Drives:

c:


Select db1.mdb (database name of your Access database) and click OK.

ODBC Microsoft Access Setup

Data Source Name: db1

Database

Database: C:\Inetpub\wwwroot\myCitectDB\db1.mdb

System Database

• None


Click OK to confirm the database & ODBC setting.


ODBC Data Source Administrator

User DSN

User Data Sources:

Name: db1

Driver: Microsoft Access Driver(*.mdb)

An ODBC User data source store information about how to connect to the indicated data provider. A User data source is only visible to you, and can only be used on the current machine.

OK button


Click OK and you are ready to use the Access database with the ODBC setting.

Exercise:

1) Modify Cicode to read/get employee data from 3rd record in database table.

2) Modify Cicode functions to increase salary of 3rd record by 100.

Name: SCADA 2013-04-24 6:08

More Codes:

AutoMove.ci

FUNCTION

AutoMove()   //Function to move the cylinders
INT counter=0; //Create and set counter used to stored number of cycles to 0
WHILE counter<NumCycles DO //while loop to run the number of cycles set by users
Cylinder5=1   //To extend cylinder 5
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder6=1   //To close cylinder 6
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder5=0   //To retract cylinder 5
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder4=1  //To extend cylinder 4
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder5=1   //To extend cylinder 5
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder6=0   //To open cylinder 6
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder5=0   //To retract cylinder 5
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder4=0   //To retract cylinder 4
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
counter=counter+1 //add 1 to counter after 1 cycle is completed
CompCycles=counter //add completed cycles to declared varables tag to be display on screen
END
END



MoveRobot.ci

FUNCTION

MoveStep1()   //Function to move the cylinders
Cylinder5=1   //To extend cylinder 5
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder6=1   //To close cylinder 6
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder5=0   //To retract cylinder 5
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder4=1   //To extend cylinder 4
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder5=1   //To extend cylinder 5
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder6=0   //To open cylinder 6
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder5=0   //To retract cylinder 5
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
Cylinder4=0   //To retract cylinder 4
SleepMS(300)  // Wait for 0.3 sec
WHILE TStop=1 DO //if TStop button is press end sequence
END
END

Name: Anonymous 2013-04-24 6:31

Name: Anonymous 2013-04-24 12:47



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-24 12:52



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-24 12:58



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: Anonymous 2013-04-24 13:05



Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop


Searching for legit Microsoft Product keys, Windows 8,7,Studio,Server etc.?

 Mail me at jeremiahgoldstein@hotmail.com

 25$ a pop

Name: SCADA 2013-05-02 5:35

More Cicode:

WaterTank

FillWater.ci

FUNCTION
FillWater()
INT count=0
WATER_LEVEL = 0
WHILE count < 100 DO
    WATER_LEVEL=WATER_LEVEL+10
    count = count+10
    SleepMS(500)
END
END

FUNCTION
DrainWater()
INT count=0
WATER_LEVEL = 100
WHILE count < 100 DO
    WATER_LEVEL=WATER_LEVEL-10
    count = count+10
    SleepMS(500)
END
END

Name: SCADA 2013-05-12 23:53

Citest Directory :

Activex.ci

FUNCTION
ActiveXCreate(STRING sControl, STRING sID, INT iXPos = 100, INT iYPos = 100, INT iWidth = 500, INT iHeight = 300)

    // Call this function with iXPos set to -1 and iYPos set to an AN number of a
    // display object which defines the size of the area to display the ActiveX
    // NOTE: the display object must be animated in some way to make the AN number
    //       become active at runtime (eg Set the visibility "Hidden When' field to FALSE

    OBJECT    CallStack;
    OBJECT    Control;
    INT    nResult;
    INT    a, b, c, d;

    IF (iXPos = -1) THEN
        IF (DspGetAnExtent(iYPos, a, b, c, d) = 0) THEN
            iXPos = b; iYpos = a;
            iWidth = d - b; iHeight = c - a;
        ELSE
            iXPos = 100; iYPos = 100;
        END
    END

    Control = _CreateControlObject(sID, sControl, iXPos, iYPos, iXPos+iWidth, iYPos+iHeight, sControl);
END

INT
FUNCTION
ActiveXInstall(STRING sFile, STRING sSourcePath = "")

    STRING    sPath, sName;

    IF (StrSearch(0, sFile, ".") = -1) THEN sFile = sFile + ".ocx"; END
    sName = StrLeft(sFile, StrSearch(0, sFile, "."));

    sPath = GetEnv("WinDir");
    IF (StrRight(sPath, 1) = "\") THEN sPath = StrLeft(sPath, StrLength(sPath)-1); END

    IF (sSourcePath = "") THEN sSourcePath = "[Run]:ActiveX"; END
    sSourcePath = PathToStr(sSourcePath);
    IF (StrRight(sSourcePath, 1) = "\") THEN sSourcePath = StrLeft(sSourcePath, StrLength(sSourcePath)-1); END

    IF NOT FileExist(sSourcePath+"\"+sFile) THEN RETURN(FALSE); END
    IF FileExist(sPath+"\System32") THEN sPath = sPath + "\System32"; ELSE
    IF FileExist(sPath+"\System") THEN sPath = sPath + "\System"; END END


    IF NOT FileExist(sPath+"\"+sFile) AND ((WndGetFileProfile("Install", "Compatable1", "", sSourcePath+"\"+sName+".ini") = "") OR (NOT FileExist(sPath+"\"+WndGetFileProfile("Install", "Compatable1", "", sSourcePath+"\"+sName+".ini")))) AND
                          ((WndGetFileProfile("Install", "Compatable2", "", sSourcePath+"\"+sName+".ini") = "") OR (NOT FileExist(sPath+"\"+WndGetFileProfile("Install", "Compatable2", "", sSourcePath+"\"+sName+".ini")))) AND
                          ((WndGetFileProfile("Install", "Compatable3", "", sSourcePath+"\"+sName+".ini") = "") OR (NOT FileExist(sPath+"\"+WndGetFileProfile("Install", "Compatable3", "", sSourcePath+"\"+sName+".ini")))) AND
                          ((WndGetFileProfile("Install", "Compatable4", "", sSourcePath+"\"+sName+".ini") = "") OR (NOT FileExist(sPath+"\"+WndGetFileProfile("Install", "Compatable4", "", sSourcePath+"\"+sName+".ini")))) AND
                          ((WndGetFileProfile("Install", "Compatable5", "", sSourcePath+"\"+sName+".ini") = "") OR (NOT FileExist(sPath+"\"+WndGetFileProfile("Install", "Compatable5", "", sSourcePath+"\"+sName+".ini")))) THEN

        TRACEMSG("ActiveX File '"+sFile+"' is not installed, Installing to "+sPath);

        FileCopy(sSourcePath+"\"+sFile, sPath+"\"+sFile, 0);
        TRACEMSG("ActiveX File '"+sFile+"' copy to "+sPath+" Directory");
        IF (WndGetFileProfile("Install", "Additional1", "", sSourcePath+"\"+sName+".ini") <> "") THEN FileCopy(sSourcePath+"\"+WndGetFileProfile("Install", "Additional1", "", sSourcePath+"\"+sName+".ini"), sPath+"\"+sFile, 0); END
        IF (WndGetFileProfile("Install", "Additional2", "", sSourcePath+"\"+sName+".ini") <> "") THEN FileCopy(sSourcePath+"\"+WndGetFileProfile("Install", "Additional2", "", sSourcePath+"\"+sName+".ini"), sPath+"\"+sFile, 0); END
        IF (WndGetFileProfile("Install", "Additional3", "", sSourcePath+"\"+sName+".ini") <> "") THEN FileCopy(sSourcePath+"\"+WndGetFileProfile("Install", "Additional3", "", sSourcePath+"\"+sName+".ini"), sPath+"\"+sFile, 0); END
        IF (WndGetFileProfile("Install", "Additional4", "", sSourcePath+"\"+sName+".ini") <> "") THEN FileCopy(sSourcePath+"\"+WndGetFileProfile("Install", "Additional4", "", sSourcePath+"\"+sName+".ini"), sPath+"\"+sFile, 0); END
        IF (WndGetFileProfile("Install", "Additional5", "", sSourcePath+"\"+sName+".ini") <> "") THEN FileCopy(sSourcePath+"\"+WndGetFileProfile("Install", "Additional5", "", sSourcePath+"\"+sName+".ini"), sPath+"\"+sFile, 0); END

        Sleep(1);
        IF FileExist(sPath+"\Regsvr32.exe") THEN
            IF (Exec(sPath+"\Regsvr32.exe /s "+sPath+"\"+sFile, 6) = 0) THEN
            TRACEMSG("ActiveX File '"+sFile+"' Installed"); END
        ELSE
            IF (Exec(sSourcePath+"\Regsvr32.exe /s "+sPath+"\"+sFile, 6) = 0) THEN
            TRACEMSG("ActiveX File '"+sFile+"' Installed"); END
        END
        RETURN (TRUE);
    END

    RETURN (FALSE);
END


// ----------------------------------------------------------------
// WEB BROWSER CONTROL
// ----------------------------------------------------------------

FUNCTION CreateWebBrowser()
    ActiveXCreate("WebBrowser", "{8856F961-340A-11D0-A96B-00C04FD705A2}", 200, 120, 375, 190);
END

FUNCTION WebNavigate(STRING URL)    _ObjectCallMethod(ObjectByName("WebBrowser"), "Navigate2", URL, "", "", "", "");    END

// ----------------------------------------------------------------
// WEB CONTROL
// ----------------------------------------------------------------
FUNCTION CiMeterX_Click(Object This)
    PROMPT("Click event!");
END

FUNCTION CiMeterX_DblClick(Object This)
    PROMPT("Double click event!");
END

FUNCTION CiMeterX_MouseMove(Object This, INT Button, INT Shift, REAL X, REAL Y)
STRING Msg;
    Msg = IntToStr(X) + ", " + IntToStr(Y);
    PROMPT("MouseMove event: " + Msg);

END

Name: SCADA 2013-05-12 23:55

Citest Directory :

Alarms.ci

//    FILE:        Alarms.ci
//
//
//    DESCRIPTION:    This file contains various functions that show how
//            you can customise the way alarms behave.
//            If you want to attach Operator Comments to Alarms
//            or change analog alarm properties by selecting them
//            from an alarm list then the following functions can
//            be copied to your project.
//
//    NOTES:        If you don't want the above then you don't need any
//            of the cicode shown here.
//   

//     ---------------------        Attach Comment Functions     ------------------------
//
//    FUNCTION:    SetEventAn
//
//    DESCRIPTION:    Remembers the Animation Number selected by the
//            operator. This function is called via the left mouse
//            button (PageWide Keyboard) when the user clicks on a
//            Alarm in the list.

INT    hEventAn;

FUNCTION
SetEventAn()
    int    hAn;

    hAn = KeyGetCursor();
    IF hAn <> -1 THEN
        hEventAn = hAn;
    END
END

//    FUNCTION:    GetEventAn
//    RETURN VALUE:    hEventAn

INT       
FUNCTION   
GetEventAn()   
    Return(hEventAn);   
END

//    FUNCTION:    AttachComment
//
//    DESCRIPTION:    Attach a comment to a alarm summary.

FUNCTION
AttachComment(int hFault)
    int    hAn;
    string    sFault;

    sFault = FaultCondition(hFault);
    IF hEventAn <> -1 THEN
        hAn = KeyGetCursor();
        KeySetCursor(hEventAn);
        AlarmComment(sFault);   
        KeySetCursor(hAn);
    END
END

//    FUNCTION:    FaultCondition
//
//    DESCRIPTION:    Get the reason for the fault. If fault is less than
//            5 get a standard fault from the array of fault
//            messages, otherwise get the reason from the user.
//   
//    NOTE:        The @() characters define strings that can be
//            translated at runtime.

STRING    sFaults[6] = "", "@(Electrical)", "@(Mechanical)", "@(Operational)", "@(Process)", "@(Other)";

STRING
FUNCTION
FaultCondition(int hFault)
    string    sFault;

    IF hFault < 5 THEN
        RETURN sFaults[hFault];
    ELSE
        RETURN Input("@(Alarm Comment)", "@(Enter the reason for the alarm)", "");
    END
END


//    FUNCTION:    AlarmMoveCursor
//
//    DESCRIPTION:    This function is used to move an object to indicate the Alarm
//            that is currently selected.
//   
//    REVISION    15 April 98    Steve Schilg    Modified Cursor Offset.
//
//    AN        First AN of Alarm list
//    Count        Number of Alarms in the Alarm List
//    ObjAn        Animation Number of Object to be moved
//   
//    RETURN VALUE    None.


FUNCTION
AlarmMoveCursor(INT AN,INT Count, INT ObjAn)
INT hAn,X,Y;
   
    hAn    =    KeyGetCursor();                !Get AN currently in Focus
    IF (hAn >= AN) AND (hAn <= (AN+Count)) THEN    !Check if in range
        DspAnGetPos(hAn,X,Y);                !Get XY co-ordinates of AN
        DspAnMove(ObjAn,X-9,Y+5);            !Move Object
    END
END

//    FUNCTION:    ResetEventAn
//
//    DESCRIPTION:    Resets the hEventAn variable so that the Alarm
//            Select Cursor does not point to the last selected An.
//            Called on Page Entry or Exit.

FUNCTION
AlarmResetEventAn()
    hEventAn=0;
END

//    FUNCTION:    AlarmSelected
//
//    DESCRIPTION:    Checks if there is a Alarm displayed at the AN where the
//            Alarm Select Cursor is positioned.
//    AN        First AN of Alarm list
//    Count        Number of Alarms in the Alarm List
//
//    RETURN VALUE:    TRUE if alarm selected, FALSE if no Alarm  selected


INT
FUNCTION
AlarmSelected(Int An,Int Count)
    IF StrLength(AlarmGetDsp(GetEventAn(), "Tag")) > 0 AND
            (GetEventAn() >= An) AND (GetEventAn() <= (Count+An)) THEN
        Return(1);
    ELSE
        Return(0);
    END
END

!---------------------------- Set Analog Alarm Thresholds -------------------------

// The following Function should be called from a alarm list that shows all configured alarms.
// You need to set up an alarm page that shows all alarms but is not updated when the status of an alarm is
// changed. To do this use a button with the command AlarmSetInfo(21,3,4)


INT iRecNo;
STRING sHighHigh,sHigh,sLow,sLowLow,sDeadBand,sDeviation,sRate;

FUNCTION
AlarmSet()
INT  hAn;
STRING sTag,sName,sEnab,sDisab;
    SleepMS(250);       
    KeySetCursor(GetEventAn());   
    hAn = KeyGetCursor();
       
    sTag = AlarmGetDsp(hAN, "Tag");

    IF StrLength(sTag) > 0 THEN
       
        sName    =AlarmGetDsp(hAN, "Name");
        iRecNo    =StrToInt(AlarmGetDsp(hAN, "RecNo"));
   
        sHighHigh=AlarmGetThreshold(0);       
        sHigh    =AlarmGetThreshold(1);   
        sLow    =AlarmGetThreshold(2);
        sLowLow    =AlarmGetThreshold(3);
        sDeadBand=AlarmGetThreshold(4);
        sDeviation=AlarmGetThreshold(5);
        sRate    =AlarmGetThreshold(6);

        FormNew("Alarm Tune",30,12,0);
       
        FormPrompt(0,0,"Tag");
        FormPrompt(11,0,": "+sTag);
        FormPrompt(0,1,"Name");
        FormPrompt(11,1,": "+sName);

        FormRadioButton(0,2,"Enable",sEnab);
        FormRadioButton(11,2,"Disable",sDisab);

        FormInput(0,3,"High High     ",sHighHigh,10);
        FormInput(0,4,"High          ",sHigh,10);
        FormInput(0,5,"Low           ",sLow,10);
        FormInput(0,6,"Low Low       ",sLowLow,10);
        FormInput(0,7,"DeadBand      ",sDeadBand,10);
        FormInput(0,8,"Deviation     ",sDeviation,10);
        FormInput(0,9,"Rate of Change",sRate,10);

        FormButton(0 ,11,"   OK   ", 0, 1);
        FormButton(12,11," Cancel ", 0, 2);

        IF FormRead(0)=0 THEN
            KeySetCursor(hAn);   

            IF AlarmGetDsp(hAN, "Tag")= sTag THEN    !Check Still pointing to same AN
                AlarmSetThreshold(0,sHighHigh);
                AlarmSetThreshold(1,sHigh);
                AlarmSetThreshold(2,sLow);
                AlarmSetThreshold(3,sLowLow);
                AlarmSetThreshold(4,sDeadBand);
                AlarmSetThreshold(5,sDeviation);
                AlarmSetThreshold(6,sRate);
           
                IF sDisab="1" THEN
                    AlarmDisable(0,0);
                END
                IF sEnab="1" THEN
                    AlarmEnable(0,0);
                END
            ELSE
                Message("Warning", "Alarms Changed - Please Select Alarm Again",48);
            END
        END
    END
END

Name: Anonymous 2013-05-12 23:56

>>31
that is some ugly pascal code.

Name: SCADA 2013-05-13 0:06

Citect Directory :

EXAMPLE.CI

EXAMPLE.CI

//
//    FILE:        Example.ci
//
//    DESCRIPTION:    This file contains various functions for the Example Project.
//   
//      NOTE:



//    FUNCTION:    DisplayHistoryFile
//   
//    DESCRIPTION:    Calls Select History form then translates selected
//            file from native to local text and displays it
   
FUNCTION
DisplayHistoryFile(INT AN)
    STRING    sFile;

    sFile = FormSelectHistoryFile("[data]:replog.001");
    IF StrLength(sFile) > 0 THEN
        LanguageFileTranslate( sFile,PathToStr("[DATA]:\report.rtf"));
        DspRichTextLoad(AN,PathToStr("[DATA]:\report.rtf"));
    END
END


//    FUNCTION:    FormSelectHistoryFile
//
//    DESCRIPTION:    Provides a form to the operator allowing selection of
//            historical reports.
//
//    RETURN VALUE:    The File path of the report file.



STRING
FUNCTION
FormSelectHistoryFile( STRING sFile)
   
    INT    i;
    INT     iTime;
    INT     iFile;
    INT     iOffset;
    STRING     sBuf;
    STRING     sText;

    FormNew("@(Select History File)", 50, 9, 1);
    IF FileExist( sFile) THEN
        sBuf = sFile + "     " + TimeToStr(FileTime(sFile), 4);
    END   

    FormListBox(0,0,50,8, sBuf, 0);   
       
    FOR i = 1 TO 999 DO
        sFile = StrLeft( sFile, StrLength(sFile)-3);    !Strip extension
        sFile = sFile + i:#0#;                    !Add extension
        IF FileExist(sFile) THEN
            sText = sFile + "     " + TimeToStr(FileTime(sFile), 4);
            FormAddList(sText);
        END   
    END
       
    FormButton(8, 8,  "@(OK,12,C)", 0, 1);
    FormButton(30, 8, "@(Cancel,12,C)", 0, 2);   
    FormRead(0);
    iOffset = StrSearch(0, sBuf,"     ");
    IF iOffset > 0 THEN
        sBuf = StrLeft( sBuf,iOffset );
    END
    Return( sBuf)
END

INT
FUNCTION
FileTime(STRING sFile)
    INT     iTime;
    INT     iFile;
    IF FileExist(sFile) THEN
        iFile = FileOpen( sFile, "r");
        iTime = FileGetTime(iFile);
        FileClose(iFile);   
    END    
    Return(iTime);
END



// ------------------------------- Menu Page Functions ----------------------------
//     FUNCTION:     RunExcel
//
//     DESCRIPTION:    Function will Run Excel and load the DDE Form
//            Utility (ddeformu.xls)from the \Citect\bin directory
//            and then load the spreadsheet demo.xls from the path
//             where the Citect Project is stored.
//             If Citect cannot load Excel then a Message will be
//            displayed advising of the failure.

FUNCTION
RunExcel()
    STRING    sProgram;
   
    sProgram = "Excel " + PathToStr("[BIN]:\ddeformu.xls")+" "+PathToStr("[RUN]:\demo.xls");
    IF ( Exec( sProgram ) <> 0 ) THEN
        ShortCut("DDE_Demo", "Excel.exe [BIN]:\ddeformu.xls [RUN]:\demo.xls");
    END;
END
   
//     FUNCTION:    ShortCut
//
//    VERSION:    3.0    Added support for path substitution strings.
//            3.1    Updated Dialog messages and allow file type selection
//
//    DESCRIPTION    This function will launch a third party application
//            and then load a file in that application
//            This function will look for the path in the Citect.ini
//            file if no path has been entered a form will appear to
//            enable the user to select the appropriate file.
//    Parameters:    sShortCutName     = should be a unique identifier  Excel_Demo
//            sCommand    = Command String
//    EXAMPLE:
//            ShortCut("DDE_Demo", "Excel.exe [BIN]:\ddeformu.xls [RUN]:\demo.xls");
//            This will launch excel then load ddeformu.xls then load demo.xls
//            The paths to each file will be stored in Citect.ini in the [PATHS]
//            section.
//       

STRING Command[20];    !Command array - maximum of 20 commands

FUNCTION
Shortcut(String sShortCutName, String sCommand)
    INT    Words;
    INT     i;
    INT     iSearch;
    INT     hMessage;
    STRING    sPath;
   
    While iSearch <> -1 DO            !Count words in sCommand
        iSearch=StrSearch(iSearch+1,sCommand," ") ;
        IF iSearch <> -1 THEN
            Words = Words + 1;
        END
    END
   
    FOR i = 0 TO Words DO                !Store commands in Array
        Command[i]=StrWord(sCommand);
    END

    FOR i = 0 to Words DO             !check if path is already saved in ini   
        sPath =ParameterGet("PATHS", sShortCutName + Command[i],"");
   
        IF StrRight(sPath, StrLength(Command[i])) <> Command[i] THEN   
            Command[i]= _FileSavePath(Command[i],sShortCutName);    !if no then prompt for input then Save
        ELSE
            Command[i] = sPath;
        END
    END

    FOR i = 0 to Words DO
        IF NOT FileExist(PathToStr(Command[i])) THEN            !Check if load file exists
            Command[i] = _FileSavePath(Command[i],sShortCutName);
        END   
    END

    FOR i = 0 to Words DO
        sCommand = sCommand + PathToStr(Command[i]) + " ";
    END
   
    hMessage = FlashMessage("@(Shortcut)","@(Loading)" + " "+sShortCutName,-1);

    IF Exec(sCommand) = 0 THEN        !Try and run file
        FlashMessageClear(hMessage);
    ELSE
        FlashMessageClear(hMessage);
        IF StrToValue(sCommand) = -1 THEN
            Message("@(Shortcut)", "@(Cannot run Shortcut - file path not defined)",48);
        ELSE
            Message("@(Shortcut)", "@(Cannot run)" + " " + sCommand,48);
        END
    END
END

PRIVATE
STRING
FUNCTION
_FileSavePath(String sFile,String sShortCutName)

    INT    index    =    0;
    INT     offset    =    0;
    STRING    sPath;
    STRING     sFilename;
   
    IF sFile = "-1" THEN
        Return ("-1");         !If previous file not Selected correctly then skip
    END
       
    IF StrSearch(0,sFile,"[") > -1 THEN    !If Path Substitution used
        IF FileExist(PathToStr(sFile)) THEN
            sPath = sFile;
            ParameterPut("PATHS", sShortCutName+sFile, sPath);   
            Return sPath;
        END
    END
   
    WHILE index > -1 DO    !Check if path + file find position of last \
        index = StrSearch(offset,sFile,"\") ;
        IF index > -1 THEN
            offset = index +1;
        END
    END
    sFilename = StrRight(sFile, StrLength(sFile) - offset);


    Message(sShortCutName + " " + "@(Shortcut Setup)","@(Can't find)"+ " "+sFilename,48);
   
       
    sPath = FormOpenFile("Select "+sFilename+" File", sFilename,
                StrLeft(sFilename,1)+"*."+StrRight(sFilename,3) +" |"+StrLeft(sFilename,1)+"*."+StrRight(sFilename,3)+"| "
                 + "All Files (*.*)|*.*|");

    IF StrRight(sPath,StrLength(sFilename)) = sFilename THEN
        ParameterPut("PATHS", sShortCutName+sFile, sPath);
        return sPath;
    ELSE
        Message("@(Shortcut Setup)","@(Shortcut has not been saved)",48);
        Return ("-1");
    END
END


//    FUNCTION:        FlashMessage
//
//    DESCRIPTION:    This function will display a message to the user for
//                a period then remove it from the screen.
//                If flashtime is set to -1 the function returns a
//                message handle and leaves the message on the sceen.
//                The message can be cleared from the    screen by using
//                the FlashMessageClear Function.

INT
FUNCTION
FlashMessage(STRING sTitle,String sMessage,Int iFlashTime)
    INT    hForm;
    INT    Width;

    IF StrLength(sTitle) > StrLength(sMessage) THEN
        Width = StrLength(sTitle);
    ELSE
        Width = StrLength(sMessage);
    END

    hForm = FormNew(sTitle, Width, 1, 9);
    FormPrompt(0, 0, sMessage);
    FormRead(1);
           
    IF iFlashTime = -1 THEN
        Return(hForm);   
    ELSE
        Sleep(iFlashTime);
        FormDestroy(hForm);
    END
END

FUNCTION
FlashMessageClear(STRING hMessage)
    FormDestroy(hMessage);
END

Name: SCADA 2013-05-13 0:10

Citect Directory :

Continue

EXAMPLE.CI

//    -----------    Operator Log Page Functions        --------

//    FUNCTION:    OperLog   
//
//    DESCRIPTION:    Sends message to Operator Log when user logs on

FUNCTION
OperLog(STRING sString);
INT hOper_Log;
STRING sData;

    sData = StrPad(Date(2)," ",10) + StrPad(Time(1)," ",12)+ sString;
    hOper_Log = DevOpen("Oper_Log", 0);
    DevWriteLn(hOper_Log, sData);
END


//    FUNCTION:    DisplayTextFile
//
//    DESCRIPTION:    Displays a Text file on a page that has An's defined
//            to mark the line positions.
//   
//            See also DspFile() function in help.

PUBLIC
FUNCTION
DisplayTextFile(String sFile, String sPage, INT AN = 21, INT NoLines = 24, INT Width=95, String FontName="Arial", INT Size=9, INT FgndColr=White, INT BgndColr=Black)
    PageDisplay(sPage);
    DspFile(AN, DspFont(FontName, Size, FgndColr, BgndColr),NoLines, Width );
    IF PageInfo(0) = sPage THEN
        DspFileSetName(AN, sFile);
    END
END
   
//    ---------------        Utilities Page Functions     -------------------

//    FUNCTION:    CicodeWindow
//
//    DESCRIPTION:    Opens a Cicode Window in the Kernel
//    Mode        0     Hidden
//            1    Displayed   

INT     KCheck;        !Used to determine if a Cicode Window is already open.

PUBLIC
FUNCTION
CicodeWindow(INT Mode=0)
    KCheck = 0;
    KerCmd( "Cicode", "_TestCicodeWindow()");
    SleepMS(500);               
    IF KCheck <> 1 THEN   
        DspKernel( Mode);        !Activates Kernel in Display Mode
        KerCmd( "Main", "Cicode");    !Activates Cicode Window in Kernel
    ELSE
        DspKernel( Mode);
    END
END

PRIVATE
FUNCTION
_TestCicodeWindow()
    kCheck = 1;
END

//     ---------------        XY Plot Page Functions         ------------------

Real     Buf1[10];                           
Real     Buf2[10];
Real     Buf3[10]  =20,20,60,60,40,40,50,60,55,60;
Real     YTable[10]=10,20,30,40,50,60,70,80,90,100;
Real     XTable[10]=10,20,40,50,60,60,50,40,20,10;
Int     hPlot;

FUNCTION
Plot(INT hAn,INT iGridCol= Grey,INT iFrameCol= Black,INT iFillCol=Black)
    Int    FrameWidth=3;

    hPlot=PlotOpen(hAn,"Display",65);
    //PlotGrid(hPlot,10,0,0,410,230,5,iGridCol,9,iGridCol,FrameWidth,iFrameCol,iFillCol,0);
    //PlotScaleMarker(hPlot,-3,227, 6, 1, Black, 1);
    PlotGrid(hPlot,10,0,0,833,530,5,iGridCol,9,iGridCol,FrameWidth,iFrameCol,iFillCol,0);
    PlotScaleMarker(hPlot,-3,527, 6, 1, Black, 1);
    PlotLine(hPlot, 0, Light_Red,   2, 7, Magenta       , 1, 10, Buf1[0], 0, 500,1);
    PlotLine(hPlot, 0, Light_Cyan,  1, 6, Yellow       , 1, 10, Buf2[0], 0, 500,1);
    PlotLine(hPlot, 3, Light_Blue,  1, 4, Light_Red    , 1, 10, Buf3[0], 0, 500,1);
    PlotXYLine(hPlot,0,Light_Green,1,0,White,1,10,XTable[0],0,100,YTable[0],0,100,1);
    PlotClose(hPlot);   
END

FUNCTION
UpdateRandom()
    INT    I;
    FOR I = 0 TO 9 DO
        buf1[I] = TestRandomWave(1, 0, 500.0,0);
    END
END

FUNCTION
UpdateTest()
    INT     I;
    FOR I = 0 to 9 DO
        buf2[I] = Plot_1[I];
    END
END






//    FUNCTION:    CraneDemo
FUNCTION
CraneDemo()

    INT    iStart;

    ErrSet(1);
    //Set Truck Start Positions
    TruckPosition = 15000;
    BoomMain = 0;
    ClawUpper = 24;
    ClawTip = 53;
    BoomExtent = 0;
    Cable = 0;

    // Move truck in
    PlayWav("CraneIn","","",3);
    iStart=SysTime();
       
    WHILE (SysTime() - iStart < 8000) DO
        TruckPosition = TruckPosition - 250;
        SleepMS(30);
    END
    SleepMS(50);
    TruckPosition = 0;
   
    // Raise boom   
    SleepMS(200);
    PlayWav("Lift","","",3);
    iStart=SysTime();
    WHILE (SysTime() - iStart  < 3000) DO
        BoomMain = BoomMain + 220;
        SleepMS(50);
    END
    IF (BoomMain > 8000) THEN BoomMain = 8000; END

    // Extend Boom
    SleepMS(200);
    PlayWav("Crane","","",3);
    iStart=SysTime();
    WHILE (SysTime() - iStart  < 4500) DO
        BoomExtent = BoomExtent + 1;
        SleepMS(50);
    END

    SleepMS(200);
    PlayWav("lift","","",3);
    iStart=SysTime();
    WHILE (SysTime() - iStart  < 3000) DO
        Cable = Cable + 1;
        SleepMS(50);
    END
    IF (Cable > 50) THEN Cable = 50; END

    SleepMS(200);
    PlayWav("Crane","","",3);
    iStart=SysTime();
    WHILE (SysTime() - iStart  < 4500) DO
        ClawUpper = ClawUpper + 1;
        SleepMS(70);
    END
    IF (ClawUpper > 65) THEN ClawUpper = 65; END

    SleepMS(200);
    PlayWav("Idle","","",3);
    iStart=SysTime();
    WHILE (SysTime() - iStart  < 1600) DO
        ClawTip = ClawTip + 1;
        SleepMS(100);
    END
    IF (ClawTip > 75) THEN ClawTip = 75; END
    ErrSet(0);
END

INT    hPort;
INT FUNCTION StartSerial(STRING sPort)
    hPort = ComOpen(sPort, 0);
    IF hPort < 0 THEN
        Prompt("Cannot open port " + sPort);
        RETURN -1;
    END
    RETURN 0;
END

INT FUNCTION SerialWrite(STRING buffer, INT length)
    INT    error;
   

    ! put data into buffer and set length
    error = ComWrite(hPort, buffer, length, 0);
    IF error THEN
        Prompt("Error Writing port");
        ComReset(hPort);
    END

    RETURN 0;
END

FUNCTION
RefreshFileDsp()

    INT    iNum    = WinNumber();

    IF PageInfo(0) <> "File" THEN WinSelect(0); END

    IF PageInfo(0) = "File" THEN
        DspFileSetName(21,DspFileGetName(21));
        DspFileScroll(21,4,
        DspFileGetInfo(21, 4) - DspFileGetInfo(21, 2) - DspFileGetInfo(21, 1));
    END

    WinSelect(iNum);
END

FUNCTION FileEndDsp()
    DspFileScroll(21,4,
    DspFileGetInfo(21, 4) - DspFileGetInfo(21, 2) - DspFileGetInfo(21, 1));
END

Name: SCADA 2013-05-13 0:11

Citest Directory :

Mmedia.ci


!    Multimedia Functions & Sequences


//    PlayWav

!     sFile     name of wav file (stored in project directory)
!    FromMs    Millisecond offset to start playing from   
!    ToMs    Millisecond offset to stop playing
!    Mode    0 play part of track before returning
!        1 play part of track and return immediately
!        2 play whole track before returning
!        3 play whole track and return immediately

String
FUNCTION    PlayWav(String sFile, String FromMs="", String ToMs="", Int Mode=0)

String     sPath;
String     sCommand;
String     sError;
String     Status;
INT    counter=0;
   
    sPath = "[RUN]:" + sFile + ".wav";
    sPath = PathToStr(sPath);   
    sCommand = "Open " + sPath + " Alias WAV type WaveAudio";
    sError=    DspMCI(sCommand);

    While StrLeft(sError,11) = "MMSYSTEM289" AND (Counter < 3000) DO
        sleep(1);
        sError=    DspMCI(sCommand);
        counter = counter + 1;
    END

    DspMCI("Set WAV time format milliseconds");

    sCommand =  "Play WAV";        ! Mode 2 or 3 Play whole Track

    IF Mode = 0 or (MODE = 1) THEN    ! Play Part of Track
        sCommand = sCommand + " From "+FromMs+" To "+ToMs;
    END
   
    sError=DspMCI(sCommand);    ! Play Sound

    If StrLength(sError) > 1 THEN        !If Error then send to kernel window
        traceMSG(sCommand); traceMsg(sError);
    END

    IF (Mode = 0) or (Mode=2) THEN        !Check for completion
        Status = StrLower(DspMCI("Status WAV Mode"));
        While (Status = "playing") or (Status = "seeking") DO
            SleepMS(100);   
            Status = StrLower(DspMCI("Status WAV Mode"));
        END
        DspMCI("Close WAV");
    END

    IF Mode = 1 THEN
        TaskNew("CloseWav","",0);    !start new thread to check for completion
    END
    IF Mode = 3 THEN
        TaskNew("CloseWav","",0);
    END
    Return (sError);
END

FUNCTION
CloseWav()
String Status;
    Status = StrLower(DspMCI("Status WAV Mode"));
    While (Status = "playing") or (Status = "seeking") DO
        Sleepms(100);   
        Status = StrLower(DspMCI("Status WAV Mode"));
    END
    DspMCI("Close WAV");
END

Name: SCADA 2013-05-13 0:13

Citest Directory :

RECIPE.CI

//
//    FILE:    Recipe.ci
//
//    AUTHOR:    Martin Roberts
//
//    This file contains functions for displaying and editing a
//    database of recipes. The recipe database is defined in the
//    device form. This specifies the fields in the database and
//    the file name of the database.
//
//    A form is used to view the database. The form shows one record
//    and allows you to scroll through the database or search for
//    a recipe. You may also append new recipes or replace existing
//    recipe records.
//
//    You may use this code as an basis of your own recipe system.
//    To change for your use create new recipe database with the
//    fields required in the device form. Use the existing recipe
//    device as an example. Then change the code markes with CHANGES
//    below to use your fields.
//
//    REVISED:    30 Jan 1997    V5B2     Steve Schilg
//            Added support for langauge translation by adding @()
//            around strings.
//            Added PRIVATE function definitions.
//            14 May 1997    V5RC1     Steve Schilg
//            Search function rewritten to improve User Inteface
//            15 Nov 1997     V5.01B2 Steve Schilg
//            Search function modified to report record not found properly
//            Add recipe modified to display added record.       
//

//     temp memory variables to select and edit recipe
STRING    Name;
STRING    Descript;
STRING    Sugar;
STRING    Water;
STRING    Milk;
STRING    Salt;
STRING    Flour;
// CHANGE:     add your own temp variables //

//     other working variables
INT    hRecipe = -1;    !handle to recipe database       
INT    hForm = -1;    !handle to display form       
INT    hStatus;    !status field handle           
INT     hMsg;        !Record No Message field handle    
STRING     sFindString;    !String to find

//    FUNCTION:    OpenRecipe
//
//    DESCRIPTION:    This function opens the recipe database and loads
//            the first record into the memory variables and
//            displays it on the screen.

FUNCTION
OpenRecipe()

    IF hRecipe < 0 THEN
// CHANGE: use your own recipe name here, from device database //
        hRecipe = DevOpen("Recipes");
        IF hRecipe >= 0 THEN
            DatabaseToMemory();
        ELSE
            DspError("@(Cannot Open Recipe Database)");
        END
    END
END


//    FUNCTION:    SetBatchSize
//
//    DESCRIPTION:    This function sets the batch size for the recipe.

FUNCTION
SetBatchSize(INT newBatch)

    Batch = newBatch;   
    TotalPLC = SugarPLC + WaterPLC + MilkPLC + SaltPLC + FlourPLC;
    batchTotal = totalPLC * newBatch;
END


//    FUNCTION:    EditRecipe
//
//    DESCRIPTION:    Display the recipes database into a form and allow
//            the operator to scroll through and select a recipe.
//            When the Recipe is selected the recipe is copied
//            into the PLC variables.

INT
FUNCTION
EditRecipe()

    IF hForm >= 0 THEN
        DspError("@(Form already displayed)");
        RETURN 1;
    END

    hForm = FormNew("@(Recipe)", 50, 10, 1);

    FormInput(0, 0, "@(Name,12,L)", Name, 16);
    FormInput(0, 1, "@(Desc,12,L)", Descript, 32);
    FormInput(0, 2, "@(Sugar,12,L)", Sugar, 10);
    FormInput(26,2, "@(Water,12,L)", Water, 10);
    FormInput(0, 3, "@(Milk,12,L)", Milk,  10);
    FormInput(26,3, "@(Salt,12,L)", Salt,  10);
    FormInput(0, 4, "@(Flour,12,L)", Flour, 10);


//    CHANGES:
//    ADD extra fields here if required with FormInput().
//    You may have to increase the size of the Form to
//    fit you fields in by changing FormNew above.
       
    FormButton( 1, 6, "@(Select,47,C)", 0,1);
    FormButton( 1, 7, "@(Add,15,C)", AddRecipe,     0);
    FormButton(17, 7, "@(Replace,15,C)", ReplaceRecipe, 0);
    FormButton(33, 7, "@(Search,15,C)", SearchRecipe,  0);
    FormButton( 1, 8, "@(Prev,23,C)", PrevRecipe,    0);
    FormButton(25, 8, "@(Next,23,C)", NextRecipe,    0);
    FormButton( 1, 9, "@(Cancel,47,C)", 0, 2);

    hMsg = FormPrompt(1, 5, "              ");
    hStatus = FormPrompt(12, 5, "                     ");

    IF FormRead(0) = 0 THEN    !copy selected recipe to PLC variables
        NamePLC  = Name;
        DescPLC  = Descript;
        SugarPLC = Sugar;
        WaterPLC = Water;
        MilkPLC  = Milk;
        SaltPLC  = Salt;
        FlourPLC = Flour;
// CHANGES: add or modify fields here if required //
    END
    hForm = -1;

    SetBatchSize(1);

    RETURN 0;
END


PRIVATE
FUNCTION DelEditForm()

    IF hForm >= 0 THEN
        FormDestroy(hForm);
    END;
END

//    FUNCTION:    AddRecipe
//
//    DESCRIPTION:    This function is called when the Add button is
//            pressed.
//            It appends the current data in the form to the end
//            of the recipe database.

PRIVATE
INT
FUNCTION
AddRecipe()

    IF DevAppend(hRecipe) = 0 THEN
        FormGetData(hForm);
        MemoryToDatabase();
        UpdateForm();
        FormStatus("@(Recipe Appended)");       
    ELSE
        FormStatus("@(Cannot Append Record)");       
    END
    RETURN 0;
END


//    FUNCTION:    ReplaceRecipe
//
//    DESCRIPTION:    This function is called when the replace button is
//            pressed. It gets the current data from the form and puts it into the
//            current recpie record.

PRIVATE
INT
FUNCTION
ReplaceRecipe()

    FormGetData(hForm);
    MemoryToDatabase();
    FormStatus("@(Recipe Replaced)");       
    RETURN 0;
END


//    FUNCTION:    PrecRecipe
//
//    DESCRIPTION:    This function is called when the Prev button is
//            pressed. It gets the previous record in the recipe
//            database and puts the data into the form.

PRIVATE
INT
FUNCTION
PrevRecipe()

    IF DevPrev(hRecipe) = 0 THEN
        UpdateForm();
    ELSE
        FormStatus("@(No Prev Record)");       
    END
    RETURN 0;
END

//    FUNCTION:    NextRecipe
//
//    DESCRIPTION:    This function is called when the Next button is
//            pressed. It gets the next record in the recipe
//            database and puts the data into the form.

PRIVATE
INT
FUNCTION
NextRecipe()

    IF DevNext(hRecipe) = 0 THEN
        UpdateForm();
    ELSE
        FormStatus("@(No Next Record)");       
    END

    RETURN 0;
END

//    FUNCTION:    SearchRecipe
//
//    DESCRIPTION:    This function is called when the Search button is
//            pressed. It displays an input dialog to get the name
//            of the Name then trys to find the Name. If found the
//                data is put into the form.

PRIVATE
INT
FUNCTION
SearchRecipe()
   
    STRING     sPartial="1";
    STRING    sWhole;
    INT     RecNo;
    INT    Found;
    STRING    sField = "NAME";        !Field to Search
   

    FormNew("@(Search)", 50, 4, 1);
    FormInput(0,0, "@(Enter Recipe Name)", sFindString, 30);

    FormGroupBox(0, 1, 23, 4);
    FormRadioButton( 1, 2, "@(Match Whole Field)", sWhole);
    FormRadioButton( 1, 3, "@(Match Partial Field)", sPartial);
    FormButton(28, 3, "@(OK,15,C)", 0, 1);
    FormRead(0);

    RecNo = DevRecNo(hRecipe);        !Current Record Number

    DevSeek(hRecipe, 1);
   
    SELECT CASE sWhole        
    CASE "1"                !Match Whole Field
        IF DevFind(hRecipe, sFindString, sField) = 0 THEN
            Found = 0;
        ELSE
            Found = -1;
        END       
       
    CASE ELSE
        Found = StrSearch(0, StrLower(DevGetField(hRecipe, sField)), StrLower(sFindString));
        WHILE (NOT DevEOF(hRecipe)) AND (Found = -1) DO
            DevNext(hRecipe);
            Found = StrSearch(0, StrLower(DevGetField(hRecipe, sField)), StrLower(sFindString));
        END   
   
    END SELECT
    IF Found > -1 THEN
        UpdateForm();
    ELSE
        FormStatus("@(Recipe Not Found)");    
        DevSeek(hRecipe, RecNo);   
    END
    FormGoto(hForm);
    RETURN 0;
END


//    FUNCTION:    DatabaseToMemory
//
//    DESCRIPTION:    Copy the current database record into the memory
//            variables.

PRIVATE
FUNCTION
DatabaseToMemory()
    Name  = DevGetField(hRecipe, "Name");
    Descript  = DevGetField(hRecipe, "Descript");
    Sugar = DevGetField(hRecipe, "Sugar");
    Water = DevGetField(hRecipe, "Water");
    Milk  = DevGetField(hRecipe, "Milk");
    Salt  = DevGetField(hRecipe, "Salt");
    Flour = DevGetField(hRecipe, "Flour");
// CHANGES:  add or modify fields here if required //
END

//     FUNCTION:     UpdateForm
//    DESCRIPTION:    Updates form, gets data from file and displays
//                it in the form fields.

PRIVATE
FUNCTION
UpdateForm()
    DatabaseToMemory();
    FormSetData(hForm);
    FormStatus("");       
    FormRecordNo();           
END


//    FUNCTION:    MemoryToDatabase
//
//    DESCRIPTION:    Copy the memory variables into the current database
//            record.

PRIVATE
FUNCTION
MemoryToDatabase()

    DevSetField(hRecipe, "Name",  Name);
    DevSetField(hRecipe, "Descript",  Descript);
    DevSetField(hRecipe, "Sugar", Sugar);
    DevSetField(hRecipe, "Water", Water);
    DevSetField(hRecipe, "Milk",  Milk);
    DevSetField(hRecipe, "Salt",  Salt);
    DevSetField(hRecipe, "Flour", Flour);
// CHANGES: add or modify fields here if required //
END

//    FUNCTION:        FormStatus
//
//    DESCRIPTION:    This function displays the status message on the
//                form.
//                It does this by changing the prompt field text
//                message.

PRIVATE
FUNCTION
FormStatus(STRING sMessage)
    FormSetText(hForm, hStatus, sMessage);
END

//    FUNCTION:    FormRecordNo
//
//    DESCRIPTION:    Displays record number on form

PRIVATE
FUNCTION
FormRecordNo()
    FormSetText(hForm, hMsg, "@(Record)" + " " + IntToStr(DevRecNo(hRecipe)));
END

Name: SCADA 2013-05-13 0:14

Citest Directory :

Sample.CI

// This function creates a single instance of the CiMeter control at the designated location with an object name of "CiMeterEvent" and an event class of "CiMeterEvent"//
FUNCTION
CreateCiMeter(INT X1, INT Y1, INT X2, INT Y2)
    OBJECT    CiMeter;
    STRING    sCiMeterClass;
    STRING    sEventClass;
    STRING    sObjectName;
    INT        nAN;

    sCiMeterClass = "CiMeterX.TechMeter";
    sEventClass = "CiMeterEvent";
    sObjectName = "MyMeter";
    CiMeter = CreateControlObject(sCiMeterClass, sObjectName, X1, Y1, X2, Y2, sEventClass);
    nAN = AnByName("MyMeter");
    DspSetTip(nAN, "Click me to record the number of clicks");
    _ObjectSetProperty(CiMeter, "CaptionBackColor", 8421376);
    _ObjectSetProperty(CiMeter, "Caption", "Click me to record the clicks");
END

// This function shows how to change the title font of the CiMeter//
FUNCTION
CiMeterSetFont(STRING sFont, INT nSize, INT nBold)
    OBJECT    Font;
    OBJECT    CiMeter;

    CiMeter = ObjectByName("MyMeter");
    Font = _ObjectGetProperty(CiMeter, "CaptionFont");
    IF sFont <> "" THEN
        _ObjectSetProperty(Font, "Name", sFont);
    END
    IF nSize > 5 THEN
        _ObjectSetProperty(Font, "Size", nSize);
    END
    //_ObjectSetProperty(Font, "Bold", nBold)
END

// This function shows how to change the background colour of the CiMeter//
FUNCTION
CiMeterSetColour(STRING sObjectName)
    OBJECT    CiMeter;
    INT newColor;
    INT oldColor;

    CiMeter = ObjectByName(sObjectName);
    oldColor = _ObjectGetProperty(CiMeter, "BackColor");
    IF oldColor = 255 THEN
        _ObjectSetProperty(CiMeter, "BackColor", 8421376);
    ELSE
        _ObjectSetProperty(CiMeter, "BackColor", 255);
    END
END


// This function shows you how to write a mouse click event handler for the CiMeter//
FUNCTION
CiVBA_AN35_Click(OBJECT This)
    INT    nValue;
    INT    nMaxValue;

    nValue = _ObjectGetProperty(This, "Value");
    nMaxValue = _ObjectGetProperty(This, "MaxValue");
    IF nValue > nMaxValue THEN
        nMaxValue = nMaxValue + 20
        _ObjectSetProperty(This, "MaxValue", nMaxValue);
    END       
    nValue = nValue + 1;
    _ObjectSetProperty(This, "Value", nValue);

END

Name: SCADA 2013-05-13 0:17

Citest Directory :

Simulatr.ci

//    FILE:        Simulatr.ci
//
//    DESCRIPTION:    The code in this section is used for simulating the
//            I/O device (PLC) to provide a realistic look and
//            feel to the example project.
//
//    NOTE:        You do not need this in your project.


INT    DemoRunning = FALSE;

//    FUNCTION:    Startup
//
//    DESCRIPTION:    This function is called at startup - See Definitions
//            |Parameters | Code | Startup.
//             This function starts up the Simulation functions
//            which will run only on the I/O Server
//
//    VERSION:     2.0
//    DATE:        2 Apr 1996
//    REVISION:    Changed to run only on the I/O server.
//
//    VERSION:     2.1
//    DATE:        06 Oct 2000

FUNCTION
Startup()

    INT    I;
           
    CheckAnsiToOEM();

    sleep(10);

    ! Initialise & Start Simulations
   

    IF (ParameterGet("IOSERVER","Name","IOServer") = "IOServer") AND
        (ParameterGet("IOSERVER","Server","") = "1") THEN        !Check if this machine is IO Server
  
           IF LOOP_1_P = 0 AND LOOP_2_P = 0 AND LOOP_3_P = 0 THEN   !Check if PID settings lost
            Loop_5_PV = 1.3;                 !Set Process Varible to 1.3   
            Loop_5_SP = 1.3;                 !Set Setpoint to 1.3
            FOR I = 1 TO 5 DO
                TagWrite("LOOP_"+IntToStr(I)+"_P",0.2,0); !Set loop1 to 5 Gain           
                TagWrite("LOOP_"+IntToStr(I)+"_I",40,0)
            END
        END

        FileCopy(PathToStr("[RUN]:cando.gif"), PathToStr("[DATA]:cando.gif"), 1);     ! This code copies the necessary bitmaps to the DATA directory for the HTML report.
                                                ! where the HTM file is stored.
                                                ! You would not normally need this in a real app as the files
                                                ! would be stored there permanently.
                                                ! File is only copied if the time is different.
   
        SPCParetoStartup();

        IF Loop_5_PV < 1.2 THEN        !In case Disk PLC gets destroyed.   
            Loop_5_PV = 1.5;
            Loop_5_SP = 1.5;
        END

        TaskNew( "PID", "^"LOOP_1^"", 0 );    !Start PID Simulations
        TaskNew( "PID", "^"LOOP_2^"", 0 );
        TaskNew( "PID", "^"LOOP_3^"", 0 );
        TaskNew( "PID", "^"LOOP_4^"", 0 );
        TaskNew( "PID", "^"LOOP_5^"", 0 );
        TaskNew( "WaterTankLevel","", 0 );    !Start WaterTank Simulation
        TaskNew( "Always","",0);

        TaskNew( "PIDSPSim", "^"LOOP_1^"", 0 );

       
        VALVE_512_M = 1;        ! Set Valve 512 to Auto
        Valve_1_CMD = 0;
        Valve_2_CMD = 0;
        Valve_3_CMD = 0;
        Valve_4_CMD = 0;
        Valve_5_CMD = 0;
        PUMP_A_M = 1;
        DiskFilter=1;            ! Turn Filter On
        Stockpile =50;            ! Start Stockpile at 50%
        Oper_Input_Real = 123.45;
        Oper_Input_Integer = 88.8;
        Oper_Input_String = "Citect";

      END

END


//     FUNCTION:        Always
//
//    DESCRIPTION:    This function will run continuosly until Citect is
//            Shutdown


FUNCTION
Always()
    INT     I;
    WHILE TRUE DO
        ReRead(0);            !Re-Read I/O Tags
        Sleep(1);            !Run once per second

        CPU_Usage=CitectInfo("General","General",0);

        FilterPage();
        I=I+1;
        IF I > 4 THEN        !Run StockPile Simulation every 5 Seconds   
            StockPileSim();
            I = 0;
        END
    END
END

//    FUNCTION:    CheckAnsiToOEM
//   
//    DESCRIPTION:    Checks parameter in Citect.ini file. Applies when overwriting
//            an old version of Citect (pre 5.01).
//

FUNCTION
CheckAnsiToOEM()

    IF ParameterGet("CTEDIT","ANSItoOEM"," ") = "1" THEN    !Ensure ANSItoOEM parameter set correctly
        ParameterPut("CTEDIT","ANSItoOEM","0");
        Message("Parameter Incorrect", "Incorrect Parameter Found ^n Correcting and Restarting Citect",48);
        Sleep(2);
        Shutdown("", PathToStr("[RUN]:"), 2);
    END
END




//    FUNCTION:    Temp_Profile_Sim
//   
//    DESCRIPTION:    Simulation for Temperature Profile.

INT     Temp_Profile_Running     = 0;   

FUNCTION
Temp_Profile_Sim()
   
    IF Temp_Profile_Running THEN
        Beep(1);
        Halt();
    END
    Temp_Profile_Running = 1;

    Ramp_Temp_Profile( 6, 100);
    SleepMS(6000);
    Ramp_Temp_Profile( 7, 175);
    SleepMS(6000);
    Ramp_Temp_Profile( 6, 70);   
    SleepMS(5000);
    Ramp_Temp_Profile( 9, 22);
    Temp_Profile_Running = 0;
END

//    FUNCTION:    Ramp_Temp_Profile
//
//    DESCRIPTION:    Ramps Temp_Profile Tag

FUNCTION
Ramp_Temp_Profile( Real rRampTime, INT RampTo=0)
    INT    iStart;
    INT     iTimeExp;
    INT     iRampValue;
    INT     iRampFrom;
   
    iStart = Systime();

    rRampTime=rRampTime *1000;   
    iRampFrom = Temp_Profile;
   
    iTimeExp=(Systime() - iStart);
   
    While rRampTime > iTimeExp DO
        iRampValue=(iTimeExp/ rRampTime) * (RampTo-iRampFrom);
        Temp_Profile = iRampFrom + iRampValue;
        SleepMS(500);
        iTimeExp=(Systime() - iStart);
    END
    Temp_Profile = iRampFrom + iRampValue;
END

//    FUNCTION:    DynamicResetAll
//
//    DESCRIPTION:    Function resets all the variables that are used on
//            the Dynamic_1 page.

FUNCTION
DynamicResetAll()
    H_Fill = 0;
    V_Fill = 100;
    V_Size = 100;
    H_Size = 100;
    H_Movement = 0;
    V_Movement = 0;
    Rotation = 0;
    Hide=0;
    Fill_A=1;
    Fill_B=0;
    Fill_C=0;
END

Name: SCADA 2013-05-13 0:20

Citest Directory :

Continue :

Simulatr.ci

//      ---------------        Recipe Page Simulation        ---------------

//    FUNCTION:    Process
//
//    DESCRIPTION:    This function performs the Simulation for the Recipe
//            Page

FUNCTION
Process()
    INT     Salt;
    INT     Sugar;
    INT     Flour;
    INT     Milk;
    INT     Water;

    Salt  = SaltPLC  * Batch;
    Sugar = SugarPLC * Batch;
    Flour = FlourPLC * Batch;
    Milk  = MilkPLC  * Batch;
    Water = WaterPLC * Batch;

    MIX_RUNNING = TRUE;
       
    WHILE ((Salt> 0) OR (Sugar > 0) OR (Flour > 0) OR (Milk > 0) OR (Water > 0)) DO

        IF (Salt > 0) THEN
            VALVE_1_CMD = TRUE;
            Salt = Salt - 1;
        ELSE
            VALVE_1_CMD = FALSE;
        END
        IF (Sugar > 0) THEN
            VALVE_2_CMD = TRUE;
            Sugar = Sugar - 1;
        ELSE
            VALVE_2_CMD = FALSE;
        END
        IF (Flour > 0) THEN
            VALVE_3_CMD = TRUE;
            Flour = Flour - 50;
        ELSE
            VALVE_3_CMD = FALSE;
        END
        IF (Milk > 0) THEN
            VALVE_4_CMD = TRUE;
            Milk = Milk - 20;
            MILK_LEVEL = MILK_LEVEL - (32000/(MilkPLC*Batch));
        ELSE
            VALVE_4_CMD = FALSE;
        END
        IF (Water > 0) THEN
            VALVE_5_CMD = TRUE;
            Water = Water - 300;
        ELSE
            VALVE_5_CMD = FALSE;
        END

        IF (VALVE_1_CMD OR VALVE_2_CMD OR VALVE_3_CMD) THEN
            PUMP_2_CMD = TRUE;
        ELSE
            PUMP_2_CMD = FALSE;
        END

        Sleep(1);
    END
   
    VALVE_1_CMD = FALSE;
    VALVE_2_CMD = FALSE;
    VALVE_3_CMD = FALSE;
    VALVE_4_CMD = FALSE;
    VALVE_5_CMD = FALSE;

    Pump_1_Cmd = TRUE;
    Sleep(3);
    PUMP_1_CMD  = FALSE;
    PUMP_2_CMD  = FALSE;
    MIX_RUNNING = FALSE;
END

//    FUNCTION:    WaterTankLevel
//
//    DESCRIPTION:    Simulates water tank level

FUNCTION
WaterTankLevel()
    While TRUE DO
        ReRead(0);

        SELECT CASE Water_Level
        CASE Is < 8000
            Water_Tank_Lo_Switch = 1;
        CASE Is > 28000
            Water_Tank_Lo_Switch = 0;
        END SELECT   
        IF Water_Tank_Lo_Switch THEN
            Water_Level = Water_Level + 550;
        END
        IF Valve_5_Cmd = TRUE AND (Water_Level >=600) THEN
            Water_Level = Water_Level -600;
        END
        Sleep(1);
    END
END

//     ---------        PID Loop Simulation    ---------------------------
//   
//    FUNCTION:    PID
//
//     DESCRIPTION:    This PID function is to provide a realistic look and
//            feel and is not intended to be used for control of a
//            process. If you wish to perform PID type control in
//            Citect it is better to use package designed for PID
//            control or alternately write an algorithm written as
//            a DLL.
//
//    AUTHOR:     Steve Schilg
//    VERSION:     3.0
//    DATE:         2 Apr 96
//
//      NOTE:        This function should be called only once for each
//            tag name and should run until Citect Shuts down.
//            Use TaskNew as follows to start this
//            Function: TaskNew( "PID", "^"LOOP_1^"", 0 );
//
//      sTag        = The Loop tagname as a String - do not include
//            the attribute. Tag can be either Real or Integer.
//
//    REVISIONS:     2 Apr 96
//            Replaced DspInfoField() with TagInfo() function as
//            it runs faster.
//            Removed ReReads as these are not necessary with the
//            TagRead function.
//            Used sleepMS(1000) instead of Sleep(1) to provide
//            more precise timing
//            3 Dec 96
//            Modified timing to execute more deterministically

FUNCTION
PID(String sTAG)
   
    REAL     Dev,oDev, rGO,rIO,rDO,rZero,rFull,rOZero,rOFull;
    REAL     rOP,rPV, rSP, rP,rI,rD,rFeedBack;
    INT      iOPM;
    INT      iSleepTime;
    INT      iStart;
       
    rOZero     = TagInfo(sTag+"_OP", 4);         !Get Output Range
    rOFull     = TagInfo(sTag+"_OP", 5);   
    rZero    = TagInfo(sTag+"_PV", 4);        !Get PV Range
    rFull    = TagInfo(sTag+"_PV", 5);
    rFeedback    =16000;                    !Initialise Feedback value
       
    WHILE TRUE DO
        iStart = SysTime();                !Must Execute once per second for Integral Action to be
                                !correct
        iOPM    =TagRead(sTag+"_OPM",0);        !Read Output Mode
        IF iOPM = 0 THEN                !If in Manual
            rOP=TagRead(sTag+"_OP",0);        !Read Output Value
            rFeedBack = EngToGeneric(rOP,rOZero,rOFull);    !Set FeedBack = Output   
        ELSE                   
            rPV=TagRead(sTag+"_PV", 0);        !Read PV
            rSP=TagRead(sTag+"_SP", 0);        !Read SP
                       
            rPV=EngToGeneric(rPV,rZero,rFull);    !Convert PV to Generic
            rSP=EngToGeneric(rSP,rZero,rFull);    !Convert SP to Generic
   
            rP=TagRead(sTag+"_P", 0);        !Read the Gain Constant
            rI=TagRead(sTag+"_I", 0);        !Read the Integral Constant
            rD=TagRead(sTag+"_D", 0);        !Read the Derivitive Constant

            Dev = rSP-rPV ;                !Calc Deviation
            rGO = rP * Dev;                !Calc Gain Output
            rIO = rI/60 * rGO;            !Calc Integral Output
            rDO = rD * (Dev-oDev) * 60 ;        !Calc Derivitive Output
            rOP = rFeedBack + rGO + rIO+rDO;    !Total Output       
            rFeedBack=rFeedBack+rIO;        !Remember Feedback
            oDev=Dev;                !Remember deviation

            IF rOP = 0 then                !Prevent Divide by Zero
                rOP= rOZero;           
            ELSE
                rOP= (rOP/32000.00) * (rOFull-rOZero) + rOZero;   !Scale for Output
            END   
       
            IF rOP > rOFull THEN            !Output high limit
                rOP = rOFull;   
            END

            IF rOP < rOZero THEN            !Output Low limit
                rOP = rOZero;
            END
       
            TagWrite(sTag + "_OP",RealToStr(rOP,8,3) , 0);    !Write to Ouput
        END
        ProcSim(sTag,rOP,rOZero,rOFull,rZero,rFull);   
        iSleepTime  = 1000 - SysTimeDelta( iStart);
        IF iSleepTime < 1 THEN                 !Prevent negative sleep time!
            iSleepTime =1;
        END
        SleepMS( iSleepTime);
    END
END


//     FUNCTION:     PIDSim
//
//    DESCRIPTION:    This function is designed to run continuously as a
//                background Cicode task to simulate a PID SP change

FUNCTION
PIDSPSim(String sTag)

    REAL    rZero, rFull, rSP;


    IF (ParameterGet("DEBUG", "PIDSPSim", "0") <> "1") THEN RETURN; END

    rZero    = TagInfo(sTag+"_PV", 4);        !Get PV Range
    rFull    = TagInfo(sTag+"_PV", 5);

    WHILE TRUE DO
        rSP=TagRead(sTag+"_SP", 0);        !Read SP

        if (rSP > (((rFull-rZero)/2) + rZero)) then
            rSP = ((rFull-rZero)*0.25) + rZero;
        else
            rSP = ((rFull-rZero)*0.8) + rZero;
        end

        TagWrite(sTag+"_SP", RealToStr(rSP,8,3) , 0);    !Write SP

        sleep(300);
    END
END

Name: SCADA 2013-05-13 0:23

Citest Directory :

Continue :

Simulatr.ci

//     FUNCTION:     ProcSim
//
//    DESCRIPTION:    This function is designed to run continuously as a
//                background Cicode task to simulate a Process

FUNCTION
ProcSim(String sTag, Real rOP, Real rOZero, Real rOFull, Real rZero, Real rFull)

    REAL    rPV;
    INT    iPV;
    INT    iOP;
    INT    iLag = 20;

    rPV = TagRead(sTag+"_PV", 0);                ! Read PV
    iPV = EngToGeneric(rPV,rZero,rFull);            ! Convert PV to Generic
   
    iOP = EngToGeneric(rOP,rOZero,rOFull);

    rPV = rPV + (iOP - iPV)*(rFull - rZero)/32000/iLag;

    TagWrite(sTag + "_PV",RealtoStr(rPV,8,3) , 0);    ! Write to PV
   
END

//    ------------    Filter Page Simulations     -------------------
//
//    FUNCTION:    FilterPage   
//
//    DESCRIPTION:    These functions provide Simulation for the Filter
//            page.

FUNCTION
FilterPage()
   
    IF ((VALVE_512_CMD=1) AND (PUMP_A_CMD=1)) THEN    !Level Simulation
        IF FILTER_TANK_LEV > 0 THEN   
            FILTER_TANK_LEV = FILTER_TANK_LEV - 1;
        END
    ELSE
        IF FILTER_TANK_LEV < 100 THEN
            FILTER_TANK_LEV = FILTER_TANK_LEV + 1;
        END
    END

    IF VALVE_512_M = 1 THEN        !If in Auto            ! Auto Valve Control
   
        IF FILTER_TANK_LEV > 95 THEN
            VALVE_512_CMD = 1;
        END
        IF FILTER_TANK_LEV < 5 THEN
            VALVE_512_CMD = 0;
        END
    END

    IF PUMP_A_M = 1 THEN                        ! Auto Pump Control
        IF FILTER_TANK_LEV > 95 THEN
            PUMP_A_CMD=1;
        END
        IF FILTER_TANK_LEV < 5 THEN
            PUMP_A_CMD = 0;
        END
    END
END

//     -----------     Filter Page StockPile Simulation --------------

FUNCTION
StockPileSim()
    IF DiskFilter THEN
        STOCKPILE=STOCKPILE + 2;           
        IF STOCKPILE = 100 THEN
            STOCKPILE=0;
        END   
    END
END

//     ---------         Pareto Chart Simulation     ----------

//    FUNCTION:    SPCParetoStartup
//    DESCRIPTION:    Spawns threads to handle SPC tags simulation
   
FUNCTION
SPCParetoStartup()
    !Tag waveform period min max offset

    TagSimulate( "TT001", "RANDOM", 10, 5, 79, 0);
    TagSimulate( "TT002", "SINE", 120, 10, 30, 0);
    TagSimulate( "TT003", "SQUARE", 45, 40, 59, 0);
    TagSimulate( "TT004", "SAW", 78, 5, 100, 0);
    TagSimulate( "TT005", "RANDOM", 36, 80, 99, 0);
    TagSimulate( "TT006", "RANDOM", 58, 10, 80, 0);
    TagSimulate( "TT007", "SINE", 10, 5, 79, 0);
    TagSimulate( "TT008", "TRIANG", 30, 20, 68, 0);
    TagSimulate( "TT009", "SINE", 25, 5, 79, 0);
    TagSimulate( "TT010", "TRIANG", 30, 20, 68, 0);
END


//    FUNCTION:    TagSimulate
//
//    DESCRIPTION:    Spawns a task that runs forever which will generate
//            data for a tag based on the waveform specified. This
//            function also prechecks for data type and range
//            checkng.
//       
//    REV    DATE        WHO        DESCRIP
//    1.0    23/3/96    A.Winter    Original
//
//    CALLED BY:    Kernel or TagSimulateForm()
//
//    ARGUMENTS:
//        STRING    sTag     The variable tag to simulate
//        STRING    sWaveForm   On of the cicode waveforms "SQUARE", "RANDOM", "SINE", "TRIANG", "SAW"
//        INT    iPeriod    The period of the waveform cycle in seconds
//        REAL    rMin    The minimum of the generated data required
//        REAL    rMax    The maximum of the generated data required
//        INT    iOffset    Offsets the start of the waveform cycle
//
//    RETURNED VALUE:
//        The handle to the task if spawned OK else -1
//
//    NOTES:


INT
FUNCTION
TagSimulate( STRING sTag, STRING sWaveForm, INT iPeriod = 60, REAL rMin = 0, REAL rMax = 100, INT iOffset = 0)
    INT    hSimTask    = -1;
    INT    iRangeOK    = FALSE;
    STRING    sType        = "";

    ErrSet( 1);
    TagRead( sTag);
    ErrSet( 0);
    IF IsError() = 0 THEN        !Check it exists
        sType = DspInfoField( 0, sTag, "TYPE")
        IF sType = "DIGITAL" THEN
            rMin = 0;
            rMax = 1;
            sWaveForm = "SQUARE";
            iRangeOK  = TRUE;
        END
        IF sType <> "STRING" AND sType <> "DIGITAL" AND
            StrToReal( TagInfo( sTag, 4)) <= rMin AND StrToReal( TagInfo( sTag, 5)) >= rMax THEN
            iRangeOK  = TRUE;
        END
        IF iRangeOK THEN
            hSimTask = TaskNew( "_TagSimulateTask", "^""+sTag +"^",^""+ sWaveForm +"^","+
                   iPeriod:### +","+ rMin:#####.## +","+ rMax:####.## +","+ iOffset:###, 0);
            IF hSimTask = -1 THEN
                ErrLog( " TagSimulate: Error task failed for tag:"+sTag);
            END
        ELSE
            ErrLog( " TagSimulate: Error simulate range:"+ rMin:# +" - "+ rMax:# +" beyond tag:"+sTag+" engineering range");
        END

    ELSE
        ErrLog( " TagSimulate: Error tag:"+ sTag +" does not exist");
    END
    RETURN( hSimTask);
END


//
//    FUNCTION NAME:    _TagSimulateTask
//
//    FUNCTION DESCRIPTION:
//        The task spawned from TagSimulate function.
//
//    REV    DATE        WHO        DESCRIP
//    1.0    23/3/96    A.Winter    Original
//    1.1 18/2/97    S.Schilg    rewrote using SELECT CASE
//
//    CALLED BY:
//        TagSimulate()
//
//    ARGUMENTS:
//        STRING    sTag        The variable tag to simulate
//        STRING    sWaveForm   On of the cicode waveforms "SQUARE", "RANDOM", "SINE", "TRIANG", "SAW"
//        INT        iPeriod    The period of the waveform cycle in seconds
//        REAL        rMin        The minimum of the generated data required
//        REAL        rMax        The maximum of the generated data required
//        INT        iOffset    Offsets the start of the waveform cycle
//
//    RETURNED VALUE:
//
//    NOTES:
//
//

FUNCTION
_TagSimulateTask( STRING sTag, STRING sWaveForm, INT iPeriod = 60, REAL rMin = 0, REAL rMax = 100, INT iOffset = 0)

    SELECT CASE StrUpper( sWaveForm)
    CASE "SQUARE"
        WHILE TRUE DO
            Sleep( 1);
            ReRead( 0);
            TagWrite( sTag, TestSquareWave( iPeriod, rMin, rMax, iOffset));
        END
    CASE "SINE"
        WHILE TRUE DO
            Sleep( 1);
            ReRead( 0);
            TagWrite( sTag, TestSinWave( iPeriod, rMin, rMax, iOffset));
        END
    CASE "RANDOM"
        WHILE TRUE DO
            Sleep( 1);
            ReRead( 0);
            TagWrite( sTag, TestRandomWave( iPeriod, rMin, rMax, iOffset));
        END
    CASE "SAW"
        WHILE TRUE DO
            Sleep( 1);
            ReRead( 0);
            TagWrite( sTag, TestSawWave( iPeriod, rMin, rMax, iOffset));
        END
    CASE "TRIANG"
        WHILE TRUE DO
            Sleep( 1);
            ReRead( 0);
            TagWrite( sTag, TestTriangWave( iPeriod, rMin, rMax, iOffset));
        END
    END SELECT
END

Name: SCADA 2013-05-13 0:27

Citest Directory :

TRENDARC.CI

//
//    FILE:    TrendArc.ci
//
//    AUTHOR:    Tom Purcell
//
//    DATE:    December 1993
//
//    REVISION:
//
//    3.00    February 1994.
//
//    4.00    September 1996
//            Added ServerInfo() to get name of current INI file
//            Added Version() to check to see whether to run ctbackup.exe or ctback32.exe
//            Removed Version() to check to see whether to run ctbackup.exe or ctback32.exe
//
//    5.00    November 1998.  Graeme Sutton.
//            Modified to use new CtBack32.exe in v5.10r0, this version is
//            not compatable with earlier versions of Citect.
//            ArchivePath parameter now also accepts any backup
//            file names ending in .CTZ or .ZIP -
//                eg.  C:\Citect\Archive\TestArc.ctz
//            Modified _RemoveHistoryFiles() function to correctly delete files.
//
//    NOTES:    This file contains functions for archiving and restoring trend history.
//


INT    hDev1;        !handle for Trend tags database
INT    hDev2;        !handle for selected Trend tags database
INT    hFormb;        !handle for backup form
INT    hFormc;        !handle for configure form
INT    hField1;    !handle for trend selection combo box
INT    hField2;    !handle for selected trends list box
STRING    sSelect1;    !output buffer for combo box
STRING    sSelect2;    !output buffer for list box
STRING    BackupPath;    !files copied here before archive
STRING    RestorePath;    !files restored here from archive
STRING    ArchivePath;    !Trend archive stored here
STRING    CtBackupPath;    !used to call CtBackup.exe
STRING    Operation;    !Selects between 0=backup and 1=restore
STRING    sCitectINI;    !Name of the Citect.INI file being used
STRING    OperationSave;    !Selects between 0=backup and 1=restore
STRING    FilePathSave;    !Stores the name of the CtBackup archive file for restoration
STRING    ArchivePathSave;!Stores the name of the CtBackup arcihve path for restoration


//    FUNCTION        TrendArchive
//
//    Syntax
//    TrendArchive(Mode)
//    eg TrendArchive() for default or TrendArchive(0) Do not display the configure
//    button.  mode 1 display the configure button.
//    mode 1 is the default, if using mode 1 then the [Trend]BackupPath=,
//    [Trend]RestorePath= and [Trend]ArchivePath= parameters must be set
//    in the Citect.INI file.
//
//    This function allows backup or restore of trend archives, it displays
//    a form with five buttons, "Backup Selected Trends", "Backup All System Trends"
//    "Restore", "Configure", "Cancel".
//
//    To use this function, two devices must be configured in your database
//    the devices should be configured as follows.
//
//    1. Name : TrendTags, Path : [RUN]:TREND.DBF, Type : dBASE_DEV
//    2. Name : TrendBackup, Format : {NAME,16}{FILENAME,64}
//    Path : [RUN]:TrendBK.DBF, Type : dBASE_DEV
//
//    You must also create two directories, a backup directory to which the
//    files will be copies before been backed up eg C:\CITECT\BACKUP\ and a
//    restore directory to which the files will be restored to before been
//    attached to the trend system eg C:\CITECT\RESTORE\ The path to these
//    directories must be specified when you first call the function, this
//    is done through the configure button on the main form. Also note that
//    these directories should be for the exclusive use of the Trend Archive
//    system and you should not specify the directory that contains your live
//    trend history files!.
//
//    CAUTION !! Any files in the restore directory or any sub directories of
//    the restore directory will be deleted by the restore function!
//


PUBLIC
FUNCTION
TrendArchive(INT mode = 1)
   
    hDev1 = Devopen("TrendTags", 0);
    hDev2 = DevOpen("TrendBackup", 0);
    FormNew("Trend Archive System", 32, 5, 4);
    FormButton(0, 0, "     Backup Selected Trends    ", _BackupForm, 0);
    FormButton(0, 2, "    Backup All System Trends   ", _BackupTrends1, 0);
    FormButton(0, 4, " Restore ", _RestoreForm, 0);
    IF mode = 1 THEN
        FormButton(11, 4, "Configure", _ConfigureForm, 0);
    END
    FormButton(22, 4, " Cancel  ", 0, 2);
    _CtBackupEnvSave();
    FormRead(0);
    DevClose(hDev1);
    DevClose(hDev2);
END


//    FUNCTION:        _BackupForm
//
//    This function gives a list of all configured trends on the system
//    and allows the trends to be selected or deselected for archival,
//    the selected tag names are stored in a dBase device "TrendTags".

PRIVATE
INT
FUNCTION
_BackupForm()
   
    sSelect2 = "";
    DevSeek(hDev1, 1);
    DevSeek(hDev2, 1);
    hFormb = FormNew("Trend Backup", 38, 11, 0);
    hField1 = FormComboBox(1, 1, 16, 8, sSelect1);
    WHILE NOT DevEof(hDev1) DO
        FormAddList(DevGetField(hdev1, "NAME"));
        DevNext(hDev1);
    END
    hField2 = FormListBox(20, 1, 16, 8, sSelect2);
    WHILE NOT DevEof(hDev2) DO
        FormAddList(DevGetField(hdev2, "NAME"));
        DevNext(hDev2);
    END
    FormPrompt(3, 0, "All Trends");
    FormPrompt(20,0, "Selected Trends");
    FormButton(1, 10, " Add ", _AddNewTrend, 0);
    FormButton(8, 10, " Remove ", _RemoveTrend, 0);
    FormButton(18, 10, " Backup ", _BackupTrends0, 0);
    FormButton(28, 10, " Cancel ", 0, 2);
    FormRead(0);
    RETURN 0;
END


//    FUNCTION:        _AddNewTrend
//
//    This function is called from the Backup form, it searches the Trend
//    database for the trend which has selected from the Combo box and
//    when it finds it, it gets its name and path and adds these to the
//    dBase device "TrendTags" for use by the _BackupTrends() function,
//
//

PRIVATE
INT
FUNCTION
_AddNewTrend()
    STRING    sName = "";
    STRING    sFile = "";
   
    FormGetData(hFormb);
    DevSeek(hDev1, 1);
    IF NOT DevFind(hDev1, sSelect1, "NAME") THEN
        sName = DevGetField(hDev1, "NAME");
        sFile = DevGetField(hDev1, "FILENAME");
        IF NOT DevAppend(hDev2)    THEN
            DevSetField(hDev2, "NAME", sName);
            DevSetField(hDev2, "FILENAME", sFile);
            FormSetText(hFormb, hField2, sName);
        END
    ELSE
        DspError("Cannot Find " + sSelect1);
    END
    RETURN 0;
END


//    FUNCTION:        _RemoveTrend
//
//    This function is used to remove trends from the selection list box
//    on the backup form, the trend name will also be removed from the
//    dBase device "TrendTags", the device is then packed.

PRIVATE
INT
FUNCTION
_RemoveTrend()
    STRING    sFile;

    FormGetData(hformb);
    DevSeek(hDev2, 1);
    IF NOT DevFind(hDev2, sSelect2, "NAME") THEN
        DevDelete(hDev2);
    ELSE
        DspError("Cannot Find " + sSelect2);
        RETURN 0;
    END
    DevControl(hDev2, 1, "");
    FormDestroy(hFormb);
    _BackupForm();
    RETURN 0;
END

//    FUNCTION:        _BackupTrends
//
//    This function copies all the files listed in the dBase device
//    "TrendBackup" to the "[Trend] BackupPath" directory and then calls
//    CtBackup.exe to do a compressed backup of the files into the archive
//    directory "[Trend] ArchivePath=", both of these directories can be
//    set using the "Configure" form.
//    If you pass a 1 to this function it will read the "TrendTags" device
//    instead of the "TrendBackup" device, this will cause it to archive all
//    trends on the system not just the selected ones.


INT
FUNCTION
_BackupTrends(INT DevSelect = 0)
    INT    error;
    INT     hForm;
    STRING    TrendPath;
    INT    hDevGeneric;
    STRING    TempPath;
   
    IF Devselect = 1 THEN
        hDevGeneric = hDev1;
    ELSE
        hDevGeneric = hDev2;
    END
       
    // This check is to ensure that the path is legal and prevent your drive from been zapped //
    IF _CheckBackupPath() THEN
        ErrSet(1);
        hForm = FormNew("Please Wait !", 26, 1, 0);
        FormPrompt(6, 0, "Copying Files");
        FormRead(1);
        FileDelete(BackupPath + "*.*");
        DevSeek(hDevGeneric, 1);
        WHILE NOT DevEof(hDevGeneric) DO
            TrendPath = DevGetField(hDevGeneric, "FILENAME");
            !The following is so that if the trend path field is blank it will use the default //
            IF TrendPath = "" THEN
                TrendPath = "[Data]:" + StrLeft(DevGetField(hDevGeneric, "Name"),8);
            END
            error = FileCopy(TrendPath + ".*", BackupPath, 0);
            IF error > 0 THEN
                Message("Error Copying Files", "Cicode Error " + IntToStr(error) + "^n Does " + BackupPath + " Exist", 48);
                FormDestroy(hForm);
                RETURN 0;
            END
            DevNext(hDevGeneric);
        END
        FormDestroy(hForm);
        Operation = 0;
        _CtBackupEnvSet();
        error = Exec(CtBackupPath + " -a" + " -xhst" + " -i" + sCitectINI, 1);
        _CtBackupEnvReset();
        IF error > 0 THEN
            Message("Error", "Cannot Run " + CtBackupPath, 48);
        END
        ErrSet(0);
    END
    RETURN 0;
END

//    FUNCTION:        _BackupTrends1()
//               
//    DESCRIPTION:    This function is a stub which is used to pass a "1"
//                to the _BackupTrends()function as this cannot be done
//                from FormButton()in TrendArchive()
//                The function is called from TrendArchive()

PRIVATE
INT
FUNCTION
_BackupTrends1()
    _BackupTrends(1);
    RETURN 0;
END


//    FUNCTION:        _BackupTrends0()
//
//    This function is a stub which is used to pass a "0" to the _BackupTrends()
//    function as this cannot be done from FormButton() in _BackupForm()
//    The function is called from _BackupForm

PRIVATE
INT
FUNCTION
_BackupTrends0()

    _BackupTrends(0);
    RETURN 0;
END

Name: SCADA 2013-05-13 0:30

Citest Directory :

Continue :

TRENDARC.CI


//    FUNCTION:        _RestoreForm
//
//    This function is for restoring trend archives, it displays three
//    buttons, "Restore from Backup", "Add Files to System" and "Cancel".

PRIVATE
INT
FUNCTION
_RestoreForm()

    FormNew("Restore Trend Archives", 29, 7, 4);
    FormButton(0, 0, "    Restore From Archive    ", _RestoreFiles, 0);
    FormButton(0, 2, "   Attach Files to System   ", _AddHistoryFiles, 0);
    FormButton(0, 4, "  Remove Files from System  ", _RemoveHistoryFiles, 0);
    FormButton(0, 6, "           Cancel           ", 0, 2);
    FormRead(0);
    RETURN 0;
END

//    FUNCTION    _RestoreFiles
//
//    This function restores trend archives to a reserved directory so
//    that they can be added the the Trend system, this directory will be
//    set by the Configure dialogue and stored in the Citect.INI as
//    "[Trend] RestorePath="

PRIVATE
INT
FUNCTION
_RestoreFiles()

    IF _CheckRestorePath() THEN
        Operation = 1;
        _CtBackupEnvSet();
        Exec(CtBackupPath + " -a" + " -xhst" + " -i" + sCitectINI, 1);
        !IF FileExist(RestorePath + "project.cit") THEN
        !    FileDelete(RestorePath + "project.cit");
        !END
        _CtBackupEnvReset();
    END
    RETURN 0;
END

//    FUNCTION:        _AddHistoryFiles
//
//    This function adds the files to the trend system using TrnAddHistory()
//    these files must first be restored from archive with the
//    "Restore From Archive" button
//

INT
FUNCTION
_AddHistoryFiles()
    STRING     sPath;
    STRING     buffer;
    INT     hform;
    INT     hField;
   
    hForm = FormNew("Please Wait !", 36, 2, 0);
    sPath = FileFind(RestorePath + "*.*", 0);
    FormPrompt(6, 0, "Adding Trends To System");
    hField = FormField(1, 1, 32, 1, 3, buffer, sPath, 0);
    FormRead(1);
    WHILE StrLength(sPath) > 0 DO
        TrnAddHistory(sPath);
        sPath = FileFind("", 0);
        FormSetText(hForm, hField, sPath);
    END
    FormDestroy(hForm);
    RETURN 0;
END


//    FUNCTION:        _RemoveHistoryFiles
//
//    This function removes the files that were added using _AddHistoryFiles
//    function. It also deletes the files from the restore directory.

PRIVATE
INT
FUNCTION
_RemoveHistoryFiles()
    INT     hForm;
    INT    hField
    STRING    buffer;
    STRING    sPath;
   
    hForm = FormNew("Please Wait !", 36, 2, 0);
    FormPrompt(6, 0, "Removing Trends From System");
    _RemoveFiles(RestorePath + "*.*");
    FormDestroy(hForm);
    RETURN 0;
END


//    FUNCTION:        _RemoveFiles
//
//    This is necessary beacuse calling FileFind("", 0) in the same loop
//    as calling FileDelete() will not work.  Calling it recursively finds
//    all file first then deletes the files.


PRIVATE
FUNCTION
_RemoveFiles(STRING sDirName)

    INT    hField;
    STRING    sPath;

    sPath = FileFind(sDirName, 0);
    IF sPath <> "" THEN
        _RemoveFiles("");        // Call recursively
        TrnDelHistory(sPath);
        FileDelete(sPath);
    END
END


//    FUNCTION:        _ConfigureForm
//
//    This function displays a dialogue box which allows three directory
//    paths to be set, "BackupPath" : this is where the trend files get
//    copied before they get archived, "RestorePath" : this is where the
//    files get restored to from archive before getting linked into the
//    the trend system, "ArchivePath" : this directory is where the
//    compressed archives of the selected files are created. Optionally
//    any file name ending in .CTZ or .ZIP can also be specified as part
//    of the ArchivePath.

PRIVATE
INT
FUNCTION
_ConfigureForm()

    hFormc = FormNew("Configure Trend Archive", 47, 8, 0);
    FormGroupBox(0, 0, 47, 5);
    FormPrompt(1, 1, "Backup Path");
    FormPrompt(1, 2, "Restore Path");
    FormPrompt(1, 5, "Archive Path");
    FormEdit(14, 1, BackupPath, 32);
    FormEdit(14, 2, RestorePath, 32);
    FormEdit(14, 5, ArchivePath, 32);
    FormButton(15, 7, "   OK   ", _ConfigSave, 1);
    FormButton(25, 7, " Cancel ", 0, 2);
    FormRead(0);
    RETURN 0;
END


//    FUNCTION:        _ConfigSave
//
//    This function is called from the "OK" button on the Config form and
//    it saves the configuration to the Citect.INI file.

PRIVATE
INT
FUNCTION
_ConfigSave()

    INT    Length1;
    INT    Length2;
   
    FormGetData(hFormc);
    SleepMS(500);        /* this is required to allow time for _ConfigureForm
                 to write to its variables when it closes, other wise
                 it will clobber the new values when it closes */
    _UpdatePath();
    ParameterPut("Trend", "BackupPath", BackupPath);
    ParameterPut("Trend", "RestorePath", RestorePath);
    ParameterPut("Trend", "ArchivePath", ArchivePath);
    RETURN 0;
END

//    FUNCTION:        _UpDatePath
//
//    This function is called from the TrendArchive function and from the _ConfigSave function,
//    it gets the parameter data from the Citect.INI file. The Sleep(1) in the _ConfigSave
//    function will ensure that _ConfigureForm has closed and written to its variables before this
//    function is called.

PRIVATE
INT
FUNCTION
_UpdatePath()

    // This checks to ensure that the path has a "/" on the end //
    IF StrRight(BackupPath, 1) <> "\" THEN
        BackupPath = BackupPath + "\";
    END
    IF StrRight(RestorePath, 1) <> "\" THEN
        RestorePath = RestorePath + "\";
    END

    CtBackupPath = ParameterGet("CtEdit", "Bin", "") + "\CtBack32.exe";

    IF StrRight(ArchivePath, 4) <> ".CTZ" AND StrRight(ArchivePath, 4) <> ".ZIP" THEN
        IF StrRight(ArchivePath, 1) = "\" THEN
            ArchivePath = ArchivePath + "CtBackup.ctz";
        ELSE
            ArchivePath = ArchivePath + "\CtBackup.ctz";
        END
    END

    // This check is to ensure that the path is legal and prevent your drive from getting zapped //
    _CheckRestorePath();
    _CheckBackupPath();
      RETURN 0;
END

//    FUNCTION:        _CheckRestorePath()
//
//    This function is checks the path which is configured by the user, without this check it is
//    possible that CtBackup.exe would wipe out then entire contents of the harddrive.

INT
FUNCTION
_CheckRestorePath()

    IF RestorePath = "C:\" OR RestorePath = "C:" OR RestorePath = "\" OR RestorePath = ""
       OR RestorePath = "C:\CITECT\BIN\" OR RestorePath = "C:\CITECT\USER\" THEN
        Message("Illegal Restore Path " + RestorePath, "Please Select Configure", 48);
        RETURN 0;
    ELSE
        RETURN 1;
    END
END

//    FUNCTION:        _CheckBackupPath()
//
//    This function is checks the path which is configured by the user, without this check it is
//    possible that CtBackup.exe would wipe out then entire contents of the harddrive.

PRIVATE
INT
FUNCTION
_CheckBackupPath()

    IF BackupPath = "C:\" OR BackupPath = "C:" OR BackupPath = "\" OR BackupPath = ""
       OR BackupPath = "C:\CITECT\BIN\" OR BackupPath = "C:\CITECT\USER\" THEN
        Message("Illegal Backup Path " + BackupPath, "Please Select Configure", 48);
        RETURN 0;
    ELSE
        RETURN 1;
    END
END

//    FUNCTION:        _CtBackupEnvSet()
//
//    This Function is used to set the Citect.ini backup parameters to suitable
//    values for restore or backup operations.

PRIVATE
FUNCTION
_CtBackupEnvSet()

    ParameterPut("Backup", "BackupPath", ArchivePath);
    IF Operation = "0" THEN
        ParameterPut("Backup", "Operation", "0");
        ParameterPut("Backup", "FilePath", BackupPath);
    ELSE
        ParameterPut("Backup", "Operation", "1");
        ParameterPut("Backup", "FilePath", RestorePath);
    END
END


//    FUNCTION:        _CtBackupEnvSave()
//
//    This Function is used to backup the Enviroment parameters for CtBackup.exe
//    to be restored later and to initialise all parameters to be used.


PRIVATE
FUNCTION
_CtBackupEnvSave()
    OperationSave = ParameterGet("Backup", "Operation", "");
    FilePathSave = ParameterGet("Backup", "FilePath", "");
    ArchivePathSave = ParameterGet("Backup", "BackupPath", "");

    BackupPath = ParameterGet("Trend", "BackupPath", "");
    RestorePath = ParameterGet("Trend", "RestorePath", "");
    ArchivePath = ParameterGet("Trend", "ArchivePath", "");
    CtBackupPath = ParameterGet("CtEdit", "Bin", "") + "\CtBack32.exe";
    sCitectINI = ServerInfo("Client", 3);    !Get the name of the INI file beig used.

END


//    FUNCTION:        _CtBackupEnvReset()
//
//    This Function is used to reset the Enviroment parameters for CtBackup.exe.
//    The parameters will be reset to what they were before the TrendArchive()
//    function was called.

PRIVATE
FUNCTION
_CtBackupEnvReset()
    ParameterPut("Backup", "Operation", OperationSave);
    ParameterPut("Backup", "FilePath", FilePathSave);
    ParameterPut("Backup", "BackupPath", ArchivePathSave);
END

Name: Anonymous 2013-05-13 7:39

UVB-76, UVB-76, 93, 882, NAIMINA, 74, 14, 35, 74, 9, 3, 8, 8, 2, Nikolai, Anna, Ivan, Mikhail, Ivan, Nikolai, Anna, 7, 4, 1, 4, 3, 5, 7, 4.

Don't change these.
Name: Email:
Entire Thread Thread List