The following document will help you in development of your client/server process. It will help you with some important programming concepts which you should keep in mind while developing your client/server process.
Before we get into the details, lets examine what exactly a client/server process is and the advantage of using a client/server architecture. Lets assume a simple case in which you have a tank. There is some hardware, such as a sensor. in the tank that detects the tank level. You want multiple stations in your company to have access to the tank level. Instead of having each station communicate with the sensor, you can have one server computer communicating with the sensor and all of the station computers (clients) connected to that server. This way you do not have to deal with hardware/software communication issues with each client computer, but only with the server computer.
It is important to make certain distinctions between client and server processes as you design and develop your Lookout HMI.
The server should primarily perform the following functions:
- Communicate with hardware
- Execute the control loops and process control logic
- Log data to Citadel
The client is primarily the user interface. Client applications can move from computer to computer, and therefore must have no direct dependencies in order to run. Most likely you will have multiple clients in your application. You can use the same client process for all client machines.
Follow these programming rules:
Note The text includes several pictures. To make the pictures more readable all Direct connections are inside of a yellow box, while URL remote connection inside of a green box. Also watch for the direction of the arrows to get better understanding of the topic.
1. Never make any connections from server process to the client process.
This is a very common mistake that developers make. For example, assume you have a Modbus object (Mod1) in the server process and a Switch (Switch1) in the client process. Now suppose you make the following connection on the server:
Mod1.1 = \\Client1\ClientProcess\Switch1.value.
This connection is not advisable for the following reasons:
- The above connection prevents you from connecting multiple switches to Mod1.1, which defeats the purpose of having multiple clients connecting to a server. Only Switch1 in Client1 will be able to connect Mod1.1 in the server
- Usually when you have a client/server system, you are going to be running the server all the time (because it is connected to the hardware) and will periodically stop the client. If you use the connection shown above, the Mod1 object in the server process is going to continuously look for the ClientProcess, and therefore stopping ClientProcess causes problems and makes the server process busy.
The correct design makes a URL connection from Switch1 in the client process to Mod1.1 in the server process.
Another advantage of making a URL connection is that it is a read/write connection. Suppose you have made URL connections from multiple switches to Mod1.1. If you change the position of any one of the switches, the positions of all the other switches will automatically change because you used URL connections.
Note that in the above example we connected directly to the Mod1.1 register. This is possible for data members that are both read and write (remember, a URL remote connection is a read/write connection). If you launch the server process and no client is running, there is no process that is using (is connected to) the Mod1.1 data member. If there is no connection, there is no need for polling that data member. Any driver object is only going to poll connected points. As soon as you launch a client, the client connects to the data member and the Modbus driver will start polling it. In order to include the data member to its poll schedule it the driver has to reconfigure itself.
The same happens if you stop the last running client. The reconfiguration always triggers a new poll. For certain applications, such as a dial-up connection, a specific accurate poll rate is necessary and reconfiguration will add unwanted polls. To make your communication independent from clients, you have to make a permanent connection in the server process. The easiest way is to drag and drop the data member onto a panel. Lookout has to keep the display updated, so it keeps polling the data member. Also all items logged to the Citadel database (right-click the object in Object Explorer, select Edit Database, and check Log to Historical database checkbox) are automatically connected.
A more complicated, but beneficial way to make your server process independent from the client processes is to use a control object (Pot, Switch, PushButton, RadioButton or TextEntry) in the server process that is has a remote connection to the I/O item. Then the clients do not connect to the driver directly, but connect to the object instead. Refer to the example below: the switch in the server process makes permanent subscription to the I/O point and also allows the device control from the server panel. This practice contradicts the rule that the user interface is the client process, but it is usually beneficial in troubleshooting or alarm situations.
In the case of write-only items (FieldPoint.CI data members) the connection the client process control object (Pot, Switch etc) has a remote connection to a server process control object, as described above. However, the server process control object is in Local mode and there is a direct connection between the object and the driver write-only item: Mod1.1 = S_Switch1.
Note The read/write permission is considered from the Lookout point of view, not the device point of view. For example, a device output that can only be written to can be represented by read/write data member, so the value can also be read. Refer to the object reference information in the Lookout Help to find out the data member permission.
In the case of read-only items, using a control object does not make much sense, because control object are used to control, while read-only items can only be displayed or used in an expression. Use the read-only items whenever possible in the server process and in the client process, as shown in the following figure.
2. Avoid using control loops and process control logic in the client process.
This is another common mistake that can have drastic results. Consider the following example that implements multiplexing between two Pot objects. You have a Modbus object (Mod1) in the server process. In the client process you have a switch (Switch1) and two Pots (Pot1, Pot2). The switch selects between Pot1 and Pot2. If Switch1 is ON then you want Mod1.40001 to have the value of Pot1 else you want it to have the value of Pot2.
To achieve this, obey the first rule (URL remote connection), and add another Pot object (Pot3) in the client process and make a remote connection to connect it to Mod1.1, as shown in the following figure. Right-click the Pot3 object in the Object Explorer and select Edit Connections, and enter the expression Pot3.value = IF(Switch1, Pot1, Pot2).
In the above example you are not making any connections from the server to the client, so you have not broken the rule number one. However, this connection is not advisable for the following reasons:
- The client processes do not have synchronized object values. If you change the Pot1 value on the first client it will correctly change the value of Mod1.140001. However, all other client processes are going to keep the original value. The change will not be reflected on their panels.
- You will get the alarm, "Remote position source is not writable". This is because you are trying to write values to Pot3 from two sources: Mod1.40001 and the if(Switch1,Pot1,Pot2) expression. It is not really clear which source should Lookout follow.
On the server machine you should have Mod1, and along with Mod1 you should have a switch (S_Switch1) and two Pots (S_Pot1 and S_Pot2). Now make URL connections from Switch1, Pot1 and Pot2 on the client to S_Switch1, S_Pot1 and S_Pot2 respectively, in the server process. In the server process, make the connection Mod1.40001 = IF(S_Switch1, S_Pot1, S_Pot2). If you change the Pot1 value, Mod1.40001 will update. Because all clients use the same URL remote connection (\\Server\ServerProcess\S_Pot1.value), which is a both way connection, every Pot1 object on every client process will be updated and always reflect the same value.
3. Use symbolic links wherever possible.
We suggest that you use symbolic links when making connections from the client process to the server process. The main reason for this is in case you change the computer on which the server process is running. If you had made URL connections from your client processes to the server process, then you will have to change the computer name in each of the URL connections and expressions, which can be time consuming. If you used symbolic links, then you would not have to do this.