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:
Anonymous2013-04-12 7:19
stop making up words
Name:
Anonymous2013-04-12 12:48
What is this "click" of which you speak?
Name:
SCADA2013-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 :
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:
Anonymous2013-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:
Anonymous2013-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:
Anonymous2013-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:
Anonymous2013-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:
Anonymous2013-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:
Anonymous2013-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:
Anonymous2013-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:
Anonymous2013-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:
Anonymous2013-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:
Anonymous2013-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:
Anonymous2013-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:
Anonymous2013-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:
Anonymous2013-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:
SCADA2013-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
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:
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:
Anonymous2013-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:
Anonymous2013-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:
Anonymous2013-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:
SCADA2013-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).
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.
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:
SCADA2013-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
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:
Anonymous2013-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:
Anonymous2013-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:
Anonymous2013-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:
SCADA2013-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
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();
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
//
// 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
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);
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
// 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
// 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
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;
// 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:
SCADA2013-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;
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:
SCADA2013-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: 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
// 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.
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
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:
SCADA2013-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
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;
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
// 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
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
// 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:
SCADA2013-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!
//
// 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:
SCADA2013-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;
// 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.
// 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
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.
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