iViewer (our mobile control app) has a built in protocol for expressing UI events such as button presses and slider drags. We call this the 'iViewer Protocol'.
The protocol can also handle updating the UI from external control.
All messages in the iViewer Protocol take the form of:
[identifier]=[value]\x03
Each message is delimited with the End Of Message (EOM) hex value of 03. This delimiter will appear as \x03
in all message examples throughout this document.
The following identifiers are valid within the protocol:
d#
a#
s#
p
i
m
h
l#
(lowercase L)
Digital, Analog and Serial join identifiers must be combined with a join number (starting at 1). For example d12=0\x03
, where the join number is 12.
Digital joins can have a value of either 0 or 1 (low or high, off or on). A typical Digital join message looks like this:
d1=1\x03
The above message sets digital join 1 to a value o f 1 (high).
The following GUI elements make use of Digital joins:
Analog joins can have a value of between 0 and 65535 inclusive. A typical Analog join message looks like this:
a23=54677\x03
The above message sets Analog join 23 to a value of 54677.
The following GUI elements make use of Analog joins:
Serial joins can have any string value. A typical Serial join message looks like this:
s12=Hello World!\x03
The above message sets Serial join 12 to a value of ‘Hello World!’ (without quotes).
The following GUI elements make use of Serial joins:
Connections between iViewer and Server can be password protected to prevent someone connecting to your Server without authorization. The password is set on the Server side, and in the system settings in your guiDesigner projects.
At the initialization of a communication session between iViewer and the Server, iViewer will send a message containing the connection password.
The Server will then respond with a message telling iViewer whether or not the password has been accepted.
The message sequence goes like this:
p=<PasswordValueEnteredInSettings>\x03
p=ok\x03
p=bad\x03
If the password doesn’t match, iViewer will not load the GUI and will show an error message to the user informing them of the password error.
Once the password has been authenticated, iViewer will send the following initialization message:
i=1\x03
The Server will then reply with a group of messages informing the Viewer of any join state values. Only joins with values other than 0 (for Digital and Analog joins) or blank (for Serial joins) will be included in this group of messages.
This is simply used to initialize the GUI state, updating button states, slider values, text values, etc.
A typical group of initialization messages will look like this:
d12=1\x03a1=4555\x03s43=Hello World!\x03
As you can see, this is just a group of standard join messages (as described earlier in this document) concatenated, each message ending with the delimiter value of hex 03.
Whenever a message is received by the Server, it should always check for multiple commands in the one message, and split then parse them appropriately.
iViewer supports two orientations, portrait and landscape. This is utilized in iViewer (for iOS and Android) when rotating the device.
When the orientation mode of iViewer changes, it sends the following command, depending on the mode being changed to:
m=portrait\x03
or
m=landscape\x03
Again, the value is the orientation mode being change to.
iViewer utilizes a heartbeat message to ensure the connection between the mobile device and the Server remains stable.
iViewer sends a heartbeat command every 3 seconds, and expects to receive a reply heartbeat command within 5 seconds or it will show a message warning the user that the connection is experiencing difficulties.
iViewer sends the following heartbeat command:
h=0\x03
and expects the heartbeat reply message of:
h=1\x03
The iViewer application has a very flexible list generation system that allows creation of custom lists with a large emphasis on customizability.
Due to this flexibility, the protocol for sending list data and parsing list feedback is a lot more complex than the rest of the protocol.
Lists can be created in vertical and horizontal orientations, allowing scrolling in one direction (either horizontally or vertically).
Lists are separated into 4 main ‘items’ (which are defined as subpages in guiDesigner). Header, Title, Content and Footer.
Each item can contain any number of GUI objects, such as text, buttons, images, gauges, etc. The only objects that cannot appear on an item’s subpage are input fields and other subpages.
The header item appears only once in the list at the very top (or left if using horizontal lists). The header is optional and only appears if defined in guiDesigner.
Title items can appear multiple times in a list. These should be designed in a way to separate content meaningfully, such as separating a list of artists alphabetically, grouping artists starting with ‘A’, ‘B’, etc, together.
Content items are the main part of lists where your information should be displayed.
Footer items appear only once at the very bottom (or right) of the list. Footer element will be visible only if the list object defines the Footer subpage within guiDesigner.
List generation is quite an intensive process, so we recommend keeping list items as light as possible. Assigning a background color to the list object itself will in turn disable transparency for all other list subpages, drastically increasing performance. So this is a route we recommend for all heavy list usage.
REC_SEP = \x0D FIELD_SEP = \x1E l<list join>=<row command>REC_SEP<row command>REC_SEP ... REC_SEP\x03 Row commands: <row index><command><FIELD_SEP>[fields definition] Available Commands (# = <row index>, 0 based): #t title element at row # #c content element at row # #it insert title element at row # #ic insert content element at row # #i:<subpage name> insert arbitrary subpage at row# #d delete element at row # #-#d delete range of elements from rows # to # (inclusive) 0x clear the entire list contents s scroll list (see below) Fields definition: <join in subpage>=<join value><FIELD_SEP> List Scrolling: s<FIELD_SEP>index<FIELD_SEP>type<FIELD_SEP>animated where * index: the index of the row we want to scroll to * type: desired position on screen: * 0: position row 'index' at top of display * 1: position row 'index' at middle of display * 2: position row 'index' at bottom of display * 3: scroll by 'index' rows (can be negative) * 4: scroll at absolute pixel value 'index' (for pixel-perfect positioning) * 5: position row 'index' anywhere in display * animated: whether the scroll operation should be animated (1 or 0)
Below are some examples of how to generate list data. Please note that any line wrapping in the below commands is to be ignored. All commands should be a single line of text.
Create a list on analog join 10, with one title row and two contents rows:
l10=0t\x1Es1=title\x1Es2=subtitle\x1Ea1=50\x0D1c\x1Es1=content element 1\x0D2c\x1E s1=content element 2\x0D\x03
In the above example, the ‘title item subpage’ in guiDesigner has a single text object on join 1. The ‘content item subpage’ has a single text element on join 1 and a single gauge on analog join 1.
Clear the entire list on join 5:
l5=0x\x03
Update element 2 in the list (on join 10):
l10=1c\x1Es1=new value for content element 2\x0D\x03
Insert element between 1 and 2 in the list (on join 10):
l10=1ic\x1Es2=inserted element\x0D\x03
Delete elements 1 and 2 in the list (on join 10):
l10=0-1d\x0D\x03
Feedback from objects within list elements are very similar to that of normal GUI objects explained at the beginning of this document, with a little twist.
All list feedback data is pre-fixed with the list join, as well as the item number in the list the feedback is coming from. The format is as follows:
l<list join>:<item index>:<join>=<new value>
For example, the next example demonstrates feedback from a button on digital join 2 coming from list element 5 on list join number 3:
l3:5:d2=1\x03
The data elements are separated with colons, with the standard message delimiter. The last element is exactly the same as a normal button press.
So using this data, you can determine which list, list element and GUI object the feedback came from and use the information as needed.