Get MBLogic at SourceForge.net. Fast, secure and Free Open Source 
	software downloads

Help Topics

HMI Client Libraries

Help - HMI Client Protocol Library


Overview:

The HMI protocol client Javascript library comes in two parts. These are the JSON encoding library and the HMI protocol library itself.


JSON and the HMI System:

JSON is a standard data encoding format used in web applications. The HMI messages are encoded in JSON format. The HMI system can use standard JSON encoding libraries such as "json2.js" from JSON.ORG. With the increasing popularity of JSON, future versions of web browsers are expected to support it natively without requiring a separate Javascript library.


HMI Communications Library:

The HMI communications library is implemented as a single Javascript object. This library ("libhmiclient2.js") does more than just support the HMI protocol. It provides the following features:


The Read List:

The "read list" is an array of tag names that are to be polled (read) on a regular basis. The "read list" is a critical part of an application, because it defines what data is available to the client for display.


	Example - 

	// Make a list of all the address tags to be monitored. This is what we
	// send to the server asking for values.
	var ReadList = ["PL1", "PL2"];


The Zone List:

The "zone list" is an array of zone names that defines the alarms and events that are to be monitored.


	Example - 

	// Make a list of the alarm and event zones to be monitored. Zones are
	// used to filter alarms and events to only those we are interested in. 
	var AlarmZoneList = ["zone1", "zone2", "zone3"];
	var EventZoneList = ["zone1", "zone2", "zone3"];


The Display List:

The display list is an array of code objects which control graphics, text, tables, etc. "UpdateDisplay" calls each item in turn, passes it the latest data, and asks it to update itself. Each screen item must be a code object which exports a method called "UpdateScreen", and which accepts one parameter. e.g. "objref.UpdateScreen(presentstate);"

To add an item to the display list, create the object and pass it to "AddToDisplayList".


	For example - 
	
		// This defines a pilot light control.
		var PL1 = new MB_PilotLight("green", "red", "black", "PL1", document);
		MBHMIProtocol.AddToDisplayList(PL1, "PL1", "read");

This creates a pilot light using "MB_PilotLight" (part of another library), assigns it to a reference called PL1, and passes it to "AddToDisplayList" along with two other parameters.

The second parameter is the "address label". This is used by instructions which need to read the input values. This should be a valid tag from the read list whenever the address label is "read". Its value is not significant for other address labels.

The third parameter is the "tag type". This is a description of the type of address used in the second parameter. This determines the source of the data which is passed to the dislay item. Valid value are: "read" (input data from the read list), "timestamp" (the server time stamp from the last message), "stat" (the server stat value from the last message), "msgid" (the message id returned by the server), "events" (an array of the latest event messages), and "alarms" (an object containing alarms and alarm acknowledgements).

Alarms and alarm acknowledgements are contained in a single object in order to fit both within the single parameter limit. This object has the following form : {"alarms" : this._AlarmBuffer, "alarmsupdated" : this._AlarmsUpdated, "alarmack" : this._AlarmAckBuffer, "alarmackupdated" : this._AlarmAckUpdated};

In this example, "alarms" is the alarm input buffer. "alarmsupdated" is an integer that increments whenever new alarms have arrived. "alarmack" is the alarm acknowledgement input buffer. "alarmackupdated" is an integer that increments whenever new acknowledgement messages have arrived.


Initialisation:

HMIClient(url, port, cid, readlist, alarmzonelist, eventzonelist, ansyncoption);

This is the object name and the initialisation parameters.

The web browser will enforce a security policy requiring that the communications between the HMI web page and the server must be to the same host (address) and port as the web page was loaded from. This means the communications library needs to know the host name and port. This can be accomplished in several ways. One way is to hard code these values. However, that means they must be known in advance.

The other way is to use a standard Javscript object to obtain these values automatically. These are:

You must also decide whether to use synchrnous or asynchronous communications. With synchronous communications, the web browser waits for the server to reply before continuing. With asynchronous communications, the web browser does not wait. Rather, it sends the request and continues running the browser script. When the response from the server is received, the software function which handles the response is automatically called and the display list is updated.

