воскресенье, 2 сентября 2012 г.

Documentation to project

HMI (Human-Machine Interface) with Amber

Khubbatov Rustem
Short description:  The aim of this project is to create a framework for building web-based Human-Machine Interfaces in Smalltalk with Pharo-based server back-end model and UI front-end in Amber.


Original Plan


Original plan as it was presented in proposal included the following points:
1. There should be very simplified system for building Human-Machine Interfaces using web-oriented GUI.
2. This system contains of server and clients.
3. The server side of this system should be created using Pharo.
4. The client side of this system should be created using Amber.
5. Client should present structural changes in the server objects.
6. Client should display and allow modifying device properties.
7. There should be realized one-step and multi-step actions with objects. The example of one-step action is adding element to server. The example of multi-step action is network discovery. 
8. There should be a unified protocol for communication between the client and the server.
9. There should be (optional) UI-building facilities: embedded widgets, layouts, etc.
10. Making (optional) communication between client and server parallel.

Actual Work


Problems


I’ve met a number of hurdles during my work like:
- Little knowledge of JavaScript and Amber
- Bugs in Amber 
- WebClient-Core class was not updated for a long time in Pharo, so there were some troubles with Google Chrome browser
- Data transmission is slow sometimes

Unimplemented Features


Because of these problems and a very large amount of information I had to learn, I had no time to implement some features.
1. UI-building facilities were not implemented.
2. Multi-step actions are not supported.
3. Communication between server and client is not parallel.

Additional Features


Some new features that were not presented in the proposal were introduced instead:
1. Large workspace for rendering objects and scaling were implemented.
2. Some visual effects were introduced.
3. Server event simulator was created.

Results


Currently, this project can be viewed as a “prove of concept” for building web-based HMI in Smalltalk. The system consists of server and client pars implemented correspondently in Pharo and Amber. The communication between these subsystems is provided using Web Sockets. A number of real-life applications like Network Management, SCADA systems can employ this architecture as well as ideas and solutions I’ve implemented here.
I used the Network Management metaphor in this project: server simulates network components, their state and related events. Client presents this model and provides UI to control it. The most interesting parts of this project are:
- UI is based on the Raphael JavaScript library.
- WebSocket technology is employed to provide communication between Pharo and Amber.
- Two-way communication: client objects can request data and initiate actions in Pharo image, while server can notify client about events took place in the image.
- Communication protocol is based on Smalltalk messages.

References