When the web browser and the server are communicating on a reliable local network (or on the same computer), there is normally no noticable difference between the two methods. However, if the network is slow or unreliable, using the synchronous method can cause the web browser to appear to "stall" or be unresponsive. Also, if the server is stopped and restarted for some reason, the web page will require a reload (press "F5" or click on the "reload" icon) before communications will resume.

When asynchronous communications is used, these problems will not occur. The communications library will automatically keep retrying communications. However, some versions of some web browsers when running on some operating systems may have bugs or other problems which prevent asynchronous communications from working correctly. This rarely occurs. However, since applications using asynchronous communications are relatively new, this feature is not as well tested in all browsers as the synchronous method. If problems are encountered when using asynchronous communications, it is suggested to try setting the "ansyncoption" parameter to "false" to see if the synchronous method will work instead.


	// Make a list of all the address tags to be monitored. This is what we
	// send to the server asking for values.
	var ReadList = ["PL1", "PL2"];

	// Make a list of the alarm and event zones to be monitored. Zones are
	// used to filter alarms and events to only those we are interested in. 
	var AlarmZoneList = ["zone1", "zone2", "zone3"];
	var EventZoneList = ["zone1", "zone2", "zone3"];

	/* This handles communications with the server. 
	The parameters are: 
		1) The host name the web page was loaded from.
		2) The port number the web page was loaded from. 
		3) The client ID string.
		4) The list of tags to poll for data.
		5) The list of alarm zones to poll for new alarms.
		6) The list of event zones to poll for new events.
		7) true = Enable asynchronous communications.
	The first two parameters use a standard Javascript feature.
	Alternatively, these can be hard coded values if the host
	and port are known in advance.
	*/
	var MBHMIProtocol = new HMIClient(window.location.hostname, 
				window.location.port, "Any client name string.", 
				ReadList, AlarmZoneList, EventZoneList, true);

There should only be one HMI communications object in an application that takes care of all polling.

The "same origin" security policy in most web browsers requires that a web client application can only communicate with the same host that the web page was loaded from. This means that a single server must be used as the source of the web page and as the source (and destination) of all data.


Updating the Read List Dynamically

SetReadList(readlist)

The read list can be updated while the system is running.


	MBHMIProtocol.SetReadList(NewReadList);

This will change the read list that was set as part of the initialisation process. This is not normally necessary. It may be useful in reducing the amount of data polle in some larger applications. If you are not sure whether you need this feature, you probably do not need it.


Reading and Writing:

AddWrite(writetag, writeval);


	MBHMIProtocol.AddWrite("PumpSpeedCmd", PumpSpeed);

WriteImmediate(writetag, writeval);


		// Stop the pump.
		if (ButName == "PBStop") {
			PumpSpeed = 0;
		}
		// Update the new pump speed.
		MBHMIProtocol.WriteImmediate("PumpSpeedCmd", PumpSpeed);

WriteToggleImmediate(writetag, reftag);


	MBHMIProtocol.WriteToggleImmediate('PB2', 'PL2');

WriteIncImmediate(writetag, reftag, incval, inclimit);


	MBHMIProtocol.WriteIncImmediate('PB4', 'PL4', 1, 6);

function GetServerID()

Read the value of the id string.



function GetMsgStat()

Read the value of the current message status.



GetRead(readlabel);


		var PumpSpeed;
		// First, get the current pump speed.
		PumpSpeed = MBHMIProtocol.GetRead("PumpSpeedActual");

GetTimeStamp();


		var TimeStamp = MBHMIProtocol.GetTimeStamp();


Event and Alarm Handling:

AddAlarmAck();


	MBHMIProtocol.AddAlarmAck();


Display Control:

AddToDisplayList(objref, addrlabel, tagtype);

This adds an HMI display Javascript object to the display list. The "addrlabel" must be a valid tag which is part of the read list. The "tagtype" is a string, and may be "read", "timestamp", etc. (see below). Each of these tag types refers to a valid HMI field from which it derives its data.

The display list is automatically updated whenever new data is received from the server.


	// This defines a pilot light control.
	var PL1 = new MB_PilotLight(document, "PL1", "black", "green", "red");
	var PL2 = new MB_PilotLight(document, "PL2", "black", "green", "red");

	// Now, add each of these screen objects to the list of things to update.
	MBHMIProtocol.AddToDisplayList(PL1, "PL1", "read");
	MBHMIProtocol.AddToDisplayList(PL2, "PL2", "read");

	// This is for the alarm status display on the main screen.
	var AlarmStat = new MB_PLMultiColour(document, "AlarmStat", 
				"black", ["white", "green", "orange", "red"]);
	MBHMIProtocol.AddToDisplayList(AlarmStat, "", "unackalarm");

HMI Tag Types:

For "chkalarm" alarms, the HMI display object will be passed the following values:

Higher number codes take priority over lower numbered codes.


Polling Cycle Control:

SendRequest();

This triggers a communications polling cycle. However, it does not schedule the polling request. Scheduling the polling request must be done by other means. Typically, you would use "setTimeout", which is a standard web page Javascript event. In the example below, the function "RunScanCycle" is being scheduled again in 1000 milliseconds.

The polling time to use will be a compromise between several factors. If the time between polls is too long, there will be a noticable lag between a physical event happening and indication of it on the display. If the time between polls is too short, the load on the computer displaying the HMI client (and possibly the server as well) will be too high.

Also, if asynchronous polling is used, and if the time between polls is too short, the server will not have had enough time to respond before the client begins to send the next poll. If this happens, the connection will be aborted and the client will not receive the reply. In these cases, it is better to either use synchronous communcations (this is set via an initialisation parameter) or to use a slower polling rate.


	// Run all the operations required each scan cycle.
	function RunScanCycle() {

		// Query the server for updates.
		MBHMIProtocol.SendRequest();

		// Call the function back again at the set interval.
		window.setTimeout("RunScanCycle()", 1000);
	}


Communications Watchdog:

CommsWatchDogTimeOut(limit);

This function is useful only when using asynchronous communications. The "SendRequest" function keeps track of the number of requests sent and received. If too many consecutive requests are sent without a response from the server, "CommsWatchDogTimeOut" will return "true". This may be used to annunciate a loss of communications on the screen. The count of requests is automatically reset every time a response is received, so an occasional loss of messages will automatically correct itself when the next response is received.

If communications is lost, a valid response message will not be received, which in turn means the display list will not be called to update itself. If you wish to display a message to the operator, you should call the appropriate function directly yourself. If you are using one of the client display library functions, you may do this by called the "UpdateScreen") method directly.

This method is an alternative to using the watchdog list. The watchdog list method using "SetCommsWatchDogTimeOut" and "AddToWatchdogList" is recommended for most normal applications.


	// Run all the operations required each scan cycle.
	function RunScanCycle() {

		// Query the server for updates.
		MBHMIProtocol.SendRequest();

		// Check the comms watch dog counters.
		ComsTimeOut = MBHMIProtocol.CommsWatchDogTimeOut(10);
		if (ComsTimeOut) {
			CommWD.UpdateScreen(1);
		} else {
			CommWD.UpdateScreen(0);
		}

		// Call the function back again at the set interval.
		window.setTimeout("RunScanCycle()", 1000);
		
	}

SetCommsWatchDogTimeOut(limit);

Set the limit to be used when checking the communications watchdog limit via the watchdog list. The watchdog function checks if responses are being received from the server by comparing a communications counter to the limit.


	// Set the watchdog limit to 10 scans.
	MBHMIProtocol.SetCommsWatchDogTimeOut(10);

AddToWatchdogList(objref);

Add an item to the watchdog list. This is similar to the "display list" but is only for the communications watchdog counter. Objects on this list are scanned and automatically updated each time a request is sent. The watchdog function passes a 1 to the display function if the communications watchdog counter has exceeded the limit, or 0 otherwise.


	// This is for the communications watch dog display. 	
	var CommWD = new MB_PilotLight(document, "CommWatchDog", "black", "green", "red");
	// This is the watchdog list, not the regular display list.
	MBHMIProtocol.AddToWatchdogList(CommWD);