- Amber Smalltalk ( http://amber-lang.net )
- Pharo Smalltalk (http://pharo-project.org )
- Raphael JavaScript library ( http://raphaeljs.com )
- WebSocket protocol ( http://websocket.org )

How To Install and Run


To install this system in Linux you have to:
- Download sources of this project or clone them using Git command:
git clone https://github.com/hubbatov/amber_pharo_websocket.git
- Download and install node.js (for example from http://nodejs.org )
- Run Pharo using command: Pharo directory/pharo.sh
- Run server in Pharo using command: WebHMIServer startServerOnPort: aPort
- Run Amber server using command: amber directory/#sudo node ./server/server.js. it must say that the file server is running on port 4000
- Open your browser and go to http://localhost:4000/projects/simpleHMI/admin.html
- Type the server address in the field on top-right corner of the page, for example “localhost:9898”
- Press the connect button. It must say that the connection has been made successfully and you will see objects.

Available functions


You can add objects, delete objects, change their properties. Also server can send notifications (emit events) to clients about changing in object properties, adding or deleting object. All changes made in server by you in workspace or by one of the clients will be shown on all clients, connected to the server.
There are some instructions how to use these functions:
- To add the object click on “Add new item” button. On the right panel input the type and the name of the object. Click on the add button. As a result you will see a new object that you created.
- To remove the object click on “Remove item” button. Then click on the object you want to remove. On the right panel you will see the name of the selected object. Click on remove button. As a result this object will be removed from the server and you will not see it again.
- To change the property of the object click on “Change item” button. Then click on the item you want to change. On the right panel input new properties of the object (title, name type and path to the icon). Click on change button. As a result the new properties will be saved on the server and you will see these changes on the browser.
- Also you can switch on or off objects (change the state of the objects).
- If you run “Event Caster” on the server, you will see how properties (state and usage) are changing. To start “Event Caster” you have to run WebHMIEventCaster start in Pharo workspace. 
About using this project

This project can be used by Smalltalk developers to create web-oriented real-time applications for Human Machine Interfaces of SCADA systems. Such systems are used for monitoring and controlling elements of information systems. 
Look at WebHMIElementType and WebHMIElement Pharo classes and WebHMI and HMIelement Amber classes. There are the main functions for work with the server objects. For example, in WebHMIElementType class on the class side you can already find created types (workstation, router and server). In WebHMIElement class there is only one dynamically changing property called “usage”. It shows how this element is used in percent. Changing of this property will emit event. Receiving this event all clients will show it. For more information look at the method “emitEvent: aEvent” in WebHMIServer class side.
Information that is transmitted between the Pharo server and the Amber clients is presented in Smalltalk code. The server and the clients can execute this code and do actions. How it works? The client asks for the action by sending script written on Smalltalk. The server receives this script, executes it and sends notification to clients about this action as Smalltalk written script. All clients receive this notification and execute it. As a result of this action you will see changes on the latter.
Amber clients use JavaScript and this allows me to use created libraries, as Raphael JS and library for work with the mouse events.
You may look at Amber server in “img/” folder in my project. There are all images I used. If you want to use your own images just copy them in this folder and edit properties using application GUI.

Classes and methods


Pharo side


WebHMIElement instance


createElement: anElementName withType: anElementType – creates element on the server.anElementName – name of new element, anElementType – type of new element.
elName – returns name of the element.
elName: aName – gives new name to the element with emitting signal about it`s changing. aName – new name of the element.
elType – returns WebHMIElementType object, that represents the type of the element.
elType: aType – gives new type to the element with emitting signal about it`s changing. aType – new type of the element.
info – emit signal with full information about this element.
info: aWS – emit signal with full information about this element to one client. aWS – receiver of the message as WebSocket.
state – represents the state of the element, return "on" or "off".
state: aState – gives new state to the element. aState – new state of the element.
switch – switches the element to another state with emitting signal about changing state.
usage – returns integer value, represents the usage of this element (in percent).
usage: aUsage – gives new value of the “usage” of this element, emits signal about it`s changing. aUsage – new value for “usage”.
widget – returns a WebHMIWidget element of this element.
xPos: x yPos: y – sets new x position and y position to element widget, emits signal about it`s changing. x – new x position, y – new y position.

WebHMIElement class


Add: aWebHMIElement – adds new aWebHMIElement.
Remove: aWebHMIElement – removes element aWebHMIElement.
RemoveByName: aName – removes element with name “aName”, emits signal about deleting this element.
elementFromCollection: aName – search for the element with name “aName”.Returns false if this element will not detected, else returns WebHMIElement with name “aName”.
elements– returns the collection of the elements.

WebHMIElementType instance


= - operator for comparing types.
imageOff – returns path to the icon for “off” state.
imageOff: aPath – gives new path to the icon for “off” state. aPath – new path to the icon.
imageOn – returns path to the icon for “on” state.
imageOn: aPath – gives new path to the icon for “on” state. aPath – new path to the icon.
typeName – returns name of this type.
typeName: aName – gives new name for this type. aName – new name of type.

WebHMIElementType class


default – returns "undefined" WebHMIElementType object.
router – returns "router" object type.
server – returns "server" object type.
workstation – returns “workstation” object type.

WebHMIWidget instance


xPos – returns x-coordinate of widget.
xPos: aPos – sets x coordinate of widget.aPos – new x coordinate.
yPos – returns y-coordinate of widget.
yPos: aPos – sets y-coordinate of widget. aPos – new y coordinate.
xPos: xpos yPos: ypos - sets x coordinate and y coordinate of widget. xpos – new x coordinate, ypos – new y coordinate.

WebHMIEventCaster class


start – starts event casting.
stop – terminates event casting.
isStarted – returns true if casting is running and false if casting is stopped.
startRandomCasting – starts random casting events.
castRandomSwitchChange – switch random element.
castRandomUsageChange – changes usage value of random element.
getRandomPosition – get random index of the element from the collection.
getRandomUsage – get random value from 0 to 100.
getRandomVariable – get random value from 0 to 1.

WebHMIServer class


startServerOnPort: aPort – starts the server on port aPort.
processMessage: aMessage withMutex: aMutex fromSockets: aSockets sender: aSender – processing the message aMessage from client aSender.
emitEvent: aEvent – emits event aEvent to all clients.

Amber side


WebHMI instance


createSocket: anAddress – create new WebSocket to address anAddress. Address is a string like “localhost:8080”.
elementsContains: aName – returns true if element with name aName is created and false if element with such name is not created.
prepareWorkField: anId – returns Raphael paper value. anId – id of the “div” element in the HTML.
processMessage: aMsg – processing message method.
processInfoMessage: aMsg – processing message, that will create new element in work field.
processMovedMessage: aMsg – processing message, that will move element.
processParamChangeMessage: aMsg – processing message, that will change property of element.
processSwitchedMessage: aMsg – processing message, that will switch one of the element.
showAddForm – call class method to show “add element” form.
showChangeForm – call class method to show “change element” form.
showRemForm – call class method to show “remove element” form.
start – starts the application.
startAdmin – sets “edit available” settings and starts the application.
startClient – sets “viewer only” settings and starts the application.

WebHMI class


addFormHTML – returns html-code for “add element” form.
addItem – method for adding new element to the server.
changeFormHTML – returns html-code for “change element” form.
changeItem – method for changing properties of the element.
currentItem – returns current selected element.
currentItem: anItem – sets current selected element.
delItem – method for removing element.
enableMoving – returns flag, that allows you to move elements.
enableMoving: aFlag – allows you to move elements, if aFlag is equal true.
field – returns current Raphael paper object.
field: aPaper – sets current Raphael paper object.
removeFormHTML – returns html-code for “remove element” form.
resize – automatically resizes work field.
scale – returns a parameter of current scale.
scale: aParam – sets a parameter for current scale.
setHeight: aHeight – sets height of work field.
setWidth: aWidth – sets width of work field.
setViewBox: x atY: y width: w height: h - sets the view box of the paper. Practically it gives you ability to zoom and pan whole paper surface by specifying new boundaries, x – new x position, y – new y position, w – new width of canvas, h – new height of canvas.
workSpaceId – returns current id for work field.
workSpaceId – sets id for work field.
zoomIn – increase zoom.
zoomOut –decrease zoom.

HMIelement class


elements – returns Array of HMIelement objects.
getElement: aName – returns HMIelement object with name “aName” if it is created. If not returns false.
removeElement: aHMIelement – removes aHMIelement from collection.

HMIelement instance


drawOn: aField – draws element on the field aField.
elName – returns name of the element.
elName: aName – sets name of the element. aName – new name of the element.
elPicture – returns path to the icon depending on state.
elType – returns type of the element.
elType: aHMIelementType – sets new type of the element. aHMIelementType – new type of the element.
element – returns Raphael image object, that represents picture of this element.
setActions – event processing for this element (like mouse drag event or double click event).
state – returns current state of the element.
state: aState – sets current state for the element and redraw itself.
switch – changes state of the element to another state.
text – returns Raphael text object representing name of element.
usage – returns Raphael text object representing usage of element.
usage: aValue - sets current usage of element. aValue – new value for usage.
usingSocket: aWebSocket – sets current socket for sending notifications.
xPos – returns x position.
xPos: x – sets x position. x – new x position.
yPos – returns y position.
yPos: y – sets y position. y – new y position.

HMIelementType instance


off – returns path to the icons for the “off” state.
off: aPath – sets path to the icon for the “off” state. aPath – new path to the icon.
on – returns path to the icons for the “on” state.
on: aPath – sets path to the icon for the “on” state. aPath – new path to the icon.
typeName – returns name of this type.
typeName: aTypeName – sets name for this type. aTypeName – new name of the type.

CommandExecutor class


doIt: aString – executes string “aString” with compiler.
receiver – returns the receiver of the message.
receiver: anObject – sets the receiver of the message. anObject – new receiver.

Комментариев нет:

Отправить комментарий