AMX Netlinx Language Reference Guide

Download as pdf or txt
Download as pdf or txt
You are on page 1of 246

Language Reference Guide

NetLinx
Programming Language

Document ID: 033-004-2255


NetLinx Programming Last Revised: 10/05/2006
Software License and Warranty Agreement
LICENSE GRANT.
AMX grants to Licensee the non-exclusive right to use the AMX Software in the manner described in this License. The AMX Software is
licensed, not sold. This license does not grant Licensee the right to create derivative works of the AMX Software. The AMX Software consists
of generally available programming and development software, product documentation, sample applications, tools and utilities, and
miscellaneous technical information. Please refer to the README.TXT file on the compact disc or download for further information regarding
the components of the AMX Software. The AMX Software is subject to restrictions on distribution described in this License Agreement.
LICENSEE MAY NOT SUBLICENSE, RENT, OR LEASE THE AMX SOFTWARE. Licensee may not reverse engineer, decompile, or
disassemble the AMX Software.

INTELLECTUAL PROPERTY.
The AMX Software is owned by AMX and is protected by United States copyright laws, patent laws, international treaty provisions, and/or state
of Texas trade secret laws. Licensee may make copies of the AMX Software solely for backup or archival purposes. Licensee may not copy
the written materials accompanying the AMX Software.

TERMINATION.
AMX RESERVES THE RIGHT, IN ITS SOLE DISCRETION, TO TERMINATE THIS LICENSE FOR ANY REASON AND UPON WRITTEN
NOTICE TO LICENSEE. In the event that AMX terminates this License, the Licensee shall return or destroy all originals and copies of the
AMX Software to AMX and certify in writing that all originals and copies have been returned or destroyed.

PRE-RELEASE CODE.
Portions of the AMX Software may, from time to time, as identified in the AMX Software, include PRE-RELEASE CODE and such
code may not be at the level of performance, compatibility and functionality of the final code. The PRE-RELEASE CODE may not
operate correctly and may be substantially modified prior to final release or certain features may not be generally released. AMX is
not obligated to make or support any PRE-RELEASE CODE. ALL PRE-RELEASE CODE IS PROVIDED "AS IS" WITH NO
WARRANTIES.

LIMITED WARRANTY.
AMX warrants that the AMX Software will perform substantially in accordance with the accompanying written materials for a period of ninety
(90) days from the date of receipt. AMX DISCLAIMS ALL OTHER WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT
LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, WITH REGARD TO THE
AMX SOFTWARE. THIS LIMITED WARRANTY GIVES LICENSEE SPECIFIC LEGAL RIGHTS. Any supplements or updates to the AMX
SOFTWARE, including without limitation, any (if any) service packs or hot fixes provided to Licensee after the expiration of the ninety (90) day
Limited Warranty period are not covered by any warranty or condition, express, implied or statutory.

LICENSEE REMEDIES.
AMX's entire liability and Licensee's exclusive remedy shall be repair or replacement of the AMX Software that does not meet AMX's Limited
Warranty and which is returned to AMX. This Limited Warranty is void if failure of the AMX Software has resulted from accident, abuse, or
misapplication. Any replacement AMX Software will be warranted for the remainder of the original warranty period or thirty (30) days,
whichever is longer. Outside the United States, these remedies may not available.

NO LIABILITY FOR CONSEQUENTIAL DAMAGES. IN NO EVENT SHALL AMX BE LIABLE FOR ANY DAMAGES WHATSOEVER
(INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THIS AMX SOFTWARE,
EVEN IF AMX HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME STATES/COUNTRIES DO NOT
ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION
MAY NOT APPLY TO LICENSEE.

U.S. GOVERNMENT RESTRICTED RIGHTS.


The AMX Software is provided with RESTRICTED RIGHTS. Use, duplication, or disclosure by the Government is subject to
restrictions as set forth in subparagraph ©(1)(ii) of The Rights in Technical Data and Computer Software clause at DFARS 252.227-
7013 or subparagraphs ©(1) and (2) of the Commercial Computer Software Restricted Rights at 48 CFR 52.227-19, as applicable.

SOFTWARE AND OTHER MATERIALS FROM AMX.COM MAY BE SUBJECT TO EXPORT CONTROL.
The United States Export Control laws prohibit the export of certain technical data and software to certain territories. No software from this Site
may be downloaded or exported (i) into (or to a national or resident of) Cuba, Iraq, Libya, North Korea, Iran, Syria, or any other country to
which the United States has embargoed goods; or (ii) anyone on the United States Treasury Department's list of Specially Designated Nation-
als or the U.S. Commerce Department's Table of Deny Orders. AMX does not authorize the downloading or exporting of any software or
technical data from this site to any jurisdiction prohibited by the United States Export Laws.

This Agreement replaces and supersedes all previous AMX Software License Agreements and is governed by the laws of the State of Texas,
and all disputes will be resolved in the courts in Collin County, Texas, USA. For any questions concerning this Agreement, or to contact AMX
for any reason, please write: AMX, 3000 Research Drive, Richardson, TX 75082.
Table of Contents

Table of Contents
Introduction ........................................................................................................1
Conventions Used in this Document ......................................................................... 1
Related Instruction Manuals...................................................................................... 1
NetLinx Programming Overview ........................................................................3
Defining the Superset ............................................................................................... 3
NetLinx vs. Axcess - Comparison by Structure.......................................................... 4
DEFINE_DEVICE.............................................................................................................. 4
DEFINE_CONSTANT ...................................................................................................... 4
DEFINE_VARIABLES........................................................................................................ 5
DEFINE_CALL (Subroutines) ........................................................................................... 6
DEFINE_START ............................................................................................................... 7
DEFINE_EVENT .............................................................................................................. 7
DEFINE_PROGRAM ........................................................................................................ 8
Operators ................................................................................................................. 8
Axcess/NetLinx Incompatibility................................................................................. 9
Data Types.............................................................................................................. 10
Constants................................................................................................................ 10
Variables ................................................................................................................. 11
Persistent Variables ................................................................................................ 12
Arrays ..................................................................................................................... 12
Structures ............................................................................................................... 14
Data sets ....................................................................................................................... 15
Conditionals & Loops.............................................................................................. 17
SWITCH...CASE statements........................................................................................... 17
FOR loops ..................................................................................................................... 18
Functions ................................................................................................................ 19
DEFINE_CALL................................................................................................................ 19
DEFINE_FUNCTION ...................................................................................................... 20
Events ..................................................................................................................... 21
Button Events................................................................................................................ 21
Channel Events.............................................................................................................. 22
Data Events ................................................................................................................... 24
Level Events .................................................................................................................. 27
Combining Devices, Channels and Levels ............................................................... 28
Virtual devices, levels and device/channel sets ............................................................. 28
Combining and uncombining devices............................................................................ 28
Combining and uncombining levels............................................................................... 28

NetLinx Programming Language Reference Guide i


Table of Contents

Combining and uncombining channels .......................................................................... 29


String Comparisons................................................................................................. 29
Axcess code - string comparison ................................................................................... 29
Netlinx code - string comparison .................................................................................. 29
Modules .................................................................................................................. 29
Language Elements ..........................................................................................31
Statements and Expressions ................................................................................... 31
Assignments............................................................................................................ 31
Variables........................................................................................................................ 31
Output channels ............................................................................................................ 31
Conditionals ............................................................................................................ 32
IF…ELSE ........................................................................................................................ 32
SELECT…ACTIVE........................................................................................................... 32
SWITCH…CASE ............................................................................................................. 33
Loops ...................................................................................................................... 34
WHILE statements ......................................................................................................... 34
MEDIUM_WHILE statements ......................................................................................... 34
LONG_WHILE statements ............................................................................................. 35
FOR loop structure ........................................................................................................ 35
Waits....................................................................................................................... 36
Naming Waits ................................................................................................................ 36
Types of Waits............................................................................................................... 36
Nesting Waits ................................................................................................................ 37
Pausing and restarting Waits......................................................................................... 38
Canceling Waits............................................................................................................. 38
Using Waits - Limitations ............................................................................................... 38
Comments............................................................................................................... 39
Operators ............................................................................................................... 39
Arithmetic operators ..................................................................................................... 39
Relational operators ...................................................................................................... 39
Logical operators .......................................................................................................... 40
Bitwise operators .......................................................................................................... 40
Assignment operators ................................................................................................... 40
Operator precedence .................................................................................................... 41
Identifiers................................................................................................................ 41
Devices .......................................................................................................................... 41
Device arrays ................................................................................................................. 42
Device array examples .................................................................................................. 43
Device-channels and device-channel arrays ................................................................... 43
Device-level arrays ........................................................................................................ 44

ii NetLinx Programming Language Reference Guide


Table of Contents

Variables ................................................................................................................. 45
Scope ............................................................................................................................ 45
Local variables............................................................................................................... 45
Global variables............................................................................................................. 47
Constancy...................................................................................................................... 48
Persistence .................................................................................................................... 48
Constants................................................................................................................ 49
Data Types.............................................................................................................. 50
Intrinsic types ................................................................................................................ 50
Type conversion ............................................................................................................ 50
Type conversion rules.................................................................................................... 50
Strings .................................................................................................................... 51
String expressions ......................................................................................................... 51
Wide strings .................................................................................................................. 51
Arrays .................................................................................................................... 52
Multi-dimensional arrays ............................................................................................... 53
Structures ............................................................................................................... 55
Subroutines............................................................................................................. 56
DEFINE_CALL subroutines ............................................................................................ 56
SYSTEM_CALL subroutines ........................................................................................... 56
Function Subroutines .................................................................................................... 57
Calling parameters ........................................................................................................ 59
Event Handlers .................................................................................................61
Button events................................................................................................................ 62
Channel events.............................................................................................................. 63
Data events ................................................................................................................... 64
Level events .................................................................................................................. 65
Custom events .............................................................................................................. 67
Event Parameters .......................................................................................................... 68
Timeline Functions .................................................................................................. 71
Creating a timeline........................................................................................................ 71
TIMELINE example ........................................................................................................ 74
TIMELINE IDs ................................................................................................................ 78
Combining Devices, Levels, and Channels ........................................................79
Combining and Un-Combining Devices................................................................... 79
Combining devices ........................................................................................................ 79
Un-combining devices ................................................................................................... 81
Combining and Un-Combining Levels ..................................................................... 82
Combining levels........................................................................................................... 83

NetLinx Programming Language Reference Guide iii


Table of Contents

Un-combining levels ...................................................................................................... 83


Combining and Un-combining Channels ................................................................. 84
Combining channels ...................................................................................................... 84
Un-combining channels.................................................................................................. 84
Master-To-Master (M2M) ..................................................................................91
Master Routing ....................................................................................................... 92
Design considerations and constraints .......................................................................... 93
Control/NetLinx Language Support........................................................................ 95
Design considerations and constraints .......................................................................... 95
General Master-to-Master Issues................................................................................... 95
Mainline ............................................................................................................97
Reserved Identifiers ..........................................................................................99
Compiler Directives ................................................................................................ 99
#DEFINE ................................................................................................................................ 99
#END_IF ................................................................................................................................ 99
#ELSE .................................................................................................................................... 99
#IF_DEFINED ........................................................................................................................ 99
#IF_NOT_DEFINED ............................................................................................................... 99
Keywords & Run-Time Library Functions............................................................... 100
__DATE__ ............................................................................................................................ 100
__FILE__ .............................................................................................................................. 100
__LDATE__ .......................................................................................................................... 100
__LINE__ ............................................................................................................................. 100
__NAME__ ........................................................................................................................... 100
__TIME__ ............................................................................................................................. 100
ABS_VALUE ........................................................................................................................ 100
ACTIVE ................................................................................................................................ 100
#INCLUDE ........................................................................................................................... 100
#WARN ................................................................................................................................ 100
ADD_URL_ENTRY .............................................................................................................. 101
AND (&&) ............................................................................................................................. 101
ASTRO_CLOCK .................................................................................................................. 101
ATOI ..................................................................................................................................... 102
ATOF .................................................................................................................................... 102
ATOL .................................................................................................................................... 102
BAND (&) ............................................................................................................................. 102
BNOT (~) .............................................................................................................................. 102
BOR (|) ................................................................................................................................. 102
BREAK ................................................................................................................................. 103
BUTTON_EVENT ................................................................................................................ 103
BXOR (^) .............................................................................................................................. 103
CALL .................................................................................................................................... 103
CANCEL_ALL_WAIT ........................................................................................................... 103
CANCEL_ALL_WAIT_UNTIL ............................................................................................... 103
CANCEL_WAIT .................................................................................................................... 103
CANCEL_WAIT_UNTIL ....................................................................................................... 104
CASE ................................................................................................................................... 104
CHANNEL_EVENT .............................................................................................................. 104

iv NetLinx Programming Language Reference Guide


Table of Contents

CHAR ................................................................................................................................... 104


CHARD ................................................................................................................................ 104
CHARDM ............................................................................................................................. 104
CLEAR_BUFFER ................................................................................................................. 104
CLKMGR_ADD_USERDEFINED_TIMESERVER ............................................................... 105
CLKMGR_DELETE_USERDEFINED_TIMESERVER ......................................................... 105
CLKMGR_GET_ACTIVE_TIMESERVER ............................................................................ 105
CLKMGR_GET_DAYLIGHTSAVINGS_OFFSET ................................................................ 105
CLKMGR_GET_END_DAYLIGHTSAVINGS_RULE ........................................................... 105
CLKMGR_GET_RESYNC_PERIOD .................................................................................... 105
CLKMGR_GET_START_DAYLIGHTSAVINGS_RULE ....................................................... 105
CLKMGR_GET_TIMESERVERS ......................................................................................... 106
CLKMGR_GET_TIMEZONE ................................................................................................ 106
CLKMGR_IS_DAYLIGHTSAVINGS_ON ............................................................................. 106
CLKMGR_IS_NETWORK_SOURCED ................................................................................ 106
CLKMGR_SET_ACTIVE_TIMESERVER ............................................................................ 106
CLKMGR_SET_CLK_SOURCE .......................................................................................... 106
CLKMGR_SET_DAYLIGHTSAVINGS_MODE .................................................................... 106
CLKMGR_SET_DAYLIGHTSAVINGS_OFFSET ................................................................. 106
CLKMGR_SET_END_DAYLIGHTSAVINGS_RULE ............................................................ 106
CLKMGR_SET_RESYNC_PERIOD .................................................................................... 107
CLKMGR_SET_START_DAYLIGHTSAVINGS_RULE ....................................................... 107
CLKMGR_SET_TIMEZONE ................................................................................................ 107
CLOCK ................................................................................................................................. 107
COMBINE_CHANNELS ....................................................................................................... 107
COMBINE_DEVICES ........................................................................................................... 108
COMBINE_LEVELS ............................................................................................................. 108
COMMAND .......................................................................................................................... 108
COMPARE_STRING ........................................................................................................... 109
CONSTANT ......................................................................................................................... 109
CREATE_BUFFER .............................................................................................................. 109
CREATE_LEVEL ................................................................................................................. 110
CREATE_MULTI_BUFFER ................................................................................................. 110
DATA_EVENT ...................................................................................................................... 111
DATE .................................................................................................................................... 112
DAY ...................................................................................................................................... 112
DATE_TO_DAY ................................................................................................................... 112
DATE_TO_MONTH ............................................................................................................. 112
DATE_TO_YEAR ................................................................................................................. 112
DAY_OF_WEEK .................................................................................................................. 112
DEFAULT ............................................................................................................................. 112
DEFINE_CALL ..................................................................................................................... 113
DEFINE_COMBINE ............................................................................................................. 113
DEFINE_CONNECT_LEVEL ............................................................................................... 113
DEFINE_CONSTANT .......................................................................................................... 113
DEFINE_DEVICE ................................................................................................................. 114
DEFINE_EVENT .................................................................................................................. 114
DEFINE_FUNCTION ........................................................................................................... 114
DEFINE_LATCHING ............................................................................................................ 114
DEFINE_MODULE ............................................................................................................... 114
DEFINE_MUTUALLY_EXCLUSIVE ..................................................................................... 115
DEFINE_PROGRAM ........................................................................................................... 115
DEFINE_START .................................................................................................................. 115
DEFINE_TOGGLING ........................................................................................................... 115

NetLinx Programming Language Reference Guide v


Table of Contents

DEFINE_TYPE ..................................................................................................................... 115


DEFINE_VARIABLE ............................................................................................................ 116
DELETE_URL_ENTRY ........................................................................................................ 116
DEV ...................................................................................................................................... 116
DEVCHAN ............................................................................................................................ 116
DEVICE_ID .......................................................................................................................... 116
DEVICE_ID_STRING ........................................................................................................... 116
DEVICE_INFO ..................................................................................................................... 117
DEVLEV ............................................................................................................................... 118
DO_PUSH ............................................................................................................................ 119
DO_PUSH_TIMED ............................................................................................................... 119
DO_RELEASE ..................................................................................................................... 119
DOUBLE .............................................................................................................................. 119
DUET_MEM_SIZE_GET ...................................................................................................... 119
DUET_MEM_SIZE_SET ...................................................................................................... 119
ELSE .................................................................................................................................... 119
FALSE .................................................................................................................................. 119
FILE_CLOSE ....................................................................................................................... 120
FILE_COPY ......................................................................................................................... 120
FILE_CREATEDIR ............................................................................................................... 121
FILE_DELETE ...................................................................................................................... 121
FILE_DIR ............................................................................................................................. 121
FILE_GETDIR ...................................................................................................................... 122
FILE_OPEN ......................................................................................................................... 122
FILE_READ .......................................................................................................................... 123
FILE_READ_LINE ................................................................................................................ 123
FILE_REMOVEDIR .............................................................................................................. 124
FILE_RENAME .................................................................................................................... 124
FILE_SEEK .......................................................................................................................... 124
FILE_SETDIR ...................................................................................................................... 125
FILE_WRITE ........................................................................................................................ 125
FILE_WRITE_LINE .............................................................................................................. 125
FIND_STRING ..................................................................................................................... 126
FIRST_LOCAL_PORT ......................................................................................................... 126
FLOAT .................................................................................................................................. 126
FOR ...................................................................................................................................... 126
FORMAT .............................................................................................................................. 127
FTOA .................................................................................................................................... 128
GET_BUFFER_CHAR ......................................................................................................... 128
GET_BUFFER_STRING ...................................................................................................... 128
GET_DNS_LIST ................................................................................................................... 129
GET_IP_ADDRESS ............................................................................................................. 129
GET_LAST ........................................................................................................................... 130
GET_MULTI_BUFFER_STRING ......................................................................................... 131
GET_PULSE_TIME ............................................................................................................. 131
GET_SERIAL_NUMBER ..................................................................................................... 131
GET_SYSTEM_NUMBER ................................................................................................... 131
GET_TIMER ......................................................................................................................... 131
GET_UNIQUE_ID ................................................................................................................ 131
GET_URL_LIST ................................................................................................................... 132
HEXTOI ................................................................................................................................ 133
HOLD ................................................................................................................................... 134
IF .......................................................................................................................................... 134
INCLUDE ............................................................................................................................. 134

vi NetLinx Programming Language Reference Guide


Table of Contents

INTEGER ............................................................................................................................. 134


IP_CLIENT_CLOSE ............................................................................................................. 134
IP_CLIENT_OPEN ............................................................................................................... 135
IP_MC_SERVER_OPEN ..................................................................................................... 136
IP_SERVER_CLOSE ........................................................................................................... 136
IP_SERVER_OPEN ............................................................................................................. 137
ITOA ..................................................................................................................................... 137
ITOHEX ................................................................................................................................ 137
LDATE .................................................................................................................................. 137
LEFT_STRING ..................................................................................................................... 138
LENGTH_ARRAY ................................................................................................................ 138
LENGTH_STRING ............................................................................................................... 139
LENGTH_VARIABLE_TO_STRING (VARIABLE Encode) .................................................. 139
LENGTH_VARIABLE_TO_XML ........................................................................................... 139
LEVEL_EVENT .................................................................................................................... 139
LOCAL_VAR ........................................................................................................................ 139
LONG ................................................................................................................................... 139
LONG_WHILE ...................................................................................................................... 140
LOWER_STRING ................................................................................................................ 140
LSHIFT ................................................................................................................................. 140
MASTER_SN ....................................................................................................................... 140
MASTER_SLOT ................................................................................................................... 140
MAX_VALUE ........................................................................................................................ 140
MAX_LENGTH_ARRAY ...................................................................................................... 140
MAX_LENGTH_STRING ..................................................................................................... 141
MEDIUM_WHILE ................................................................................................................. 141
MID_STRING ....................................................................................................................... 141
MIN_VALUE ......................................................................................................................... 141
MIN_TO ................................................................................................................................ 141
MOD (%) .............................................................................................................................. 142
MODULE_NAME ................................................................................................................. 142
NOT (!) ................................................................................................................................. 142
NON_VOLATILE .................................................................................................................. 142
OFF ...................................................................................................................................... 142
OFFLINE .............................................................................................................................. 142
ON ........................................................................................................................................ 142
ONERROR ........................................................................................................................... 142
ONLINE ................................................................................................................................ 142
OR (||) .................................................................................................................................. 142
PAUSE_ALL_WAIT .............................................................................................................. 142
PAUSE_WAIT ...................................................................................................................... 142
PERSISTENT ....................................................................................................................... 143
PROGRAM_NAME .............................................................................................................. 143
PULSE ................................................................................................................................. 143
PUSH ................................................................................................................................... 143
PUSH_CHANNEL ................................................................................................................ 143
PUSH_DEVCHAN ................................................................................................................ 143
PUSH_DEVICE .................................................................................................................... 143
RANDOM_NUMBER ............................................................................................................ 143
RAW_BE .............................................................................................................................. 143
RAW_LE .............................................................................................................................. 143
REBOOT .............................................................................................................................. 144
REBUILD_EVENT() ............................................................................................................. 144
REDIRECT_STRING ........................................................................................................... 146

NetLinx Programming Language Reference Guide vii


Table of Contents

RELEASE ............................................................................................................................. 146


RELEASE_CHANNEL ......................................................................................................... 146
RELEASE_DEVCHAN ......................................................................................................... 146
RELEASE_DEVICE ............................................................................................................. 146
REMOVE_STRING .............................................................................................................. 147
REPEAT ............................................................................................................................... 147
RESTART_ALL_WAIT ......................................................................................................... 147
RESTART_WAIT ................................................................................................................. 147
RETURN .............................................................................................................................. 147
RIGHT_STRING .................................................................................................................. 147
RSHIFT ................................................................................................................................ 148
SELECT…ACTIVE ............................................................................................................... 148
SEND_COMMAND .............................................................................................................. 148
SEND_LEVEL ...................................................................................................................... 148
SEND_STRING .................................................................................................................... 148
SET_DNS_LIST ................................................................................................................... 149
SET_IP_ADDRESS ............................................................................................................. 149
SET_LENGTH_ARRAY ....................................................................................................... 150
SET_LENGTH_STRING ...................................................................................................... 150
SET_OUTDOOR_TEMPERATURE ..................................................................................... 150
SET_PULSE_TIME .............................................................................................................. 150
SET_SYSTEM_NUMBER .................................................................................................... 151
SET_TIMER ......................................................................................................................... 151
SET_VIRTUAL_CHANNEL_COUNT ................................................................................... 151
SET_VIRTUAL_LEVEL_COUNT ......................................................................................... 151
SET_VIRTUAL_PORT_COUNT .......................................................................................... 151
SINTEGER ........................................................................................................................... 151
SLONG ................................................................................................................................. 151
STACK_VAR ........................................................................................................................ 152
STRING ................................................................................................................................ 152
STRING_TO_VARIABLE (VARIABLE DECODE) ................................................................ 152
STRUCTURE ....................................................................................................................... 152
SWITCH...CASE .................................................................................................................. 153
SYSTEM_CALL ................................................................................................................... 153
SYSTEM_NUMBER ............................................................................................................. 153
TIME ..................................................................................................................................... 153
TIME_TO_HOUR ................................................................................................................. 153
TIME_TO_MINUTE .............................................................................................................. 153
TIME_TO_SECOND ............................................................................................................ 154
TIMED_WAIT_UNTIL ........................................................................................................... 154
TIMELINE_ACTIVE .............................................................................................................. 154
TIMELINE_CREATE ............................................................................................................ 154
TIMELINE_EVENT ............................................................................................................... 155
TIMELINE_GET ................................................................................................................... 155
TIMELINE_KILL ................................................................................................................... 155
TIMELINE_PAUSE .............................................................................................................. 155
TIMELINE_RELOAD ............................................................................................................ 156
TIMELINE_RESTART .......................................................................................................... 156
TIMELINE_SET .................................................................................................................... 156
TO ........................................................................................................................................ 157
TOTAL_OFF ........................................................................................................................ 157
TRUE ................................................................................................................................... 157
TYPE_CAST ........................................................................................................................ 157
UNCOMBINE_CHANNELS .................................................................................................. 157

viii NetLinx Programming Language Reference Guide


Table of Contents

UNCOMBINE_DEVICES ..................................................................................................... 157


UNCOMBINE_LEVELS ........................................................................................................ 158
UPPER_STRING ................................................................................................................. 158
VARIABLE_TO_STRING (VARIABLE ENCODE) ................................................................ 158
VARIABLE_TO_XML ........................................................................................................... 159
VOLATILE ............................................................................................................................ 161
WAIT .................................................................................................................................... 161
WAIT_UNTIL ........................................................................................................................ 161
WHILE .................................................................................................................................. 161
WIDECHAR .......................................................................................................................... 161
XML_TO_VARIABLE ........................................................................................................... 162
Send_Commands .................................................................................................. 164
DEFINE_MUTUALLY_EXCLUSIVE and Variables.......................................................... 164
XOR (^^) ............................................................................................................................... 164
Compiler Messages ........................................................................................167
Compiler Warnings ............................................................................................... 167
(w) Cannot assign unlike types .................................................................................... 167
(w) Define_Call is not used .......................................................................................... 167
(w) Integer applies to arrays only ................................................................................ 167
(w) Long_While within While ....................................................................................... 167
(w) Possibly too many nested levels ............................................................................ 167
(w) Variable is not used ............................................................................................... 168
Compiler Errors .................................................................................................... 168
A "<symbol>" was expected ...................................................................................... 168
ACTIVE keyword expected ......................................................................................... 168
Allowed only in DEFINE_START .................................................................................. 168
Attempted CALL to undefined subroutine .................................................................. 168
Comment never ends, EOF encountered .................................................................... 168
Conditional compile nesting too deep ........................................................................ 168
Constant type not allowed .......................................................................................... 168
DEFINE_CALL must have a name ................................................................................ 168
DEFINE_CALL name already used ............................................................................... 168
Device values must be equal ....................................................................................... 168
Duplicate symbol......................................................................................................... 168
Evaluation stack overflow ........................................................................................... 169
Evaluation stack underflow ......................................................................................... 169
Identifier expected...................................................................................................... 169
Identifier is not an array type ...................................................................................... 169
Include file not found .................................................................................................. 169
Invalid include file name.............................................................................................. 169
Library file not found .................................................................................................. 169
Maximum string length exceeded............................................................................... 169
Must be char array reference ...................................................................................... 169

NetLinx Programming Language Reference Guide ix


Table of Contents

Must be integer reference........................................................................................... 169


Out of memory............................................................................................................ 169
Parameter mismatch in CALL....................................................................................... 169
Program_Name must be on line 1 ............................................................................... 169
Push/Release not allowed within Push/Release ........................................................... 169
Push/Release not allowed within Wait......................................................................... 169
PUSH_CHANNEL not allowed within Wait .................................................................. 170
RELEASE_CHANNEL not allowed within Wait............................................................. 170
PUSH_DEVICE not allowed within Wait....................................................................... 170
RELEASE_DEVICE not allowed within Wait ................................................................. 170
String constant expected ............................................................................................ 170
String constant never ends, EOF encountered............................................................ 170
String literal expected................................................................................................. 170
Subroutine may not call itself ...................................................................................... 170
Syntax error................................................................................................................. 170
SYSTEM_CALL name not same as PROGRAM_NAME in <file> ................................... 170
This variable type not allowed .................................................................................... 170
TO statements that occur outside the data flow of PUSH events/statements may not work
170
Too few parameters in CALL ....................................................................................... 171
Too many include files ................................................................................................. 171
Too many parameters in CALL .................................................................................... 171
Type mismatch in function CALL ................................................................................. 171
Undefined identifier .................................................................................................... 171
Unmatched #END_IF ................................................................................................... 171
Unrecognized character in input file............................................................................ 171
Use SYSTEM_CALL [instance] 'name'........................................................................... 171
Variable assignment not allowed here ........................................................................ 171
Wait not found ............................................................................................................ 171
Run-Time Errors .................................................................................................... 171
Bad assign 2dim... ....................................................................................................... 171
Bad assign Call... ......................................................................................................... 172
Bad element assign... .................................................................................................. 172
Bad Off... Bad On... Bad To......................................................................................... 172
Bad re-assign Call... ..................................................................................................... 172
Bad run token.............................................................................................................. 172
Bad Set_Length... ........................................................................................................ 172
Bad While .................................................................................................................... 172
NetLinx UniCode Functions ............................................................................173
Overview .............................................................................................................. 173

x NetLinx Programming Language Reference Guide


Table of Contents

_WC ..................................................................................................................................... 173


CH_TO_WC ......................................................................................................................... 173
WC_COMPARE_STRING ................................................................................................... 173
WC_CONCAT_STRING ...................................................................................................... 173
WC_DECODE ...................................................................................................................... 174
WC_ENCODE ...................................................................................................................... 174
WC_FILE_CLOSE ............................................................................................................... 175
WC_FILE_OPEN ................................................................................................................. 176
WC_FILE_READ .................................................................................................................. 177
WC_FILE_READ_LINE ........................................................................................................ 177
WC_FILE_WRITE ................................................................................................................ 178
WC_FILE_WRITE_LINE ...................................................................................................... 178
WC_FIND_STRING ............................................................................................................. 178
WC_GET_BUFFER_CHAR ................................................................................................. 179
WC_GET_BUFFER_STRING .............................................................................................. 179
WC_LEFT_STRING ............................................................................................................. 179
WC_LENGTH_STRING ....................................................................................................... 179
WC_LOWER_STRING ........................................................................................................ 180
WC_MAX_LENGTH_STRING ............................................................................................. 180
WC_MID_STRING ............................................................................................................... 180
WC_REMOVE_STRING ...................................................................................................... 180
WC_RIGHT_STRING .......................................................................................................... 181
WC_SET_LENGTH_STRING .............................................................................................. 181
WC_TO_CH ......................................................................................................................... 181
WC_TP_ENCODE ............................................................................................................... 181
WC_UPPER_STRING ......................................................................................................... 181
Working With UniCode in NetLinx Studio v2.4..................................................... 182
Configuring NetLinx Studio......................................................................................... 182
Including the Unicode Library ..................................................................................... 183
Defining a Unicode String Literal ................................................................................ 183
Storing a Unicode String ............................................................................................. 184
Working with WIDECHAR arrays and Unicode Strings ................................................ 184
Character Case Mappings ........................................................................................... 185
Concatenating String .................................................................................................. 185
Converting between WIDECHAR and CHAR ............................................................... 185
Using FORMAT............................................................................................................ 185
Reading and Writing to Files....................................................................................... 186
Send strings to a User Interface .................................................................................. 186
Right-to-Left Unicode Strings...................................................................................... 186
Compiler Errors ........................................................................................................... 187
IP Communication ..........................................................................................189
Client Programming.............................................................................................. 189
Initiating a conversation .............................................................................................. 189
Terminating a conversation ......................................................................................... 190
Sending data ............................................................................................................... 190
Receiving data............................................................................................................. 190

NetLinx Programming Language Reference Guide xi


Table of Contents

Server Programming ............................................................................................. 191


Listening for client requests ........................................................................................ 191
Multiple client connections.......................................................................................... 192
Closing a local port ..................................................................................................... 192
Connection-oriented notifications ............................................................................... 192
Receiving data............................................................................................................. 193
Sending data ............................................................................................................... 193
Receiving Data with UDP ............................................................................................ 193
Multicast...................................................................................................................... 194
Example IP Code ......................................................................................................... 194
NetLinx Modules ............................................................................................197
Defining a module ....................................................................................................... 197
Using a module in a program ...................................................................................... 204
Internet Inside ................................................................................................207
Java TPClasses............................................................................................................. 207
WDM Configuration .................................................................................................... 208
Encoding and Decoding: Binary and XML ......................................................209
Appendix A: Marshalling Protocol ..................................................................215
Marshalling Protocol (Group of Bytes) .................................................................. 215
Marshalled Stream Format .......................................................................................... 215
Marshalling Protocol (Variables) ........................................................................... 217
Marshalled Stream format ........................................................................................... 217
Encoding notes:........................................................................................................... 219
String encoding ........................................................................................................... 219
Binary array encoding.................................................................................................. 219
Binary Encoding Result................................................................................................ 221
XML Encoding Result .................................................................................................. 223
Appendix B: Glossary .....................................................................................225

xii NetLinx Programming Language Reference Guide


Table of Contents

NetLinx Programming Language Reference Guide xiii


Table of Contents

xiv NetLinx Programming Language Reference Guide


Introduction

Introduction
NetLinx® is the second generation of the Axcess® programming language and is a superset of the
original Axcess language with extensions for additional data types, new event handlers, structure
support, multi-dimensional arrays, and other features. This document assumes that you are familiar with
Axcess; the focus is on the new language elements and how they extend the functionality of the existing
language.
For background information on Axcess, refer to the Axcess Programming Language instruction manual.
For a side-by-side comparison of programming in Axcess and NetLinx, refer to the NetLinx
Programming Overview section on page 3.

Conventions Used in this Document


NetLinx contains a number of keywords that define various available operations to perform in a NetLinx
command, such as the word CALL in the statement:
CALL 'Read Data' (Buffer)

Keywords are case insensitive. For example, the PUSH command is the same as push. Keywords are
reserved, meaning that identifiers (device names, constants, or variables) must have unique names. These
keywords are listed and defined in the Reserved Identifiers section on page 99. All references to NetLinx
language keywords in this document appear in THE FONT SHOWN HERE, in all capital letters.
Programming examples appear in the same fixed font. For example:
DEFINE_VARIABLE
CHAR MyString[32]
INTEGER StrLen

Square brackets indicate an optional element in a command. Angle brackets indicate substitution. In the
example below, the notation <return type> indicates that a valid data type (such as CHAR, INTEGER,
or FLOAT) must be substituted for <return type>. The square brackets surrounding it indicate that
the return type is optional.
DEFINE_FUNCTION [<return type>] <name> [(Param1, Param2, …)]
{
(* body of subroutine *)
}

Related Instruction Manuals


These instruction manuals contain additional information that relates to the NetLinx Programming
Language:
Axcess Programming Language Instruction Manual
NetLinx Studio Program Instruction Manual

NetLinx Programming Language Reference Guide 1


Introduction

2 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

NetLinx Programming Overview


The NetLinx control system was designed to upgrade the processor bus and improve the power of the
Axcess programming language. Originally named Axcess2, the NetLinx was designed to be a superset of
the Axcess programming language. The relationship between the new language (NetLinx) and Axcess is
very similar to the relationship between C++ and C.
Just as C++ brought a whole new level of power to C programming, NetLinx offers a variety of new tools
and commands to dynamically increase the speed and power of present and future applications.

Use the NetLinx Studio software program to create, compile, and transfer Axcess/
NetLinx code.

Defining the Superset


NetLinx contains all of the elements of Axcess. Largely, you can use the same code from Axcess
systems in NetLinx systems. Some exceptions include variable names conflicting with new NetLinx
keywords; however, Axcess keywords are valid in NetLinx.
You cannot compile NetLinx code on an Axcess compiler, or download NetLinx code to an Axcess
control system. To upgrade an existing Axcess control system to NetLinx you must upgrade the Axcess
Master to a NetLinx Master. You can still use the existing Axcess equipment as long as you can disable
the existing Axcess Central Controller.

The exceptions are the Axcent, the Axcent2, the AXB-EM232, and the AXB-MPE+
Master Port Expander. None of these integrated controllers allow you to disable the
Central Controller. Both Axcess Card Frame Systems and Axcent3 systems allow you
to either remove or disable the Axcess Central Controller. If you are using an
Axcent3 / Axcent3 Pro, you can disable the Master with the OpenAxcess program.
You can connect the Axcent3 / Axcent3 Pro to a NetLinx Master Module via AXlink.
Then you can compile and download the existing Axcess code.

Several Axcess control limitations have been fixed in NetLinx.


NetLinx expands the types of data and variables from Axcess.
NetLinx provides multiple processes and event threads beyond the Mainline in Axcess.
NetLinx offers more options in distributed processing. NetLinx expands and strengthens
Master-to-Master communications and expands the traditional AXlink bus to include ICSNet
and Ethernet Network communications.
Axcess is linear in its process. At run time, Axcess runs the DEFINE_START code once when the system
is loaded or restarted. Axcess then makes a pass through mainline code, polls the bus for activity, checks
the wait and pulse stacks, and repeats the process again. The length of mainline and the activity on the
bus affect runtime speeds. The mainline process is considered a single thread.
NetLinx runs on multiple threads; mainline and event handlers run on parallel threads. Event handlers
are defined within NetLinx and operate like mini-mainlines. They contain far less code and run faster
than mainline. If an event occurs, and an event handler has been defined for that event, NetLinx bypasses
mainline and runs the event handler.

NetLinx Programming Language Reference Guide 3


NetLinx Programming Overview

NetLinx vs. Axcess - Comparison by Structure


DEFINE_DEVICE
Axcess Language NetLinx Language
Axcess defines devices with a single number (some- NetLinx defines the device by Device:Port:System.
times called an address) from 1 to 255. Axcess per- • Device is a 16-bit integer representing the device
mits a maximum of 255 devices on the AXlink bus. number. Physical devices range from 1 to 32,767.
DEFINE_DEVICE Virtual devices range from 32,768 to 36,863.
VCR = 1 (* AXC-IRS *) Note: These numbers do not seem so random when
VPROJ= 2 (* AXC-IRS *) represented in hexadecimal. Physical devices range
TP = 128 (* AXT-CA10*) from $0001 to $7FFF. Virtual devices range from
$8000 to $8FFF.
• Port is a 16-bit integer representing the port number in
a range of 1 through the number of ports on the
device.
• System is a 16-bit integer representing the system
number (0 indicates this system).
DEFINE_DEVICE
VCR = 1:1:0 (* NXC-IRS4 PORT 1 *)
VPROJ= 1:2:0 (* PORT 2 *)
TP = 128:1:0 (* AXT-CA10 *)

DEFINE_CONSTANT
Axcess Language NetLinx Language
Axcess defines constants as either a fixed integer NetLinx processes constants just like Axcess. NetLinx
value between 0 and 65,535 or an array with a max- also allows you to define an expression in the
imum length of 255 bytes in which each element can DEFINE_CONSTANT section. The expression cannot
hold a value from 0 to 255. These values can be contain any variables.
expressed in ASCII, Decimal, or Hexadecimal. DEFINE_CONSTANT
DEFINE_CONSTANT VALUE_MIN = 40
VALUE_MAX = 140 DEFAULT_NAME = 'Axcess'
DEFAULT_NAME = 'Axcess' ETX [] = {$FE,$FF}
ETX = "$FE,$FF" VALUE_MAX = VALUE_MIN + 100
VALUE_MAX = VALUE_MIN + 100

4 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

DEFINE_VARIABLES
Axcess Language NetLinx Language
Axcess supports 5 types of variables: NetLinx substantially increased the number of supported
• Integer Variables (default) can contain a value variable types. In addition to more data types, NetLinx
from 0 to 65,535. also supports Sets, Structures, and Multi-dimensional
arrays.
• Character Arrays are single element arrays, in
which each element has a value from 0 to 255 with Arrays default to Character Arrays. Variables default to
a maximum of 255 elements Integer Variables. Variables default to Non-Volatile, but
can be set as Non-Volatile or Volatile (Volatile variables
• 2-Dimensional Arrays equate to a maximum of are initialized when code is loaded or when the system
255 single element character arrays. Each
is reset).
element can have a value from 0 to 255.
DEFINE_VARIABLE
• Integer Arrays are single element arrays, in which
CHAR VALUE1
each element can contain a value from 0 to 65,535
WIDECHAR BIGCHAR
with a maximum of 255 elements
INTEGER VALUE2
• 2-Dimensional Integer Arrays may have a
SINTEGER SIGNED1
maximum value of 65,535.
LONG BIGVALUE
Variables are Non-Volatile (the variable loses its
SLONG SIGNED2
value when the program is loaded, but retains its
FLOAT DECIMAL
value if the controller is reset).
DOUBLE VERYBIGVALUE
DEFINE_VARIABLE
INTEGER ARRAY[3][3][3]
VALUE
VOLATILE INTEGER RESET_VAR
ARRAY[3]
ARRAY_2DIM[4][6]
INTEGER INT_ARRAY[6]

NetLinx Programming Language Reference Guide 5


NetLinx Programming Overview

DEFINE_CALL (Subroutines)
Axcess Language NetLinx Language
Axcess provides two methods for incorporating sub- Like Axcess, NetLinx supports DEFINE_CALL and
routines into your program. SYSTEM_CALL. NetLinx also supports functions, which
• DEFINE_CALL subroutines are defined in the are similar to a DEFINE_CALL(s). They can be used
program and support parameter passing into the standalone or in-line as an expression.
call. Changing the parameter value inside the call Functions are defined in the DEFINE_CALL section of
changes the value of the variable passed to the the code as a global function.
parameter. The DEFINE_CALL can use global Defining a function differs slightly from a DEFINE_CALL:
variables or defined local variables.
• The data type of the function's return value must be
DEFINE_CALL is for standalone statements and specified.
cannot be used in-line as an expression.
• The function name is not enclosed with quotes or case
• SYSTEM_CALL is an externally defined subroutine sensitive.
with a '.LIB' extension. SYSTEM_CALL programs
DEFINE_CALL 'SWITCH' (CARD,IN,OUT)
are produced by AMX and are available on
CD-ROM and on the Tech Support Web site at {
www.amx.com. SEND_STRING CARD,
"ITOA(IN),'*',ITOA(OUT),'!'"
DEFINE_CALL 'SWITCH' (CARD,IN,OUT)
}
{
SEND_STRING CARD, DEFINE_FUNCTION INTEGER MULTIPLY
"ITOA(IN),'*',ITOA(OUT),'!'" (INTEGER X, INTEGER Y)
} {
DEFINE_CALL 'MULTIPLY' (X,Y,RESULT) RETURN (X * Y)
{ }
RESULT = X * Y DEFINE_PROGRAM
} PUSH[TP,11]
DEFINE_PROGRAM {
PUSH[TP,11] CALL 'SWITCH' (SWITCHER,4,1)
{ }
CALL 'SWITCH' (SWITCHER,4,1) PUSH[TP,12]
} {
PUSH[TP,12] VALUE = MULTIPLY(3, 4)
{ }
CALL 'MULTIPLY' (3,4,VALUE) SYSTEM_CALL [1] 'VCR1'
} (VCR,TP,21,22,23,24,25,26,27,28,0)
SYSTEM_CALL [1] 'VCR1'
(VCR,TP,21,22,23,24,25,26,27,28,0)

6 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

DEFINE_START
Axcess Language NetLinx Language
DEFINE_START sets the initialization parameters for There is no difference between the way Axcess and
the Axcess program. This section defines buffers, NetLinx handle the DEFINE_START section of the pro-
levels, sets communication settings, and initializes gram; however, the role of the DEFINE_START section
variables. is greatly reduced. Variable initializations are handled in
DEFINE_START is run once when the program is the DEFINE_VARIABLE section. Device initializations
loaded or the system is reset. are handled with a DATA_EVENT in the DEFINE_EVENT
section.
DEFINE_START
DEFINE_START
CREATE_BUFFER TP, TP_BUFFER
CREATE_LEVEL VOL, 1, VOL_LEVEL1 ON[CLEAR_TO_SEND]
SEND_COMMAND SWT,
'SET BAUD 9600,N,8,1,DISABLE'
ON[CLEAR_TO_SEND]

DEFINE_EVENT
Axcess Language NetLinx Language
Axcess does not support events. Events are a new process in NetLinx. The events thread
runs parallel to the mainline thread. Events describe cer-
tain types of conditions within the control system. If the
conditions are defined as a DEFINE_EVENT, the event
code is run and mainline is bypassed.
There are five different types of events: Button Events,
Channel Events, Data Events, Level Events, and Time-
line Events.
DEFINE_EVENT
BUTTON_EVENT[TP,21]
(* KC REPEAT 'A' *)
{
PUSH:
{SEND_STRING KC, 'A'
}
RELEASE:
{
}
HOLD[5,REPEAT]:
{
SEND_STRING KC, 'A'
}
}

NetLinx Programming Language Reference Guide 7


NetLinx Programming Overview

DEFINE_PROGRAM
Axcess Language NetLinx Language
The DEFINE_PROGRAM or mainline section of the The DEFINE_PROGRAM or mainline section of the
Axcess program is where most of the programming NetLinx program and the DEFINE_EVENTS section of
process takes place. Axcess supports 99 reserved code are responsible for processing events in a NetLinx
identifiers or keywords. 83 of these keywords can be system. NetLinx has expanded the list of keywords to
used in the mainline. 194 reserved identifiers. NetLinx also supports loops,
Axcess runs through a loop where: data conversions, string processing, and file handling.

• The AXlink bus is queried for any changes. NetLinx handles mainline in a similar fashion to Axcess,
with a couple of differences. Because NetLinx supports
• Mainline code is run.
multiple bus formats (AXlink, ICSNet, and Ethernet),
• Axcess checks the wait stack and the pulse stacks events and changes in bus status are handled through a
for any expired waits and pulses. connection manager and message queue. NetLinx
• The process is repeated. checks the message queue to see if an event is defined
for the message. If not, NetLinx makes a pass through
mainline. When NetLinx finishes the event handler or
mainline, NetLinx processes the Wait list and Pulse list,
and returns to the message queue to start the process
again.

Operators
NetLinx added several operators to the language consistent with C++ programming. In conditional
statements (True or False statements), the double equal signs (==) can be used to evaluate whether two
statements are equal. The double equal signs perform the same function as a single equal sign.
There are two Bitwise operators:
Shift Left shifts the bits of a value to the left n binary positions or effectively multiplies the
value by 2n, where n is the number of places to shift. Shift Left is designated by a double less-
than sign (<<) or the LSHIFT keyword.
Shift Right shifts the bits of a value to the right n binary positions or effectively divides the
value by 2n, where n is the number of places to shift. Shift Right is designated by a double
greater-than sign (>>)or the RSHIFT keyword.
An example of both is shown below.
X = 1
Y = 8
X = X << 2 (* X is now equal to 4 *)
Z = Y >> 3 (* Z is now equal to 1 *)

NetLinx also includes value increment and decrement operators. These operators with variables as
statements work just like an Assignment operator or the equal sign does. The Increment-by-One operator
or double plus sign (++) increments the value of its variable by one. The
Decrement-by-One operator or double minus sign (--) decrements the value of its variable by one.
An example of value increment and decrement operators is shown below.
X = 1
Y = 5
X++ (* X is now equal to 2 *)
Y-- (* Y is now equal to 4 *)X = Y++(* This is not a legal statement *)

8 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

Axcess/NetLinx Incompatibility
According to previous versions of each of their language reference manuals, Axcess and NetLinx each
give the operator NOT highest precedence while giving AND and OR lowest. As demonstrated in the
following code, however, the two systems behave differently. In reality, Axcess gives the operator NOT
lowest precedence.
DEFINE_VARIABLE
C D E
DEFINE_CALL 'GO' (A,B)
{
C = !A && B
D = B && !A
E = !B && !A
}
DEFINE_PROGRAM
PUSH[1,1]
CALL 'GO' (0,0)
PUSH[1,2]
CALL 'GO' (1,0)
PUSH[1,3]
CALL 'GO' (0,1)
PUSH[1,4]
CALL 'GO' (1,1)

Axcess RESULTS
A B !A && B B && !A !B && !A
0 0 1 0 1
1 0 1 0 1
0 1 1 1 0
1 1 0 0 1

NETLINX RESULTS
A B !A && B B && !A !B && !A
0 0 0 0 1
1 0 0 0 0
0 1 1 1 0
1 1 0 0 0

The problem applies whether A and B are channels, variables, or expressions, and for OR as well as AND.
To solve the problem, AMX always recommends the use of (!A) && B instead of !A && B; however,
and this is critical, some programs out there are taking advantage of the logic flaw. Where the Axcess
programmer intended the truth table of !(A && B) he/she may have coded !A && B and gotten the
desired result. If these systems are converted to NetLinx Masters, the logic will not work as desired.
Please be aware of this difference as you support programs being converted from Axcess to NetLinx.
When it occurs, Axcess-like operation can generally be achieved by including all the conditions to the
right of the NOT in a single set of parentheses. For example:
IF (SYSTEM_POWER && ![VCR,PLAY] || [VCR,RECORD])

becomes:
IF (SYSTEM_POWER && !([VCR,PLAY] || [VCR,RECORD]))

NetLinx Programming Language Reference Guide 9


NetLinx Programming Overview

Data Types
NetLinx expanded the types of data handled beyond the 8-bit and 16-bit integers handled by Axcess.
NetLinx supports integers up to 32-bits and signed values to allow positive and negative values. The
following table lists the data types available to NetLinx.
Data Types Supported by NetLinx
Type Used to Store Data Ranges Sample of Stored Values
Names
CHAR Single byte values and character 0 to 255 (8-bit) 'a', 145, $FE, 'The quick gray fox'
strings
WIDECHAR Wide character strings dealing with 0 to 65,535 (16-bit) "'OFF',500"
Unicode fonts that use 16-bit character
codes (and most Far-eastern fonts)
INTEGER Default variable value to store values 0 to 65,535 (16-bit) 512, 32468, 12
up to 65,535
SINTEGER Signed integer values both greater 32,767 to 32,767 24, -24, 568, -568
than and less than zero (16-bit)
FLOAT Small real numbers with 5 digits of 10e-38 to 10e38 1.2345
precision 123.451.2345e5
-16.323.1415
DOUBLE Large real numbers with 15 digits of 10e-308 to 10e308 1.23456789012345
precision 12,345,678.9012545
3.14159265358979
-0.048512934
LONG Stores large integer values esp. 0 to 4,294,967,295 1,000,000
greater than 65,535 (32-bit) 2,000,046
SLONG Signed large integer values less than - -2,147,483,647 to -1,000,000
32,767 and greater than 32,767 2,147,483,647 1,000,000-2,000,000
(32-bit)
2,000,000

Constants
The DEFINE_CONSTANT section in NetLinx is similar to the DEFINE_CONSTANTS section in Axcess.
The scope of the constant extends throughout the module in which it is defined. If the
DEFINE_CONSTANT section appears in the main program or in an include file, the constant's scope
extends globally throughout the program. DEFINE_CONSTANT accepts data in these formats:
DEFINE_CONSTANT Data Formats
Types Formats Examples
Decimal Integer 0000 1500
Hexadecimal Integer $000 $DE60
Binary Integer 000b 01110011b
Floating Point 000.0 924.5
Exponential Notation 0.0e0 .5e-12
Character 'c' or <char code> 'R' or 255
String Literal 'ssss’ 'Reverse'

The standard format for DEFINE_CONSTANT is:


<constant name> = <constant expression>

10 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

NetLinx allows variables to be defined as constants in the DEFINE_VARIABLE section of the program
or module, and in the LOCAL_VAR section of a DEFINE_CALL or a DEFINE_FUNCTION. Assigning
constants is consistent with C++ programming conventions.

Variables
The role of the DEFINE_VARIABLE section is enhanced for NetLinx. The structure of a variable
definition is:
[NON_VOLATILE|VOLATILE][CONSTANT][<type>]<variable name> [= <value>]

NetLinx handles variables just like Axcess. NetLinx defaults non-array variables to the integer data types
and defaults array variables to character data type array. The variable must be explicitly declared if using
any other data type.
The NON_VOLATILE and VOLATILE keywords specify what happens to a variable when the program is
downloaded or after a system reset.
NON_VOLATILE variables (the default) lose their values when the program is downloaded, but
retain their values when the system resets.
VOLATILE variables lose their values when the system is loaded and after the system resets.
If you initialize a VOLATILE variable in the DEFINE_VARIABLE section, the variable initializes every
time the code is loaded or after a system reset. The variable initializes like it would in the
DEFINE_START section. If you initialize a NON_VOLATILE variable within the DEFINE_VARIABLE
section, the variable only initializes when the system is loaded, and it retains any changed values after
system resets.
Variables can now be defined as constant variables. Since the DEFINE_CONSTANT section does not
allow you to explicitly declare a constant's data type, using the CONSTANT keyword allows you to
explicitly declare the data type of a constant, and to define constant values for structures and arrays of
structures.
CONSTANT STR_TV CHAN_5 = {'KXAS', 5}
CONSTANT SINTEGER ABS_ZERO = -273

With Axcess, the DEFINE_CALL section allowed you to define local variables with the LOCAL_VAR
keyword. NetLinx expands the scope of LOCAL_VAR beyond the DEFINE_CALL section of code. Local
variables now come in two flavors:
LOCAL_VAR now defines a static (fixed) local variable (the next time a DEFINE_CALL is
called, the last value of the LOCAL_VAR will be in memory unless the variable is initialized).
This is how Axcess handles variables defined with LOCAL_VAR. NetLinx does not limit
LOCAL_VAR definitions strictly to the DEFINE_CALL section. LOCAL_VAR definitions can
appear within any statement block. This includes (but is not limited to) DEFINE_FUNCTION,
DEFINE_EVENT, WHILE statements, WAIT statements, etc.
STACK_VAR defines a non-static local variable. STACK_VAR defines local variables the same
way as LOCAL_VAR, and like LOCAL_VAR, STACK_VAR can appear in any statement block.
The difference is that the value stored in the variable is initialized to zero whenever the
statement block is called, and the value is destroyed when the statement block is finished. The
structure for LOCAL_VAR and STACK_VAR variables include:
LOCAL_VAR [NON_VOLATILE | VOLATILE] [CONSTANT] [<type>] name [= <value>]STACK_VAR
[<type>] name [= <value>]

NetLinx Programming Language Reference Guide 11


NetLinx Programming Overview

Persistent Variables
Persistent variables have been implemented in the second release of NetLinx. Persistent variables are
NetLinx program variables that maintain their value between updates to the NetLinx program. The user
can define a variable to be persistent using the PERSISTENT storage modifier as show below:
PERSISTENT CHAR cMyString[100]

All persistent variables are automatically non-volatile. It is not legal to define a variable as VOLATILE
and PERSISTENT.
When a NetLinx program has a persistent variable declared, subsequent downloads of new NetLinx
programs containing the same persistent variable will retain the variable settings. By default, non-
persistent variables are set to zero after a NetLinx program download. Persistence overrides this behavior
by setting the variable in the newly downloaded program to be the same as it was before the download.
Typically, persistent variables are used for saving preset information. Suppose you have a system that
contains several PosiTrack camera positioning systems, and that the user interface to the system allows
the user to set the position of any of the cameras and record that position for recalling later. The position
presets are stored in a non-volatile array variable so they are maintained during a power cycle. Without
persistent variables, an update to the NetLinx program would zero out all of the presets the user had
stored. With persistent variables, the new NetLinx program can be downloaded and all of the presets
remain intact.
When a new NetLinx program is downloaded to the Master, the Master iterates through all non-volatile
variables from the new program looking for persistent ones. When it finds a persistent variable in the
new program, it searches the old programs persistent variable space for the same variable. When it finds
the same variable, the value of the new variable is set to the same value as the old variable. The Master
identifies the same variable by verifying the following:
Variable name
Variable source location
Variable type
Therefore, in order for persistence to function properly the name, type, and file location declared must be
the same as the previously downloaded NetLinx program. If you changed any of the three, the new
persistent variable will not be set with the old variable's value.

Arrays
Arrays are the most common way of combining a number of data items into a single unit. Axcess uses
three methods to store data in arrays:
8-bit single dimensional arrays
16-bit single dimensional arrays
8-bit two-dimensional arrays
Axcess arrays are limited to storing 255 elements per dimension. Axcess does not allow you to store
two-dimensional arrays as constants; instead, you set and initialize a two-dimensional array in the
DEFINE_START section. You are responsible for maintaining the integrity of the initialized value.
NetLinx enhances the handling of arrays. You can define arrays of any data type in single and multi-
dimensional arrays. You can define arrays of structures, initialize arrays within the DEFINE_VARIABLE
section, and define arrays as constants.
NetLinx handles arrays similar to C++, except that the first index value of the array is 1 rather than an
index of 0 used by C++. With array initialization you don't need to count how many items are initialized.
These definitions are functionally the same:

12 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

CHAR TV_CHAN[11] = {2, 3, 4, 5, 8, 11, 13, 21, 27, 33, 39}


CHAR TV_CHAN[] = {2, 3, 4, 5, 8, 11, 13, 21, 27, 33, 39}

Multi-dimensional arrays allow multiple collections of data. NetLinx allows up to five array dimensions;
array size is limited only by available memory. A two-dimensional array is a collection of single
dimensional arrays. Three-dimensional arrays are collections of two-dimensional arrays. Here are
examples of multi-dimensional arrays:
INTEGER NUM1D[10] (* [COLUMN] *)
INTEGER NUM2D[5][10] (* [ROW][COLUMN] *)
INTEGER NUM3D[2][5][10] (* [TABLE][ROW][COLUMN] *)

NUM3D[1] refers to the 1st table


NUM3D[1][4] refers to the 4th row of the 1st table
NUM3D[1][3][7] refers to the 7th column of the 3rd row of the 1st table

CHAR NAME[16] (* [PRESET NAME] *)


CHAR PRESET[10][16] (* [PRESET NUM][PRESET NAME] *)
CHAR USER_PRESET[10][10][16] (* [USER][PRESET NUM][PRESET NAME] *)

CHAR USER_PRESET[10][10][16] allows you to define tables that can store ten 16-character preset
names for ten users. With Axcess, you would either store ten two-dimensional arrays or index one two-
dimensional array (USER_PRESET[100][16]). For example, the fifth user would occupy
USER_PRESET[41] through USER_PRESET[50].
It is sometimes difficult for people to envision multi-dimensional arrays beyond three-dimensions. We
sometimes try to define the arrays spatially, as in a three-dimensional array. If we take the approach of
cascading arrays, it is easier to understand. Using the previous example of defining user presets, you can
expand the array to five dimensions by classifying the preset name by location and department. For
example: AMX has three domestic locations; each location has a sales team, a professional services team
and a tech support team; each team has a maximum of ten employees; each employee has the ability to
store 10 preset names; each preset name can have up to 16 characters. The array would look like this:
CHAR USER_PRESET[3][3][10][10][16]
(*[LOCATION][DEPT][USER][PRESET][NAME]*)

NetLinx has a new set of functions to better deal with arrays. LENGTH_ARRAY and
MAX_LENGTH_ARRAY determine the effective length and defined length of an array. When used with
multi-dimensional arrays, LENGTH_ARRAY and MAX_LENGTH_ARRAY return the lengths associated
with the level of the array supplied as the argument. For example:
INTEGER NUM_LIST [10] = {1, 2, 3, 4, 5}
LEN = MAX_LENGTH_ARRAY (NUM_LIST) (* LEN = 10 *)
LEN = LENGTH_ARRAY (NUM_LIST) (* LEN = 5 *)
INTEGER NEW_LIST[] = {10, 20, 30, 40}
LEN = MAX_LENGTH_ARRAY (NEW_LIST) (* LEN = 4 *)
LEN = LENGTH_ARRAY (NEW_LIST) (* LEN = 4 *)
INTEGER MULTI_LIST[4][10] = { {1, 2, 3}, {4, 5, 6, 7}, {8, 9} }
LEN = MAX_LENGTH_ARRAY (MULTI_LIST[2]) (* LEN = 10 *)
LEN = LENGTH_ARRAY (MULTI_LIST[2]) (* LEN = 4 *)
LEN = MAX_LENGTH_ARRAY (MULTI_LIST) (* LEN = 4 *)
LEN = LENGTH_ARRAY (MULTI_LIST) (* LEN = 3 *)

NetLinx Programming Language Reference Guide 13


NetLinx Programming Overview

NetLinx expands the capabilities of the assignment operator '=' to support arrays. Similar array levels are
assigned to another array using the '=' operator, if the arrays match the number of dimensions and the
data type of the array. You cannot assign a two-dimensional long array to a one-dimensional character
array. The MAX_LENGTH_ARRAY of the array to the left of the '=' operator must be greater than or equal
to the LENGTH_ARRAY of the array to the right of the '=' operator.
INTEGER ARRAY1[10] = {1, 2, 3, 4}
INTEGER ARRAY2[10] = {5, 6, 7}
INTEGER ARRAY3[10]
INTEGER DIM2ARRAY1[3][4] = { {1, 2, 3}, {4, 5, 6} }
INTEGER DIM2ARRAY2[3][4] = { {7, 8, 9} }
INTEGER DIM2ARRAY3[3][4]
ARRAY3 = ARRAY1 (* ARRAY3 = {1, 2, 3, 4} *)
DIM2ARRAY2[2] = ARRAY1 (* DIM2ARRAY2 = { {7, 8, 9}, {1, 2, 3, 4} } *)
DIM2ARRAY3 = DIM2ARRAY1 (* DIM2ARRAY3 = { {1, 2, 3}, {4, 5, 6} } *)

Structures
Arrays are limited by their inability to have multiple data-types within one array. NetLinx supports
Structures to remove this limitation. Structures group different data types together as one data unit.
Structures also group arrays of structures together so that each element of the array contains all of the
elements of the structure. This may sound complex, but it is actually very familiar.
A database table is an array of structures. The database table is an array of records. Each record is a
structure. Each record contains data of different types. Let's first consider the elements of a database
table. We then show how to define the structure and create a variable that uses the data structure in an
array. We show how to access the individual elements of the structure.
Employee Number (* INDEX - Integer Value *)
Employee National Insurance Number (* National Insurance Number - Long *)
Employee First Name (* First Name - Character Array *)
Employee Last Name (* Last Name - Character Array *)
Contribution to Pension (* Contribution in % - Float *)

The DEFINE_TYPE section is added to the basic structure of a NetLinx Program. Structures are defined
within the DEFINE_TYPE section. The DEFINE_TYPE section appears between the
DEFINE_CONSTANT section and the DEFINE_VARIABLE section. Since structures cannot be used
within the DEFINE_CONSTANT section but must be declared before they are used within the
DEFINE_VARIABLE section, placing DEFINE_TYPE between DEFINE_CONSTANT and
DEFINE_VARIABLE is the logical location.
The attributes NON_VOLATILE, VOLATILE, and CONSTANT do not apply to the individual data
elements of the structure, but can be attributed to the instances of the structure as defined in the
DEFINE_VARIABLE section.
The standard format for structures is:
STRUCTURE <name>
{
[<type>] <data1>
[<type>] <data2>
.
.
}

Using this format, we define our 'employee' structure in the DEFINE_TYPE section:

14 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

DEFINE_TYPE
STRUCTURE EMP
{
INTEGER EMP_NUM
CHAR NI_NUM[9]
CHAR F_NAME[16]
CHAR L_NAME[16]
FLOAT CONT_PENSION
}

Then, within the DEFINE_VARIABLE section, you create an instance of the structure and an array of
the structure as follows:
DEFINE_VARIABLE
EMP JOHN_DOE
EMP AMX_EMP[1000]

Within the program, we use the information stored within the structure and assign information to the
structure in the following manner:
JOHN_DOE.EMP_NUM = 101
JOHN_DOE.NI_NUM = ’155426367’
JOHN_DOE.F_NAME = ’JOHN’
JOHN_DOE.L_NAME = ’DOE’
JOHN_DOE.CONT_PENSION = 0.01

EMP_INDEX = JOHNDOE.EMP_NUM (* EMP_INDEX = 101 *)


AMX_EMP[101] = JOHNDOE
(* AMX_EMP[101] = {101, '155426367', 'JOHN', 'DOE',
0.01}*)
AMX_EMP[60].EMP_NUM = 60
AMX_EMP[60].F_NAME = 'BOB'

Other uses for arrays of structures include channel listings, speed-dial lists, and user password lists.
Data sets
NetLinx predefines several structures designed to work with NetLinx device numbers, channels, and
levels. Data sets allow you to group and combine certain elements of NetLinx devices. There are three
data set structures supported by NetLinx:
DEV (Device Sets)
DEVCHAN (Device-Channel Sets)
DEVLEV (Device-Level Sets)
You have already seen the structure DEV structure in the DEFINE_DEVICE section. If we were to define
the structure DEV in the DEFINE_TYPE section, it would look like this:
STRUCTURE DEV
{
INTEGER DEVICE
INTEGER PORT
INTEGER SYSTEM
}

NetLinx Programming Language Reference Guide 15


NetLinx Programming Overview

The actual instancing of the structure is unique to the DEV structure because you separate the individual
structure's elements with colons (:) instead of enclosing the structure with braces {} and separating the
elements with commas (,). For example:
DEV PANEL_A = 128:1:0 (* correct *)
DEV PANEL_B = {128, 1, 0} (* wrong *)

Using the DEV structure, you create the structures DEVCHAN and DEVLEV like this:
STRUCTURE DEVCHAN
{
DEV DEVICE
INTEGER CHANNEL
}
STRUCTURE DEVLEV
{
DEV DEVICE
INTEGER LEVEL
}

DEVCHAN and DEVLEV instance and initialize similarly to other NetLinx structures:
DEV PANEL_A = 192:1:0
DEV PANEL_B = 129:1:0
DEVCHAN BUTTON_A = { PANEL_A, 1 }
DEVCHAN BUTTON_B = { 128:1:0, 2 }
DEVLEV LEVEL_1 = { PANEL_A, 1 }
DEVLEV LEVEL_2 = { 128:1:0, 2 }

DEV, DEVCHAN, and DEVLEV are structures built into the NetLinx language. You can do more with DEV,
DEVCHAN, and DEVLEV than you could with structures you create within the code.
DEV PANEL_GROUP1[] = { 128:1:0, 129:1:0, 130:1:0 }
DEV MSP_GROUP[5] = { MSP1, MSP2, MSP3 }
DEVCHAN PRESET1_BUTTONS[5] = { {TP1, 21}, {MSP1, 1}, {134:1:0, 1} }
DEVLEV VOL1_LEVEL[] = { {TP1, 1}, {MSP1, 1}, {192:1:0, 1} }

You can use the structures and arrays of the structures within many commands and situations where you
would use a device number, a device and channel combination, or a device and level combination. These
data sets allow you to combine devices, devices and channels, and devices and levels without using the
DEFINE_COMBINE or DEFINE_CONNECT_LEVEL sections. This gives you the ability to combine
certain pages of panels or to combine panels under certain conditions. In Axcess, once the panels were
combined you were locked into that system configuration.
Instead of writing the following statements:
PUSH[MSP1, 1]
PUSH[MSP2, 1]
PUSH[MSP3, 1]
[RELAY, 1] = ![RELAY, 1]
[MSP1, 1] = [RELAY, 1]
[MSP2, 1] = [RELAY, 1]
[MSP3, 1] = [RELAY, 1]

You can use device sets or channel sets to accomplish the same functionality:

16 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

PUSH[MSP_GROUP,1] (* MSP_GROUP IS A DEV SET *)


[RELAY, 1] = ![RELAY, 1]
[MSP_GROUP, 1] = [RELAY, 1]

- or -

PUSH[MSP_PRESET1] (* MSP_PRESET1 IS A DEVCHAN SET *)


[RELAY,1] = ![RELAY, 1]
[MSP_PRESET1] = [RELAY, 1]

Conditionals & Loops


Axcess supports two types of conditional statements and three types of loops:
Conditional statements:
IF...ELSE statements

SELECT...ACTIVE statements
Loops:
WHILE statements

MEDIUM_WHILE statements

LONG_WHILE statements
NetLinx supports:
Conditional statements:
IF...ELSE statements

SELECT...ACTIVE statements

SWITCH...CASE statements
Loops:
FOR statements

WHILE statements
LONG_WHILE statements
MEDIUM_WHILE statements are obsolete in NetLinx due to eliminating the timeout of WHILE loops.
LONG_WHILE loops now differ from WHILE loops in the way input change notifications are processed
during the programming loop. WHILE, MEDIUM_WHILE and LONG_WHILE statements are all still
accepted syntax to provide compatibility with existing Axcess programs.
SWITCH...CASE statements
NetLinx adds the SWITCH...CASE conditional statements. The SWITCH...CASE statements provide
selective execution of code blocks evaluated by a single condition. The value of the SWITCH expression
is tested against each CASE value (which must be a numeric constant or a string literal). If a match is
found, the statements associated with the CASE are executed. All other CASE statements are ignored. If
no match is found, the DEFAULT case statements (if any) are executed. The SWITCH expression is
evaluated only once.
The following rules apply to SWITCH...CASE statements:

NetLinx Programming Language Reference Guide 17


NetLinx Programming Overview

Only the statements associated with the first case that matches the value of the expression are
executed. Multiple CASE statements can be stacked within the SWITCH...CASE statement. If
the value matches one of the CASE statements, the statements associated with the stack will be
executed.
If no CASE matches the SWITCH expression, then the statements under the default case (if
available) are executed. The default statement must be the last case within the
SWITCH...CASE, otherwise the remaining case statements will not execute.
All cases must be unique.
Braces should be used to bracket the statements in a case. They are required only if variables
are declared within the case.
The BREAK statement applies to the SWITCH and takes execution to the end of the SWITCH.
Unlike C and C++, cases do not fall through to the next case if a break is not used. Because of
this, BREAK statements are not required between cases.
The following is the structure for the SWITCH...CASE statement:
SWITCH (<expression>)
{
CASE <numeric constant or string literal>:
{
(* statements for CASE 1 *)
}
CASE <numeric constant or string literal>:
{
(* statements for CASE 2 *)
}
CASE <numeric constant or string literal>:
{
(* statements for CASE n; there can be as many cases as necessary *)
}
DEFAULT <numeric constant or string literal>:
{
(* statements for DEFAULT case *)
}
}

FOR loops
FOR loops are an alternative to traditional loops. Functionally they do the same thing, but FOR loops are
more readable. FOR loops, like WHILE loops, do not process input changes from the message buffer. The
structure for a FOR loop is shown below:
FOR (<INITIAL>;<condition>;<after pass>)
{
(* loop statements *)
}

18 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

Parameters:

<INITIAL> Contains one or more statements that are executed one time before any
FOR loop statements are executed; each statement must be separated by a
comma (,).

<condition> The condition for which the loop is evaluated before each pass. If the condi-
tion evaluates TRUE, the FOR loop statements execute. If the condition eval-
uates FALSE, the loop terminates.

<after pass> Contains one or more statements that are executed after each pass through
the loop statements; each statement is separated by a comma (,). This is
typically a statement that increments the FOR-loop index.

The number of loop executions is usually stated at the beginning of the loop, unlike WHILE and
LONG_WHILE loops.
In Axcess, a typical loop may look something like this:
COUNT = 0
WHILE (COUNT<10)
{
COUNT = COUNT + 1
(* loop statements *)
}

In NetLinx you can write the same loop with a FOR statement and clarify how the loop operates:
FOR (COUNT=0 ; COUNT<10 ; COUNT++)
{
(* loop statements *)
}

By defining the loop like this, you clearly see how it is initialized and incremented. No errors appear if
you forget to initialize the WHILE loop or counter. The FOR loop helps to insure proper structure.

Functions
Axcess only supports one method to create subroutines: DEFINE_CALL. The DEFINE_CALL does not
return values very eloquently. If you pass a variable to a parameter of the DEFINE_CALL and then
change the parameter value within the subroutine, the program updates the value of the global variable in
the mainline code.
NetLinx has two methods for creating subroutines: DEFINE_CALL and DEFINE_FUNCTION.
DEFINE_CALL
DEFINE_CALL is intended to run segments of code that are repeated throughout the program, but don't
require a return value. For example, this DEFINE_CALL creates a macro to lower a screen, turn on the
projector, and set the lights to Preset 1. The subroutine executes three commands and no values are
returned to the program.
DEFINE_CALL 'PRESENTATION MACRO'
{
SYSTEM_CALL [1] 'SCREEN1' (0, 0, 1, 0, SCREEN, 1, 2, 3, 0)
SEND_STRING VPROJ, "'PON',$0D,$0A"
SEND_STRING RADIA, "'1B',$0D"
}

NetLinx Programming Language Reference Guide 19


NetLinx Programming Overview

The NetLinx compiler passes all variables by reference. This means that the variable the subroutine
operates on is the same variable the caller passed. Any change made to the variable, passed as a calling
parameter, updates the variable's value from the caller's perspective. You can take advantage of this pass
by reference feature by returning an updated value through a calling parameter rather than as the return
value.
Constants, on the other hand, are passed by value. When this happens, a copy of the parameter is
delivered to the subroutine. Any change made to the variable representing the constant is lost once the
function or subroutine is lost.
To specify an array as a function or subroutine parameter, one set of brackets for each array dimension
must follow the variable name, as shown in the following example:
DEFINE_CALL 'READ INPUT' (CHAR BUFFER[][])
{
(* body of the subroutine *)
}

The parameter BUFFER is declared to be a two-dimensional array by including two sets of brackets after
the name. For compatibility with existing programs, the array dimensions may be specified inside the
brackets. These dimensions, however, are not required and are ignored by the compiler. The NetLinx
Interpreter will do bounds checking on the array and generate a run-time error if the array bounds are
exceeded.
DEFINE_FUNCTION
DEFINE_FUNCTION provides a way to return a value to a statement. It has the same functionality as a
DEFINE_CALL. The DEFINE_FUNCTION is used inline in a statement, where a DEFINE_CALL must be
used as a standalone statement. The basic structure is:
DEFINE_FUNCTION [<return type>]<name>[(<param1>,<param2>, … <parameN>)]
{
(* statements *)
}

The following DEFINE_FUNCTION creates a subroutine to cube a number and returns a LONG integer
value:
DEFINE_FUNCTION LONG CUBEIT (LONG VALUE)
{
STACK_VAR RESULT
RESULT = VALUE * VALUE * VALUE
RETURN RESULT
}
DEFINE_PROGRAM
PUSH[TP1, 1]
{
CUBED_VAL = CUBEIT ( 3 )
(* CUBED_VAL = 27 *)
}

20 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

Events
Axcess is a linear environment. All interactions between external devices and the master processor are
handled within mainline code. The processor runs mainline code, services the wait and pulse queues, and
checks the bus for any changes in device status. We view these interactions or changes in status as
Events, which fall into one of four categories: Button Events, Channel Events, Data Events, and Level
Events.
NetLinx has a special program section called DEFINE_EVENT to handle incoming events. The event
processing that previously could only occur within mainline code can now be handled in the
DEFINE_EVENT section.
NetLinx maintains a table of defined event handlers. When a new event comes into the NetLinx
processing queue, the event is compared against the table of events. If the event is found, only the code in
the event definition is evaluated and executed; mainline is bypassed. If an event handler is not defined,
mainline is run and the event is evaluated against the mainline code. This provides a more efficient
mechanism for processing events, since mainline is not required to process a single
I/O request. If no events are pending, mainline is run. Mainline becomes an idle time process.
With the addition of the DEFINE_EVENT section for processing events, the mainline's role in NetLinx
becomes greatly diminished, if not totally eliminated. Programs can still be written using the traditional
technique of processing events and providing feedback in mainline code; however, programs written
using the event table structure will run faster and be much easier to maintain.
Button Events
Events associated with a button on a touch panel or an AXD-MSP32 will fall into one of three
categories:
What happens when the button is pushed.
What happens when the button is released.
What happens if the button is held.
The structure for Button Events is as follows:
BUTTON_EVENT [<device>,<channel>]
{
PUSH:
{
(* push event handler code *)
}
RELEASE:
{
(* release event handler code *)
}
HOLD [<time>,[REPEAT]]
{
(* hold event handler code *)
}
}

The [<device>, <channel>] declaration can contain a DEV device set, or a DEVCHAN device-
channel set in addition to individual device and channel declarations. The HOLD event specifies the
actions to be performed when a button is pressed and held for a minimum length of time indicated by the
<time> parameter, which is specified in tenth seconds.

NetLinx Programming Language Reference Guide 21


NetLinx Programming Overview

The following is an example of how a block of existing Axcess code can be rewritten using the NetLinx
BUTTON_EVENT handler. The code below will send an 'A' to an RS-232 port defined as KC1 upon a
button push and will repeat the 'A' string every 0.5 seconds until the button is released.
Axcess Language NetLinx Language
DEFINE_PROGRAM DEFINE_EVENT
. .
. .
PUSH[TP1,10] BUTTON_EVENT[TP1,10]
{ {
SEND_STRING KC1, 'A' PUSH:
ON[REPEAT_KC] {
} TO[TP1,10]
RELEASE[TP1,10] SEND_STRING KC1, 'A'
{ }
CANCEL_WAIT 'REPEAT KC' RELEASE:
OFF[REPEAT_KC] {
} }
IF (REPEAT_KC) HOLD[5,REPEAT]:
{ {
WAIT 5 'REPEAT KC' SEND_STRING KC1, 'A'
SEND_STRING KC1, 'A' }
} }
[TP1,10] = REPEAT_KC .
. .
. DEFINE_PROGRAM
.
.

In addition to evaluating the push within the event handler structure, you can see the simplified logic for
creating the repeating 'A' string using the HOLD event handler.
Channel Events
Channel Events are similar to Button Events. Channel Events are generated by ON, OFF, PULSE, TO, or
MIN_TO. The format for a Channel Event is shown below:
CHANNEL_EVENT[<device>,<channel>]
{
ON:
{
(* on event handler code *)
}
OFF:
{
(* off event handler code *)
}
}

Like Button Events, the [<device>, <channel>] declaration can contain a DEV device set, or a
DEVCHAN device-channel set in addition to individual device and channel declarations.
In the following example, a Channel Event is defined to turn off a video projector every time the
projector lift is raised. In Axcess, you need to include the code to turn off the projector whenever the
projector lift is raised. In NetLinx, you define a Channel Event for the 'Projector Lift Up' relay and tell
the system to turn off the projector every time this relay is turned on. Since turning on or pulsing the
relay does not produce a push, a Button Event is not generated.

22 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

Here is the existing Axcess Code:


DEFINE_PROGRAM
.
.
PUSH[TP1,21] (* LIFT UP BUTTON *)
{
PULSE[RELAY,LIFT_UP]
PULSE[VPROJ,VP_POWER_OFF]
}
PUSH[TP1,22] (* SYSTEM OFF BUTTON *)
{
PULSE[RELAY,RACK_OFF]
PULSE[RELAY,LIFT_UP]
PULSE[VPROJ,VP_POWER_OFF]
}
.
.

NetLinx Channel Event:


DEFINE_EVENT
.
.
BUTTON_EVENT[TP1,21] (* LIFT UP BUTTON *)
{
PUSH:
{
PULSE[RELAY,LIFT_UP]
}
}
BUTTON_EVENT[TP1,22] (* SYSTEM OFF BUTTON *)
{
PUSH:
{
PULSE[RELAY,RACK_OFF]
PULSE[RELAY,LIFT_UP]
}
}
CHANNEL_EVENT[RELAY,LIFT_UP] (* LIFT UP RELAY EVENT *)
{
ON:
{
PULSE[VPROJ,VP_POWER_OFF]
}
}

NetLinx Programming Language Reference Guide 23


NetLinx Programming Overview

Data Events
Data Events provide some interesting capabilities in a NetLinx system. At first glance, it seems to be
concerned with receiving strings of data either from a serial data device such as an NXC-COM2 card or
an interface device such as a touch panel or WebLinx. While this is a valid function, DATA_EVENT has
many more capabilities and works with many devices. The structure for a DATA_EVENT is:
DATA_EVENT [<device>]
{
COMMAND:
{
(* command data event handler *)
}
STRING:
{
(* string data event handler *)
}
ONLINE:
{
(* online data event handler *)
}
OFFLINE:
{
(* offline data event handler *)
}

ONERROR:
{
(* error data event handler *)
}
}

In Axcess, strings are handled in mainline code. Between each pass through mainline, the data received
by a device is placed within a created buffer. The next pass through mainline allows the Axcess program
to evaluate the string. This has two limitations:
First, Axcess must evaluate the contents of the buffer with each pass through mainline,
whether there is data in the buffer or not. This adds to the length of mainline and slows
mainline.
Second, data is only received into the buffer between passes through mainline. In large
systems, data processing is delayed, and some buffers may be overrun and some data may be
lost.
Because the role of mainline is diminished in NetLinx and events can be processed quickly, NetLinx is
able to process data received by a DATA_EVENT in real time. When data is received, it enters the
message queue and triggers a data event. If a buffer has been created for the device, the data is placed
within the buffer and can be used by either the DATA_EVENT or mainline.
The data can be evaluated in two ways. The actual string that is received by the message queue can be
evaluated using the DATA.TEXT object within the event. The string in DATA.TEXT is also added to the
end of the device's buffer. This becomes a factor when receiving large strings, or when receiving strings
with an embedded string length or start and end characters. DATA_EVENT then evaluates the buffer to see
if the entire string has been received before processing it; however, the evaluation is done immediately

24 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

upon receipt of another chunk of data, and is only done when data is received. For example, DATA.TEXT
may equal {'over the lazy brown dog',ETX} and the DATA_BUFFER[500] might equal
{STX,'The quick gray fox jumps over the lazy brown dog',ETX}. By evaluating the
buffer value, you can evaluate the entire string at once.
Two other important aspects of the DATA_EVENT are the ONLINE and OFFLINE event handlers.
ONLINE and OFFLINE events are triggered when the master recognizes a device has come on the bus or
has dropped off the bus.
In Axcess, device initialization is primarily handled with the DEFINE_START section of code. The other
alternative was to evaluate the DEVICE_ID on each pass through mainline. If the
DEVICE_ID(<device>) equaled the DEVICE_ID of the device, the device was online. If
DEVICE_ID(<device>) equaled 0, the device was offline. Within the conditional statements, the
device could be initialized or a warning could be sent. The downfall of these approaches is that
DEFINE_START initializations are only run when the master is reset, and evaluations of the DEVICE_ID
must run with each pass of mainline and are dependent on the speed of mainline.
NetLinx handles all device initializations and offline warning through the DATA_EVENT. Since every
device triggers an ONLINE event when the master is reset, this not only ensures that the device will be
initialized on startup, but also insures that the device will be initialized any time the device comes online.
The DATA_EVENT is also evaluated on a need to know basis, rather than on each pass through mainline.
The following example shows basic code for tracking a touch panel page in Axcess. Assume that the
variables have been properly defined in the DEFINE_VARIABLE section. The DEFINE_START section
contains the creation of the buffer and the DEFINE_PROGRAM section contains the string evaluation.
Existing Axcess code:
DEFINE_START
.
.
CREATE_BUFFER TP1, TP1_BUFFER
SEND_COMMAND TP1, 'TPAGEON'
.
.
DEFINE_PROGRAM
.
.
IF (LENGTH_STRING (TP1_BUFFER))
{
SELECT
{
ACTIVE (FIND_STRING (TP1_BUFFER,'PAGE-',1)):
{
JUNK = REMOVE_STRING (TP1_BUFFER,'PAGE-',1)
CUR_PAGE = TP1_BUFFER
}
ACTIVE (FIND_STRING (TP1_BUFFER,'KEYP-',1)):
{
(* keypad code *)
}
ACTIVE (FIND_STRING (TP1_BUFFER,'KEYB-',1)):
{
(* keyboard code *)
Continued

NetLinx Programming Language Reference Guide 25


NetLinx Programming Overview

}
ACTIVE (1):
{
(* keypad code *)
}
}
}
.
.

NetLinx Data Event:


DEFINE_START
CREATE_BUFFER TP1, TP1_BUFFER
.
.
DEFINE_EVENT
..
DATA_EVENT[TP1](* EVALUATE TP1 DATA *)
{
STRING:
{
SELECT
{
ACTIVE (FIND_STRING (DATA.TEXT,'PAGE-',1)):
{
JUNK = REMOVE_STRING (DATA.TEXT,'PAGE-',1)
CUR_PAGE = DATA.TEXT
}
ACTIVE (FIND_STRING (DATA.TEXT,'KEYP-',1)):
{
(* keypad code *)
}
ACTIVE (FIND_STRING (DATA.TEXT,'KEYB-',1)):
{
(* keyboard code *)
}
ACTIVE (1):
{
(* default code *)
}
}
CLEAR_BUFFER TP1_BUFFER
}
ONLINE:
{
SEND_COMMAND TP1, 'TPAGEON'
}
}

Continued

26 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

.
.

Each event handler contains several imbedded data objects that pass data values into the event handler
code.
Level Events
Level Events are triggered by a level change on a particular device. This eliminates constantly evaluating
a level against a previous value. In Axcess, a level would need to be created in the DEFINE_START
section and a conditional statement would appear in mainline to evaluate and update the level. The
format for the LEVEL_EVENT is:
LEVEL_EVENT[<device>,<level>]
{
(* level event handler *)
}

Existing Axcess code:


DEFINE_START
.
.
CREATE_LEVEL TEMP, 1, TEMP_LEVEL
.
.
DEFINE_PROGRAM
.
.
IF (TEMP_LEVEL >= COOL_POINT)
{
ON[RELAY,FAN]
}
ELSE IF (TEMP_LEVEL <= HEAT_POINT)
{

OFF[RELAY,FAN]
}

NetLinx Level Event:


LEVEL_EVENT [ TEMP, 1 ]
{
IF (LEVEL.VALUE >= COOL_POINT)
{
ON[RELAY,FAN]
}
ELSE IF (LEVEL.VALUE <= HEAT_POINT)
{
OFF[RELAY,FAN]
}

LEVEL.VALUE is an embedded object value in the LEVEL_EVENT statement. The LEVEL.VALUE


object eliminates the need to create a level for the TEMP device.

NetLinx Programming Language Reference Guide 27


NetLinx Programming Overview

Combining Devices, Channels and Levels


Axcess allows you to combine devices and levels within the DEFINE_COMBINE and
DEFINE_CONNECT_LEVEL sections. This method is static and is fixed when the program compiles. You
can combine functionality within mainline by stacking push and release statements. Stacking pushes
allows you the flexibility to conditionally change what elements of the program share functionality, but
the program can be more difficult to maintain over time than if the panels were combined using
DEFINE_COMBINE.
NetLinx provides several new methods for combining the functionality of devices, channels, and levels.
Using DEV, DEVCHAN and DEVLEV accomplishes the same thing as stacking pushes in Axcess, and it
reduce the overall maintenance associated with stacking pushes; however, data sets are statically
implemented within the DEFINE_EVENT section. When the program compiles, the references to the data
sets in the DEFINE_EVENT are set and cannot change at run time.
Virtual devices, levels and device/channel sets
One of the drawbacks to combining devices and levels in Axcess is the way the central controller
handled the first device in the combine list going online and offline. This resulted in unexpected device
behavior and inconsistent feedback.
NetLinx uses virtual devices. Virtual devices carry a device number ranging from 32,768 to 36,863, a
port number of 1, and a system number of 0. Virtual Devices are devices that cannot be taken off the bus.
By listing a virtual device as the first device in a DEFINE_COMBINE, COMBINE_DEVICES,
COMBINE_LEVELS, or COMBINE_CHANNELS statement, the abnormalities seen in Axcess
DEFINE_COMBINE statements are eliminated.

Combining and uncombining devices


NetLinx still recognizes the DEFINE_COMBINE section. This section still operates as it did in Axcess;
however, once the DEFINE_COMBINE section has been compiled it remains static. NetLinx introduces
two functions: COMBINE_DEVICES and UNCOMBINE_DEVICES. COMBINE_DEVICES and
UNCOMBINE_DEVICES dynamically change the devices combined together. When devices are
combined the combine list and DEV set lists are reevaluated and updated during run time.
COMBINE_DEVICES and UNCOMBINE_DEVICES are used as stand-alone statements in an event,
mainline or in assignment statements. COMBINE_DEVICES and UNCOMBINE_DEVICES will return a
value of 0 or -1, depending on the success or failure of the operation. The first device in a
COMBINE_DEVICES statement should be a virtual device. The devices, listed after the virtual device, are
either a list of individual device numbers, DEV sets, or any combination of devices and DEV sets. The
UNCOMBINE_DEVICES statement requires only the first device in the COMBINE_DEVICES list, which
should be a virtual device. The format for COMBINE_DEVICES and UNCOMBINE_DEVICES is:
COMBINE_DEVICES (<virtual device>, <device1>, <device2>…)
UNCOMBINE_DEVICES (<virtual device>)

Devices combined with COMBINE_DEVICES respond like devices combined using the
DEFINE_COMBINE section. The central controller recognizes any input from the devices in the combine
list as the first device in the list.
Combining and uncombining levels
The NetLinx functions COMBINE_LEVELS and UNCOMBINE_LEVELS work similar to the
DEFINE_CONNECT_LEVEL section in Axcess. For compatibility with Axcess code, the
DEFINE_CONNECT_LEVEL section is still valid. Like COMBINE_DEVICES, COMBINE_LEVELS and
UNCOMBINE_LEVELS can be used within events and mainline code to dynamically change what levels
are connected to each other. It is also recommended that a Virtual DEVLEV set be used as the first
DEVLEV set in the COMBINE_LEVELS function. The format for COMBINE_LEVELS and
UNCOMBINE_LEVELS is:

28 NetLinx Programming Language Reference Guide


NetLinx Programming Overview

COMBINE_LEVELS (<virtual DEVLEV>, <DEVLEV1>, <DEVLEV2>…)


UNCOMBINE_LEVELS (<virtual DEVLEV>)

DEVLEV structures defined within the COMBINE_LEVELS are either individual DEVLEV structures or
one dimension of a DEVLEV array. Any reference to the levels is handled through the first device in the
list.
Combining and uncombining channels
Combining DEVCHANs is unique to NetLinx. The NetLinx function COMBINE_CHANNELS combines an
individual channel on a virtual device to one or more channels on another device (or devices). The
format for COMBINE_CHANNELS and UNCOMBINE_CHANNELS is:
COMBINE_CHANNELS (<virtual DEVCHAN>, <DEVCHAN1[]>, <DEVCHAN2[]>…)
UNCOMBINE_CHANNELS (<virtual DEVCHAN>)

String Comparisons
While in Axcess it is possible to perform a string comparison using the '?' wildcard, Netlinx requires the
COMPARE_STRING function to be used instead.

Axcess code - string comparison


IF (TIME = '12:00:??')
(* Do something at noon - evaluation is valid for an entire minute *)

Netlinx code - string comparison


IF (COMPARE_STRING(TIME,''12:00:??'))
// Do something at noon - evaluation is valid for an entire minute

Modules
There are two ways to reuse code in different Axcess programs: Include Files and System Calls.
Include files redirect the compiler to files with an .AXI extension. The .AXI files can contain
the same type of information present within an Axcess program. All data is accessible both
within the Include file and within the primary Axcess program. Include files are limited
because they are static. Mainline statements within the Include file cannot be adapted from
program to program without altering the Include file. To update the Include files in a program,
the entire program must be compiled and loaded.
System calls are external subroutines that can be instanced and referenced in the main
program. Like DEFINE_CALL subroutines, System Calls can pass parameters to adapt the
System Call to the needs of different programs. System Calls have been one of the primary
tools for creating standardized reusable blocks of code. To update the System Calls within a
program, the entire program must be compiled and loaded.
Modules are unique to NetLinx. Like Include files, the code within the Module is not limited to the
DEFINE_CALL section. Modules can contain variable definitions, functions, subroutines, startup code,
events, and mainline. Modules are passed parameters that are used to adapt the information and variables
used within the Module (similar to System calls).
Modules are similar to programs loaded into AXB-232++ boxes. They operate as stand-alone programs
inside the NetLinx program. Interaction between the Module and the NetLinx Program is done through
User Interface (UI) pushes and releases, turning virtual device channels on and off, and passing variables
and arrays to the Module. The code in the Module is local, or is restricted to use only within the Module.
This means that functions and subroutines defined with Module cannot be directly used with the main
NetLinx code.

NetLinx Programming Language Reference Guide 29


NetLinx Programming Overview

Modules will eventually replace System calls. Where several system calls are currently needed to
provide device initialization, buffer processing, and device functionality, one module will handle all
three functions.
The first line of a Module contains the MODULE_NAME keyword, the Module name, and the parameter
list. The format is shown below:
MODULE_NAME = '<module name>' [(<param1>, <param2>, … , <paramN>)]

The <module name> must match the file name, but has the .AXS extension. The module name can be
64 characters long and contain valid file name characters. The parameter name is optional and follows
the same restrictions as subroutine parameters, with the exception that constants and expressions cannot
be used as arguments.
Within the NetLinx program, the Module is referenced using the following format:
DEFINE_MODULE '<module name>' <instance name> [(<pass1>, <pass2>, … , <passN>)]

The <module name> must match the module name specified in the Module file, as shown above. The
<instance name> is a unique name given to each occurrence of the module within the program. If
the module is used twice within the program, each occurrence gets a unique instance name. The
parameter list passed to the module must match number and types of parameters listed in the module file
above. The DEFINE_MODULE statements are listed in the code after the DEFINE_CALL and
DEFINE_FUNCTION sections, but before the DEFINE_START section.
The DEFINE_MODULE statements cannot appear within the DEFINE_PROGRAM or DEFINE_EVENTS
section.

In order to use a module, the module must be compiled with the Source Code, and
the Master must be rebooted to run the new module.

30 NetLinx Programming Language Reference Guide


Language Elements

Language Elements
Statements and Expressions
A statement refers to a complete programming instructions such as:

Y = X (* Variable Assignment Statement *)


X = X + 1 (* Arithmetic Assignment Statement *)
IF (Y < 10) Y = Y + 1 (* IF Statement *)
[TP, 5] = [VCR, 1] (* Feedback Statement *)

Each of these statements compile, providing the referenced variables are defined.
Expressions are sub-components of statements. The following expressions are used in the above
example:

X + 1 (* Arithmetic Expression *)
Y < 10 (* Logical Expression *)
Y + 1 (* Arithmetic Expression *)
[TP, 5] (* I/O Device Expression *)
[VCR, 1] (* I/O Device Expression *)

Expressions will not compile outside the context of a statement.


It is strongly recommended that each statement appear on a separate line. The compiler cannot
enforce this since full backward compatibility with the previous Axcess language must be
maintained.
It is also strongly recommended that semicolons be used to terminate each statement (as in the
C language).

Assignments
Assignment statements include:
Variables
Output Channels
Variables
The simplest type of assignment statement is a variable, which assigns the value of an expression to a
variable. The expression may be a constant, a variable / mathematical / logical expression, or a return
from function. The data type associated with the expression should match the data type of the variable
receiving the assignment. If not, the value of the expression is typecast to match the destination variable.
An example is:
VariableName = <expression>

Output channels
This type of statement is typically used for feedback. It sends an output change to the specified channel
on the given device. An example is:
[Device, Channel] = <expression>

The expression is evaluated as follows:

NetLinx Programming Language Reference Guide 31


Language Elements

If it is non-zero, the channel associated with the device is turned on.


If it is zero, the channel is turned off.

Conditionals
IF…ELSE
The IF...ELSE statement provides a structure for conditional branching of program execution. If a
condition evaluates to true, the statement(s) associated with it are executed; otherwise, statements are not
executed. An example is:
IF (<conditional expression 1>)
{
(* statements for condition 1 *)
}
ELSE IF (<conditional expression 2>)
{
(* statements for condition 2 *)
}
ELSE
{
(* statements for all other conditions *)
}

Regarding IF statements:
ELSE IF is optional.
Braces are generally recommended in all cases but are only required if multiple statements are
assigned to a given condition.
IF statements may be nested to any number of levels.

SELECT…ACTIVE
The SELECT…ACTIVE statement provides a programming structure for selective execution of code
blocks based on the evaluation of a series of conditions. The first block whose ACTIVE condition
evaluates to true is executed; the remaining blocks are ignored. If no ACTIVE condition evaluates to true,
no statements are executed. An example is:
SELECT
{
ACTIVE (<condition 1>) :
{
(* statements for condition 1*)
}
ACTIVE (<condition 2>) :
{
(* statements for condition 2*)
}
ACTIVE (<condition n>) :
{
ACTIVE (1)
(* statements for condition n*)
}
}

32 NetLinx Programming Language Reference Guide


Language Elements

Regarding SELECT...ACTIVE statements:


Only the statements associated with the first condition evaluated to true are executed.
If no condition evaluates to true, no statements are executed.
Braces underneath individual ACTIVE statements are required only if multiple statements are
assigned to a given condition.
SWITCH…CASE
The SWITCH…CASE statement provides a programming structure for selective execution of code blocks
based on the evaluation of a single condition. The value of the SWITCH expression is tested against each
CASE value (numeric constant or string literal). If a match is found, the statements associated with the
CASE are executed. All other CASE statements are ignored. If no match is found, the DEFAULT case
statements (if any) are executed. The SWITCH expression is evaluated only once. An example is:
SWITCH (x)
{
CASE 1 : //do stuff when x = 1
{
}
CASE 2 : //do stuff when x = 2
{
}
default : // do stuff when x is not 1 or 2
{
}
}

This is programmatically the same programmatically as:


If (x = 1) //do stuff when x = 1
{
}
else if (x = 2) //do stuff when x = 2
{
}
else // do stuff when x is not 1 or 2

Regarding SWITCH...CASE statements:


Only the statements associated with the first case that matches the value of the expression are
executed.
If no CASE matches the SWITCH expression, the statements under the default case (if
available) are executed.
All cases must be unique.
Braces should be used to bracket the statements in a case. They are required only if variables
are declared within the case.
The BREAK statement applies to the SWITCH. It takes execution to the end of the SWITCH.
Unlike the C language, cases do not fall through to the next case if a break is not used.
BREAKs are recommended between cases. For example:

NetLinx Programming Language Reference Guide 33


Language Elements

SWITCH (var)
{
CASE 1:
{
(*statements go here*)
BREAK
}
CASE 3:
{
(*statements go here*)
BREAK
}
CASE 5:
{
(*statements go here*)
BREAK
}
DEFAULT:
{
(*statements go here*)
BREAK
}
}

Loops
WHILE statements
A WHILE statement executes its statement block as long as its associated condition evaluates to true. The
condition is evaluated before the first pass through the statements. Therefore, if the conditional
expression is never true, the conditional statements are never executed. An example is:
WHILE (<conditional expression>)
{
(* conditional statements *)
}

Regarding WHILE statements:


Statements are executed repeatedly while the conditional expression evaluates to true.
The condition is tested before each pass through the conditional statements.
There is no timeout period as was the case with Axcess. The original intent of the timeout
period was to prevent WHILE loops from locking out updates to/from the AXlink bus. The
NetLinx Central Controller handles bus updates through a separate execution thread, thereby
eliminating this potential problem.
MEDIUM_WHILE statements
The MEDIUM_WHILE statement is obsolete in NetLinx. The compiler accepts the statement but converts
it internally to a WHILE statement. For example:

34 NetLinx Programming Language Reference Guide


Language Elements

MEDIUM_WHILE (<conditional expression>)


{
(* conditional statements *)
}

LONG_WHILE statements
A LONG_WHILE differs from a WHILE statement in the way input change notifications are processed
during the programming loop. The system checks the input queue for a change notification message
before execution of each loop, beginning with the second loop. The message is retrieved if one exists.
This message must be processed before another one is retrieved, either at the start of the next loop or the
beginning of the next mainline iteration. Otherwise, the message is lost. For example:
LONG_WHILE (<conditional expression>)
{
(* conditional statements *)
}

DEFINE_EVENT events are still processed even if mainline is in a LONG_WHILE.

LONG_WHILE should not be used in Events. It may cause unexpected results.

FOR loop structure


The FOR loop structure allows you to define initialization statements; statements to execute after each
pass through the loop and a condition to test after each pass. If the condition evaluates to true, another
pass is made. Otherwise, the loop is terminated. The syntax of the FOR loop is as follows:
FOR (<INITIAL>; <condition>; <after pass>)
{
(* loop statements *)
}

Parameters:

<INITIAL> One or more statements that are executed one time before any FOR loop state-
ments are executed. Each statement must be separated with a comma; this is
typically a FOR loop index initialization statement.
<condition> A condition whose value is computed before each pass. If the condition evalu-
ates to TRUE, the FOR loop statements are executed. If the condition evaluates
to FALSE, the loop is terminated.
<after pass> One or more statements that are executed after each pass through the state-
ments. Each statement must be separated with a comma. This is typically a
statement that increments the FOR loop index.

NetLinx Programming Language Reference Guide 35


Language Elements

Waits
Wait instructions allow delayed execution of one or more program statements. When a wait statement is
executed, it is added to a list of currently active wait requests and the program continues running.
Naming Waits
Supplying a unique name in the wait statement allows the wait to be identified for purposes of canceling,
pausing, or restarting the wait request. The name must not conflict with previously defined constants,
variables, buffers, subroutines, or functions. Unlike other NetLinx identifiers, wait names may contain
spaces.
If a wait instruction that uses a name currently in the wait list is encountered, the new wait instruction is
thrown away so as not to conflict with the one currently in progress. If this feature is not desired, the
current wait must be canceled before processing the new request. For information, refer to the Canceling
Waits section on page 38.
Types of Waits
Types of Wait statements include:
Timed Waits have an associated parameter that indicates the amount of time that must elapse
before the associated wait instruction(s) are to be executed.
Conditional Waits require that a specified condition be met before the instructions are
executed.
Timed Conditional Waits have a timeout parameter; if the condition is not met before the
specified time elapses, the wait request is cancelled.
Types of Waits
Timed Waits Syntax:
WAIT time ['<name>']
{
(* wait statements *)
}
Parameters:
• time: A constant or variable indicating the wait time. Time is expressed in 1/
10th second units. The statement below specifies a wait time of 5 seconds
for the wait named FIRST WAIT.
• <name>: The name to assign to the wait. This name must be a literal string.
The wait name is optional, although unless a wait is named it cannot be
individually cancelled, paused, or restarted.
If greater precision is required, the time parameter can be expressed as a dec-
imal fraction, for example 0.1 to specify a wait time of 1/100th of a second. The
range is from 0.1 to 0.9.
WAIT 50 'FIRST WAIT'
{
(* wait statements *)
}

Continued

36 NetLinx Programming Language Reference Guide


Language Elements

Types of Waits (Cont.)


Conditional Waits WAIT_UNTIL is a conditional Wait request.
Syntax:
WAIT_UNTIL <condition> ['<name>']
{
(* wait statements *)
}
Parameters:
• <condition>: Any single or compound expression that can be evaluated as
a logical expression. The Wait statements are executed if and when the wait
condition becomes True.
• <name>: The name to assign to the Wait. This name must be a literal string.
The Wait name is optional, although unless a Wait is named it cannot be
individually cancelled, paused, or restarted.
Timed Conditional Waits TIMED_WAIT_UNTIL is a Timed Conditional Wait request.
Syntax:
TIMED_WAIT_UNTIL <condition> timeout ['<name>']
{
(* wait statements *)
}
Parameters:
• <condition>: Any single or compound expression that can be evaluated as
a logical expression. The Wait statements are executed if and when the Wait
condition becomes true.
• timeout: A constant or variable indicating the timeout value in 1/10th
seconds. If the Wait condition is not met within the time indicated by this
parameter, the Wait is cancelled, in which case no wait statements are
executed.
• <name>: The name to assign to the Wait. This name must be a literal string.
The Wait name is optional, although unless a Wait is named it cannot be
individually cancelled, paused, or restarted.

Nesting Waits
The wait time for a nested wait is the sum of it's own wait time, plus that of the enclosing waits. In the
example below, SECOND WAIT occurs 0.5 seconds after FIRST WAIT is executed, or 1.5 seconds after
FIRST WAIT is added to the wait list.
WAIT 10 'FIRST WAIT'
{
(* FIRST WAIT statements *)
WAIT 5 'SECOND WAIT'
{
(* SECOND WAIT statements *)
}
}

To execute the inner wait of a nested conditional wait, the conditions must be met in the order specified
(condition 1, then condition 2) but not necessarily at the same time.

NetLinx Programming Language Reference Guide 37


Language Elements

WAIT_UNTIL <condition 1> 'FIRST WAIT'


{
(* FIRST WAIT statements *)
WAIT_UNTIL <condition 2> 'SECOND WAIT'
{
(* SECOND WAIT statements *)
}
}

Pausing and restarting Waits


The following commands relate to pausing and restarting waits.
Pausing and Restarting Waits
PAUSE_WAIT PAUSE_WAIT puts a scheduled wait on hold. The wait being paused is identi-
fied by the parameter name. The wait timer stops counting down until it is
resumed with a RESTART_WAIT command. Here's a syntax sample:
PAUSE_WAIT '<name>'
RESTART_WAIT RESTART_WAIT resumes the countdown for a wait suspended with
PAUSE_WAIT. The wait to be restarted is identified by the parameter name.
RESTART_WAIT '<name>'
PAUSE_ALL_WAIT & PAUSE_ALL_WAIT and RESTART_ALL_WAIT commands are used to pause or
RESTART_ALL_WAIT restart all scheduled waits, regardless of whether or not they are named. They
have no parameters.
PAUSE_ALL_WAIT
RESTART_ALL_WAIT

Canceling Waits
Canceling Waits
CANCEL_WAIT / CANCEL_WAIT and CANCEL_WAIT_UNTIL removes the wait specified by
CANCEL_WAIT_UNTIL name from the appropriate wait list. The syntax:
CANCEL_WAIT '<name>
CANCEL_WAIT_UNTIL '<name>'
CANCEL_ALL_WAIT / CANCEL_ALL_WAIT and CANCEL_ALL_WAIT_UNTIL cancels all waits
CANCEL_ALL_WAIT_UNTIL (named or unnamed) from the appropriate wait list. The syntax:
CANCEL_ALL_WAIT
CANCEL_ALL_WAIT_UNTIL

Using Waits - Limitations


References to STACK_VAR variables are not allowed within waits (STACK_VAR are temporary
variables that cease to exist when the block in which they are declared is exited).
Variable copies are made of functions and subroutine parameters. This can have speed/
execution penalties.
A RETURN is not allowed within a WAIT within functions and subroutines.
A BREAK or CONTINUE cannot appear within a WAIT if it takes execution out of the scope of
the WAIT.
The code within a WAIT cannot reference a function or subroutine array parameter whose
bounds are unspecified.

38 NetLinx Programming Language Reference Guide


Language Elements

Comments
Comments are designated with a parentheses-asterisk to begin the comment and asterisk-parentheses to
end the comment; for example, (*COMMENT*). These comments can span lines and are not limited in
length. NetLinx supports a second type of comment with a double forward-slash (//).
All text following the double forward-slash is treated as a comment. This type of comment closely
follows the conventions of C++.
Comments are not part of the actual program code; they are not compiled. Comments can appear
anywhere except within literal strings, either on the same line as a programming statement or on a
separate line. Comments can span multiple lines with a single set of comment delimiters and can be
nested. The compiler recognizes nested comments by pairing up sets of comment delimiters. For
example:
(* The section to follow contains all variable declarations. *)

Single line comments can be specified using the double forward slash (//) notation. When a pair of
forward slash characters is encountered, all text on the same line following the slash pair, except the *)
end comment sequence, is considered a comment and ignored by the compiler. For example:
(*INTEGER Vol1 // volume for room 1 *)

The "*)" in the line above terminates the open "(*" command even though it appears after a double
slash comment command.

Operators
An operator is a character (or group of characters) that performs a specific mathematical or relational
function. Each operator type is described below.
Arithmetic operators
Arithmetic operators create a numeric value from one or more operations such as addition,
multiplication, and division.
Arithmetic Operators
Operator Function
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulo (remainder after division)

Relational operators
A relational operator is a conditional statement; it tells NetLinx whether to execute a particular
function(s) in the program.
Relational Operators
Operator Function
< Less Than
> Greater Than
= Equal To
== Equal To
<= Less Than or Equal To
>= Greater Than or Equal To
<> Not Equal To

NetLinx Programming Language Reference Guide 39


Language Elements

Logical operators
Logical operators compare two conditions or, in the case of NOT, invert one condition. A true or false
result is produced.
Logical Operators
Operator Function Keyword
&& Logical And AND
|| Logical Or OR
^^ Logical Xor XOR
! Logical Not NOT

Bitwise operators
Bitwise operators are keywords or symbols that perform a bit-by-bit operation between two items.
Bitwise Operators
Operator Function Keyword
& Bitwise And BAND
| Bitwise Or BOR
^ Bitwise Xor BXOR
~ Bitwise Not BNOT
<< Shift Left LSHIFT
>> Shift Right RSHIFT

Assignment operators
The assignment operators may appear only once in a single NetLinx statement.
Assignment Operators
Operator Function
= Assignment
++ Increment by 1
-- Decrement by 1

The following rules apply to the use of assignment operators:


The "=" operator may be used to assign:
Expressions to intrinsic type variables (see theData Types section on page 50)
Arrays to other arrays of matching size and type
Structures to other structures of the same type
The "++" and "--" operators are statements and cannot appear within expressions. For
example:
FOR (I=1; I<10; I++) // Legal
I = j++; // Illegal

Refer to the Structures section on page 55 for information on structures.

40 NetLinx Programming Language Reference Guide


Language Elements

Operator precedence
The table below shows the inherent precedence assigned to the operators. As noted in the chart, the NOT
(!) operator has the highest precedence in NetLinx systems but the lowest precedence in Axcess
systems. Axcess programs that are converted to NetLinx may exhibit logic problems if they use
statements that combine NOT (!) and other operators. Contact AMX Technical Support for help
resolving these issues.
Operator Precedence
Level Operators Associability
1 ! ~ Left To Right
2 * / % Left To Right
3 << >> Left To Right
4 + - Left To Right
5 < <= > >= = == <> Left To Right
6 & | ^ Left To Right
7 && || ^^ Left To Right

Identifiers
An Identifier is a combination of letters, numbers, or underscores that represents a device, constant, or
variable. Identifier types include:

• Devices • Device-Channel Arrays

• Device Arrays • Level Arrays

• Channel Arrays • Device-Level Arrays

Devices
A device is any hardware component that can be connected to the NetLinx bus. Each device must be
assigned a unique number to identify it on the bus. While the Axcess language allows physical device
numbers in the range 0-255, the NetLinx language allows numbers in the range 0-32767. Device 0 refers
to the Master; numbers above 32767 are reserved for internal use.
NetLinx requires a Device:Port:System (D:P:S) specification where Axcess expected only a device
number. This D:P:S triplet can be expressed as a series of constants, variables separated by colons, or a
DEV structure. For example:
STRUCTURE DEV
{
INTEGER Number // Device number
INTEGER Port // Port on device
INTEGER System // System device belongs to
}

A device specification in NetLinx can be expressed in one of two ways:


Device Number: The compiler replaces the device number with an internally generated DEV
structure. This DEV structure contains the specified device Number. If the system and port
specifications are omitted (e.g. 128), system zero (indicating this system - the system
executing the code), and port one (indicating the first port), is assumed.

NetLinx Programming Language Reference Guide 41


Language Elements

Device:Port:System (D:P:S): This notation is used to explicitly represent a device number,


port, and system. For example, 128:1:0 represents the first port of the device number 128 on
this system. The syntax:
NUMBER:PORT:SYSTEM

Parameters:

Number 16-bit integer representing the Device number


Port 16-bit integer representing the Port number (in the range 1 through
the number of ports on the device)
System 16-bit integer representing the System number (0 = this system).

Device arrays
In order to specify a group of devices for a command or event handler, NetLinx provides the capability to
define an array of DEVs and treat it as a device array. A device array may be used anywhere a device
specification is required. The result provides a range of targets for the command or instruction where it is
used.
Device arrays are declared in the DEFINE_VARIABLE section of the program in one of two ways:
DEV DSName[ ] = {Dev1, Dev2, ..., Devn}
DEV DSName[MaxLen] = {Dev1, Dev2, ..., Devn}

Each device name appearing on the right-hand side of the declaration should be defined as a device in the
DEFINE_DEVICE section; however, it can also be defined in the DEFINE_VARIABLE or
DEFINE_CONSTANT section.
The first statement above declares a device array whose maximum length is determined by the number of
elements in the initialization array on the right-hand side.
The second form uses MaxLen to specify the maximum length of the device array. In either case, the
number of elements in the initialization array determines the effective length of the device array. That
value can be determined at run-time by calling LENGTH_ARRAY. The maximum length available for a
device array can be determined by calling MAX_LENGTH_ARRAY.
The following program fragment illustrates device array initialization:
DEFINE_DEVICE
panel3 = 130

DEFINE_CONSTANT
DEV panel1 = 128:1:0
integer panel2 = 129

DEFINE_VARIABLE
// dvs is an array of three devices:
// 128:1:0
// 129:1:0
// 130:1:0
DEV dvs[ ] = {panel1, panel2, panel3}

The individual elements of a device array can be referenced by their defined names (Dev1, Dev2, etc.)
or by using array notation with the device array name. For example, the 3rd device in the device array,
MyDeviceSet, would be referenced by MyDeviceSet[3].

42 NetLinx Programming Language Reference Guide


Language Elements

The index of the last member of the array for which an event notification was received can be determined
by calling GET_LAST(MydeviceSet). This is useful for determining which device in an array is
referenced in a particular notification message.
Device array examples
The command below sends 'CHARD10' to all devices in the array, DeviceSetA.
DEV DeviceSetA[ ] = {Device1, Device2, Device3}
SEND_COMMAND DeviceSetA, 'CHARD10'

The command below sends 'CHARD10' to the third device in the array, DeviceSetA,
SEND_COMMAND DeviceSetA[3], 'CHARD10'

and is equivalent to:


SEND_COMMAND Device3, 'CHARD10'

The intent of the feedback statement is to set channel 1 in every device in DeviceSetA to either on or
off, depending on the value of the right-hand expression; it is unclear what the right-hand expression
evaluates to. The compiler will issue a warning indicating the syntax is unclear and that
DeviceSetB[1] is assumed. To avoid this warning, specify a particular device in the array. Here's an
example:
[DeviceSetA, 1] = [DeviceSetB[1], 2] (* Correct *)

Device-channels and device-channel arrays


As the name implies, a device-channel (DEVCHAN) is a combination of a device and a channel. It is
represented internally as a DEVCHAN structure. This structure combines the fields of a DEV structure
representing the device with a field representing the channel number.
STRUCTURE DEVCHAN
{
DEV //Device
INTEGER //Channel
}

The first component of a device-channel pair represents the device number, port, and system. It can be
specified as either a single device number, a constant DEV structure or as a D:P:S specification. Each
device specified in a device-channel pair should be defined in the DEFINE_DEVICE section.
Channels are expressed as integer constants. A DEVCHAN is declared in either the DEFINE_VARIABLE
or DEFINE_CONSTANT section. For example, "[128, 1]", "[CONSTANTDPS, 9]" and "[128:1:0,
5]" are all valid representations of device-channel pairs.
A DEVCHAN enclosed within square brackets implies an evaluation, whereas a DEVCHAN enclosed within
curly braces does not, as illustrated below:
DEFINE_VARIABLE
DEVCHAN dc1 = {128:1:0, 1}
DEVCHAN dcset[ ] = { {128:1:0, 1}, {128:1:0, 2}, {128:1:0, 3} }

DEFINE_PROGRAM

IF ( [dc1] || [128:1:0, 2] ) // evaluation of 2 devchans


[dc1] = 1 // feedback

dc1 = {129:1:0, 2} // assigns a new value to dc1


[dc1] = {129:1:0, 2} // Syntax Error!

NetLinx Programming Language Reference Guide 43


Language Elements

A DEVCHAN array is declared in the DEFINE_VARIABLE or DEFINE_CONSTANT section in one of two


ways:
Declare a DEVCHAN array whose maximum length is determined by the number of elements in
the initialization array on the right-hand side, as shown below:
DEVCHAN[ ] DCSName = {{Dev1,Chan1}, {Dev2,Chan2}, ...}

Use MAXLEN to specify the maximum length of the array, as shown below:
DEVCHAN[ ] DCSName[MAXLEN] = {{Dev1,Chan1}, {Dev2,Chan2}, ...}

In either case, the number of elements in the initialization array determines the effective length of the
array. That value can be determined at run-time by calling LENGTH_ARRAY. The maximum length
available for a DEVCHAN[ ] array can be determined by calling MAX_LENGTH_ARRAY.
The individual elements of a DEVCHAN array can be referenced by their defined names (Dev1, Chan1,
Dev2, Chan2, etc.) or by using array notation with the device-channel array name. For example, the
third element in the device-channel array, MyDCSet, would be referenced by MyDCSet[3].
Furthermore, since a DEVCHAN array is an array of DEVCHAN structures, DEVCHAN members can be
referenced using the dot operator notation such as MyDCSet[3].Device or MyDCSet[1].Channel.
A DEVCHAN array can be used anywhere a [Device, Channel] specification is required with the
result of providing a range of targets for the command or instruction where it is used. This implies an
alternate form for the following commands:

Button[(DEVCHAN)] PULSE[(DEVCHAN)]
DO_PUSH[(DEVCHAN)] PUSH[(DEVCHAN)]
DO_RELEASE[(DEVCHAN)] RELEASE[(DEVCHAN)]
OFF[(DEVCHAN)] TO[(DEVCHAN)]
ON[(DEVCHAN)]

The index of the last member of the array for which an event notification was received can be determined
by calling GET_LAST(MyDCSet). This is useful for determining which device and channel in an array
is referenced to in a particular notification message.
Device-level arrays
A device-level array (DEVLEV array) is an array of device-level pairs. Each element is represented
internally as a DEVLEV structure. This structure combines the fields of a DEV structure representing the
device with a field representing the level number.
STRUCTURE DEVLEV
{
DEV // Device
INTEGER // Level
}

The first component of a device-level pair (Device) represents the device number, port, and system. It
can be specified as either a single device number, a constant DEV structure or as a D:P:S specification.
Each device specified in a device-level pair should be defined in the DEFINE_DEVICE section. The
second component is the level number on the device. The level number is expressed as an integer
constant.
A DEVLEV array is declared in the DEFINE_VARIABLE or DEFINE_CONSTANT section in one of two
ways:

44 NetLinx Programming Language Reference Guide


Language Elements

Declare a DEVLEV array whose maximum length is determined by the number of elements in
the initialization array on the right-hand side.
DEVLEV DLName[ ] = {{Dev1,Level1}, {Dev2,Level2}, ...}

Use MAXLEN to specify the maximum length of the array.


DEVLEV DLName[MAXLEN] = {{Dev1,Level1}, {Dev2,Level2}, ...}

In either case, the number of elements in the initialization array determines the effective length of the
array. That value can be determined at run-time by calling LENGTH_ARRAY. The maximum length
available for a DEVLEV array can be determined by calling MAX_LENGTH_ARRAY.
The individual elements of a level array can be referenced by their defined names (Dev1, Level1,
Dev2, Level2, etc.) or alternatively, by using array notation with the device-level array name. For
example, the 3rd element in the device-level array, MyDLSet, would be referenced by MyDLSet[3].
Furthermore, since a DEVLEV array is an array of DEVLEV structures, DEVLEV members can be
referenced using the dot operator notation such as MyDLSet[3].Device or MyDLSet[1].Level.
The index of the last member of the array for which an event notification was received can be determined
by calling GET_LAST(MyDLSet). This is useful for determining which device and level in an array is
referenced to in a particular notification message.

Variables
NetLinx provides support for several different types of variables distinguished by attributes, such as:
Scope
Constancy
Persistence
Scope
Scope is a term used in reference to program variables that describe where in the program they can be
accessed. There are two types:
Local scope: a variable can only be accessed in the subroutine or method that it is declared.
Global scope: a variable can be accessed anywhere in the program.
Scope differentiates the two basic classes of NetLinx variables:
Local variable: a variable declared within a subroutine or function whose scope is limited to
that subroutine or function.
Global variable: a variable declared in the DEFINE_VARIABLE section; its scope extends
throughout the module in which it is declared.
Local variables
Local variables are restricted in scope to the statement block in which they are declared. A statement
block is one or more NetLinx statements enclosed in a pair of braces, like the blocks following
subroutines, functions, conditionals, loops, waits, and so on. Local variables must be declared
immediately after the opening brace of a block but before the first executable statement. To provide
compatibility with the Axcess language, local variables may be declared right before the opening brace
for DEFINE_CALL declarations only. For example, both formats shown below are legal in the NetLinx
language:

NetLinx Programming Language Reference Guide 45


Language Elements

DEFINE_CALL 'My Subroutine' (INTEGER INT1)


LOCAL_VAR INTEGER INT2
{
(* body of subroutine *)
}
DEFINE_CALL 'My Subroutine' (INTEGER INT1)
{
LOCAL_VAR INTEGER INT2
(* body of subroutine *)
}

The scope of a local variable is restricted to the statement block in which it is declared. A local variable
is either static or non-static, depending on whether it is declared as LOCAL_VAR or STACK_VAR:

A static variable maintains its value throughout the execution of the program,
regardless of whether it is within scope of the current program instruction.

The keyword LOCAL_VAR specifies a static variable. A static variable's value is initialized the
first time the statement block in which it is declared is executed and retained after execution of
the statement block has finished.
The STACK_VAR keyword specifies a non-static variable. A non-static variable's value is re-
initialized every time the statement block in which it is declared is executed.
If neither the LOCAL_VAR nor the STACK_VAR keyword is specified, STACK_VAR is assumed
(default).
IF (X > 10)
{
LOCAL_VAR INTEGER INT2 // static (permanent)
STACK_VAR CHAR ARRAY1[10] // non-static (temporary)
(* statements *)
}

Variable declarations outside of DEFINE_VARIABLE will default to STACK_VAR if


neither "local" or "stack" is specified.

LOCAL_VAR and STACK_VAR can be used interchangeably in any statement block except for waits.
Only LOCAL_VAR variables may be declared inside a wait block.
WAIT 10, 'My Wait Name'
{
LOCAL_VAR CHAR TempBuf[80]
(* statements *)
}

A name assigned to a local variable must be unique within the statement block in which it is declared and
any statement block enclosing that block. Therefore, non-nested statement blocks can define the same
local variable name without conflict. For example:

46 NetLinx Programming Language Reference Guide


Language Elements

Define_function integer MyFunc(INTEGER nFlag)


{
LOCAL_VAR INTEGER n
IF (nFlag > 0)
{
LOCAL_VAR INTEGER n // illegal declaration
.
.
}
.
.
}
Define_function integer MyFunc(INTEGER nFlag)
{
IF (nFlag > 0)
{
LOCAL_VAR INTEGER n
.
.
}
else
{
LOCAL_VAR INTEGER n // legal declaration
}
}

The general form of a static local variable declaration is:


[LOCAL_VAR] [VOLATILE | PERSISTENT] [CONSTANT] [<type>] name

The general form of the non-static local variable declaration is:


[STACK_VAR] [<type>] name

Since non-static local variables are allocated on the program stack (a block of memory reserved for
allocation of temporary variables), the keywords VOLATILE, PERSISTENT, and CONSTANT do not
apply.
Global variables
Global variables are defined in the DEFINE_VARIABLE section of any program module. For example:
DEFINE_VARIABLE
CONSTANT INTEGER MAXLEN = 64
CHAR STR[MAXLEN] = 'No errors were found.'
INTEGER ARRAY[ ] = {100, 200, 300}

A global variable is accessible throughout the module or program in which it is defined. Global variables
retain their value as long as the program runs. They may retain their value after powering down or
reloading the system, depending on the variable's persistence attributes (VOLATILE and PERSISTENT).

NetLinx Programming Language Reference Guide 47


Language Elements

Modules are reusable NetLinx sub-programs that can be inserted into the main
program. The main program is also a module. Refer to the NetLinx Modules section
on page 143 for information on program modules.

If a local variable shares the same name as a global variable, the local variable always takes precedence.
The general form of a global variable definition is:
[NON_VOLATILE | VOLATILE | PERSISTENT] [CONSTANT] [<type>] name [= <value>]

Constancy
Any variable may also be assigned the attribute CONSTANT. This declares a variable to be immutable
(cannot change at run-time). The variable must be initialized as part of its declaration if this keyword is
used.
Persistence
The persistence of a variable is controlled through the NON_VOLATILE, VOLATILE and PERSISTENT
keywords.
Non-volatile variables: A variable declared with the NON_VOLATILE keyword is stored in
non-volatile memory. It will retain its value in the event of a system power-down, but is reset
to zero if the program is reloaded. Unless specified otherwise, all variables are stored in non-
volatile memory.
Volatile variables: A variable declared with the VOLATILE keyword is stored in volatile
memory and resets to zero after either a power-down or reload. Volatile memory is generally
faster and more plentiful than non-volatile memory. For this reason, you should use the
VOLATILE keyword when declaring large data arrays where persistence of the data is not a
requirement.
Persistent variables: If a variable is declared with the PERSISTENT keyword, it is initialized
to zero the first time the program is loaded but will retain its value after either power-down or
reload.
If the data type is omitted from the variable definition, the following defaults are assumed:
Single variables are INTEGER type.
Arrays are CHAR type.
You can define a variable to be persistent using the PERSISTENT storage modifier as show below:
DEFINE_VARIABLE
PERSISTENT CHAR cMyString[100]

All persistent variables are automatically non-volatile, and it’s not legal to define a variable as
VOLATILE and PERSISTENT.
Any time after a NetLinx program that has a persistent variable declared subsequent downloads of new
NetLinx programs that contain the same persistent variable will automatically be set to contain the same
value as it previously did. The default behavior for non-persistent variables is they are set to zero after a
NetLinx program downloads. Persistence overrides this behavior by setting the variable in the newly
downloaded program to be the same as it was before the download.
Typically, persistent variables are used for saving preset information. Suppose you have a system that
contains several Positrack camera positioning systems and that the user interface to the system allows the
user to set the position of any of the cameras and record that position for recalling later. The position
presets are stored in a non-volatile array variable so they are maintained during a power cycle. Without
persistent variables, an update to the NetLinx program would zero out all of the presets that the user had

48 NetLinx Programming Language Reference Guide


Language Elements

stored. With persistent variables, the new NetLinx program can be downloaded and all of the presets
remain intact.
When a new NetLinx program is downloaded to the Master, the Master iterates through all non-volatile
variables from the new program looking for persistent ones. When it finds a persistent variable in the
new program, it searches the old programs persistent variable space for the "same variable". When it
finds the same variable, the value of the new variable is set to the same value as the old programs
variable. It is important to note what is considered to be the "same variable". The master identifies the
"same variable" by verifying for duplicity the following:
Variable name
Variable source location
Variable type
Therefore, in order for persistence to function properly, the name, type, and file declared in must be the
same as the previously downloaded NetLinx program. If you changed any of the three, the new persistent
variable will not be set with the old variable’s value.

Constants
Constants are defined in the DEFINE_CONSTANT section. The scope of a constant extends throughout
the module or program in which it is defined. The name assigned to a constant must be unique among all
other identifiers defined in the module or program. The syntax is:
DEFINE_CONSTANT
<constant name> = <constant expression>

Constants may be assigned expressions that consist only of other constants and operators. Variables are
not allowed in constant expressions. An example is:
VALUE_OFFSET = 500
VALUE1 = VALUE_OFFSET + 1
STR1 = 'This is a string constant.'

Constants can be used anywhere that a numeric or string constant is allowed. The value assigned to a
constant can be specified in one of the formats listed in the following table.
Valid Formats for Constants
Type Format Example
Decimal Integer 0000 1500
Hexadecimal Integer $000 $DE60
Floating Point 000.0 924.5
Exponential Notation 0.0e0 1.5e-12
Character 'c' or <char code> 'R' or 255
String Literal 'ssss' 'Reverse'

NetLinx Programming Language Reference Guide 49


Language Elements

Data Types
Intrinsic types
The following table lists the data types inherently supported by the NetLinx language.
NetLinx Intrinsic Data Types
Keyword Data Type Sign Size Range
CHAR Byte Unsigned 8-bit 0 - 255
WIDECHAR Integer Unsigned 16-bit 0 - 65535
INTEGER Integer Unsigned 16-bit 0 - 65536
SINTEGER Integer Signed 16-bit -32768 to +32768
LONG Long Integer Unsigned 32-bit 4,294,967,295
SLONG Long Integer Signed 32-bit + 2,147,483,647
FLOAT Floating Point Signed 32-bit 1.79769313 E+308 to 2.22507385 E-308
DOUBLE Double Precision Signed 32-bit 3.40282347 E+38 to 1.17549435 E-38
Floating Point

Type conversion
Although explicit type casting is not supported in the NetLinx language, the compiler is forced to do type
conversion in situations where an arithmetic assignment or other operation is defined with constants and/
or variables having mixed data types. Type conversions will occur under the following circumstances:
A value of one type is assigned to a variable of another type.
A value passed as a parameter to a subroutine does not match the declared parameter type.
The value returned by a subroutine does not match the declared return type.
Type conversion rules
If the expression contains a 32 or 64-bit floating-point variable or constant, all variables and
constants in the expression are converted to 64-bit floating point before resolving.
If the expression contains only whole number value variables and constants, all variables and
constants in the expression are converted to 32-bit integers before resolving.
If type conversion is required for an assignment or as a result of a parameter or return type
mismatch, the value is converted to fit the type of the target variable. This may involve
truncating the high order bytes(s) when converting to a smaller size variable, or sign
conversion when converting signed values to unsigned or vice versa.

50 NetLinx Programming Language Reference Guide


Language Elements

Strings
A string is an array of characters of known length. This length may be less than the dimensioned length.
For example:
DEFINE_VARIABLE
CHAR MyString[32]
INTEGER StrLen

DEFINE_START
MyString = 'STOP'
StrLen = LENGTH_STRING(MyString)

In the example above, StrLen holds the value 4, the length of MyString. The length of MyString can
range from 0 to 32. If an attempt is made to assign a string longer than the capacity of the destination
string, the copied string is truncated to fit. The string length is implicitly set when a string literal, string
expression, or variable is assigned to the string. The function SET_LENGTH_STRING can be used to
explicitly set the length of a string to any arbitrary length between 0 and the dimension of the character
array. Here's an example:
SET_LENGTH_STRING(MyString, 3)

This causes the contents of MyString to read 'STO', even though the character 'P' still resides in
MYSTRING[4].

String expressions
A string expression is a string enclosed in double quotes containing a series of constants and/or variables
evaluated at run-time to form a string result. String expressions can contain up to 16000 characters
consisting of string literals, variables, arrays, and ASCII values between 0 and 255. Here's an example:
CHAR StrExp[6]
StrExp = "STOP, 25, 'OFF', X"

In the example above, the string expression contains the constant STOP, the value 25, the string literal
'OFF', and the variable X. Assuming STOP is 2 and X = 5, the string expression will evaluate to "2,
25, 'OFF', 5".

Wide strings
A wide character string data type is provided for dealing with Unicode fonts, which use 16-bit character
codes (used for many Far-Eastern fonts) instead of the standard 8-bit codes (used with most Western
fonts). Here's a syntax sample for a wide character string:
WIDECHAR WChar[40]

The statement above declares a wide character string containing 40 elements, for a total of 80 bytes. A
wide character string can be used in the same manner as other character strings. It maintains a length
field that can be retrieved using LENGTH_STRING and set using SET_LENGTH_STRING. Here's an
example:
WIDECHAR StrExp[6]
INTEGER StrLen

StrExp = {STOP, 500, 'OFF', X}


StrLen = LENGTH_STRING(StrExp)

NetLinx Programming Language Reference Guide 51


Language Elements

In the example above, if STOP is 2 and X is a wide character whose value is 1000, the string expression
will evaluate to "2, 500, 79, 70, 70, 1000" and StrLen is 6. Each array element can now
assume a value of up to 65,535, rather than the limit of 255 imposed by the standard character string.
A CHAR string may be assigned or compared to a wide character string. For example:
WChar = 'FFWD'

- or -
IF (WChar = 'REV')
{
(* statements *)
}

Each 8-bit character in the CHAR string is converted to 16-bit before the assignment or comparison
operation is performed.

Arrays
In the Axcess language, arrays can be declared with 8-bit (string) or 16-bit (integer) fields.
The syntax for an 8-bit (string) field is:
Name[20] // 8-bit character array

The syntax for a 16-bit (integer) field is:


INTEGER Number[10] // 16-bit integer array

The NetLinx language allows arrays of any data type supported by the language, as well as, arrays of
user-defined structures and classes. If an initialization statement is included in the variable declaration,
the array dimension is not required. If the array dimension is omitted, both the maximum and effective
length is set to the length needed to hold the data contained in the initialization string.
CHAR STRING[ ] = 'character string'
WIDECHAR WideString[ ] = 'wide character string'
INTEGER IntegerNum[ ] = {1, 2, 3, 4, 5}
SINTEGER SINTEGERNum[ ] = {-1, 5, -6}
LONG LONGNum[ ] = {$EFFF, 0, 89000}
SLONG LONGNum[ ] = {-99000, 50, 100, 100000}
FLOAT FloatingNum[ ] = {1.0, 20000.0, 17.5, 80.0}
DOUBLE DoubleNum[ ] = {1.0e28, 5.12e-6, 128000.0}

String expressions are not allowed for initialization statements.

The initialization statement for a single dimension character string is enclosed in single quotes; data for
other types is enclosed in braces. In the case of a multidimensional character string, the strings in the
initialization statement are separated by commas and enclosed in braces. In order to populate the array,
for example:

52 NetLinx Programming Language Reference Guide


Language Elements

DEFINE_VARIABLE
CHAR StringTable_3[3][5]

DEFINE_START
CHAR StringTable_3[1] = 'Str 1'
CHAR StringTable_3[2] = 'Str 2'
CHAR StringTable_3[3] = 'Str 3'

For multidimensional array types, the data pertaining to each dimension is delimited using braces, as
shown below:
INTEGER Num2D[ ][ ] = {{1, 3}, {2, 4}, {7, 8}}
(* This sets the dimensions to Num2D[3][2] *)

Arrays can be manipulated using the operator "=". The "=" operator is used to assign one array to
another. In the example below, the contents of Array1 are replaced by the contents of Array2.
Array1 = Array2

The arrays must match in number of dimensions and type. The size of each dimension of the destination
array must be greater than or equal to the corresponding dimension of the array being assigned;
otherwise, the contents of the array being assigned are truncated to fit into the destination array. If a type
mismatch is detected, the compiler will issue an appropriate warning.
The length of an array is determined by calling LENGTH_ARRAY and MAX_LENGTH_ARRAY.
LENGTH_ARRAY returns the effective length of a dimension of an array; the length set implicitly through
array initialization or array manipulation operations (+ and -) or explicitly through a call to
SET_LENGTH_ARRAY. MAX_LENGTH_ARRAY is used to determine the maximum length of a dimension
of an array. For example:
INTEGER Len
INTEGER Array[1] = {3, 4, 5, 6, 7}
INTEGER Array2[10] = {1, 2}
Len = MAX_LENGTH_ARRAY(Array1) // Len = 5
Len = MAX_LENGTH_ARRAY(Array2) // Len = 10

LENGTH_ARRAY is called to determine the effective length of Array1 and Array2. This value is set
automatically when the arrays are initialized.
Len = LENGTH_ARRAY(Array1) // Len = 5
Len = LENGTH_ARRAY(Array2) // Len = 2

Multi-dimensional arrays
Any of the single dimension array types listed above can be used to define an array of n-dimensions. A
2-dimensional array is simply a collection of 1-dimensional arrays; a 3-dimensional array is a collection
of 2-dimensional arrays, and so forth. Here's an example:
INTEGER Num1D[10] // [Column]
INTEGER Num2D[5][10] // [Row][Column]
INTEGER Num3D[2][5][10] // [Table][Row][Column]

One way to view these arrays is to think of Num2D as being a collection of five Num1D's and Num3D as
being a collection of two Num2D's.
When referencing elements of the above arrays:

NetLinx Programming Language Reference Guide 53


Language Elements

Num1D[1] refers to the 1st element


Num2D[1] refers to the 1st row
Num2D[1][1] refers to the 1st element of the 1st row
Num3D[1] refers to the 1st table
Num3D[1][1] refers to the 1st row of the 1st table
Num3D[1][1][1] refers to the 1st element of the 1st row of the 1st table

The following operations are legal:


Num2D[2] = Num1D
Num2D[5][5] = Num1D[5]
Num3D[2] = Num2D
Num3D[2][1] = Num1D
Num3D[2][1][1] = Num1D[1]

LENGTH_ARRAY and MAX_LENGTH_ARRAY are used to determine the effective and maximum lengths
of multidimensional arrays as shown in the following examples:
INTEGER Len
INTEGER My3DArray[5][3][4]

Len = MAX_LENGTH_ARRAY(My3Darray) // Len = 5


Len = MAX_LENGTH_ARRAY(My3Darray[1]) // Len = 3
Len = MAX_LENGTH_ARRAY(My3Darray[1][1]) // Len = 4
INTEGER Len
INTEGER My3DArray[5][3][4] =
{
{
{1,2,3,4},
{5,6,7,8},
{9,10,11}
},
{
{13,14}
}
}
Len = LENGTH_ARRAY(My3Darray) (* Len = 2, number of tables *)
Len = LENGTH_ARRAY(My3Darray[2]) (* Len = 1, number of rows in table 2 *)
Len = LENGTH_ARRAY(My3Darray[1][3]) (* Len = 3, number of columns in table
1, row 3 *)

54 NetLinx Programming Language Reference Guide


Language Elements

Structures
A structure provides the ability to create a new data type composed of other data types arranged in a
specified order.

A structure is declared in the DEFINE_TYPE section of the program.

Here's an example:
DEFINE_TYPE
STRUCTURE NEWSTRUCT
{
INTEGER Number
CHAR Text[20]
}

In the example above, a structure named NEWSTRUCT is declared to contain two data types, a 16-bit
number and a 20-character array. Once declared, a structure may be used in the same way as any other
data type. Here is a syntax sample:
DEFINE_VARIABLE
NEWSTRUCT MyNewStruct
NEWSTRUCT MyNewStructArray[3]

Structures can be initialized using set notation as in the two examples below. Notice that the members of
each structure, as well as, the entire array are enclosed in braces.
MyNewStruct.Number = 0
MyNewStruct.Text= 'Copyright by Company X'

MyNewStructArray[1].Number = 1
MyNewStructArray[1].Text = 'Line 1'
MyNewStructArray[2].Number = 2
MyNewStructArray[2].Text = 'Line 2'
MyNewStructArray[3].Number = 3
MyNewStructArray[3].Text = 'Line 3'

Structure members are referenced using dot-operator syntax as shown below:


MyNewStruct.Number = 0
MyNewStructArray[1].Number = 20
SET_LENGTH_STRING (MyNewStruct.Text, 16)

A syntax sample for a structure definition is shown below:


STRUCTURE <name>
{
[<type>] <Data1>
[<type>] <Data2>
[<type>] <DataN>
}

The attributes VOLATILE, PERSISTENT, and CONSTANT do not apply to the individual members of a
structure.

NetLinx Programming Language Reference Guide 55


Language Elements

Subroutines
A subroutine is a section of code that stands alone, and can be called from anywhere else in the program.
DEFINE_CALL subroutines
The DEFINE_CALL is the standard method provided by NetLinx for defining subroutines.
DEFINE_CALL '<subroutine name>' [(Param1,Param2,...)]
{
(* statements *)
}

where (Param1, Param2, ...) refers to a comma-separated list of <datatype><variable>


pairs. For example, "INTEGER Size" would be one pair.
DEFINE_CALL names must not conflict with previously defined constants, variables, buffers, or wait
names. Unlike identifiers, DEFINE_CALL names are case sensitive.
A subroutine may accept parameters. To do this, each parameter and its type must be listed within the set
of parentheses to the right of the subroutine name, as shown below:
DEFINE_CALL 'Read Input' (CHAR Buffer)[ ]
{
}

To invoke a user-defined subroutine, use the CALL keyword plus the name of subroutine and any
required calling parameters.
CALL 'Read Input' (Buf1)

In NetLinx, DEFINE_CALL supports the RETURN statement (as shown in the following example),
although return values are not supported.
DEFINE_CALL 'Read Input' (CHAR Buffer)
{
if (nChars = 0)
{
RETURN // exit subroutine
}
(* read input *)
}

SYSTEM_CALL subroutines
A SYSTEM_CALL subroutine is a special type of DEFINE_CALL subroutine defined in a separate
program file called a LIB file with a PROGRAM_NAME entry matching the subroutine name.
PROGRAM_NAME = 'COSX'

DEFINE_CALL 'COSX' (FLOAT X)


{
(* body of subroutine *)
}

To invoke a system call, use the SYSTEM_CALL keyword followed by the name in single quotes and any
calling parameters, as shown below:
SYSTEM_CALL 'COSX' (45)

System calls are resolved automatically at compile time, without requiring an INCLUDE instruction to
include the system call source file.

56 NetLinx Programming Language Reference Guide


Language Elements

For special cases where multiple copies of a system call are needed, an instance number can be specified
in the call. The compiler will compile a separate copy of the subroutine for each system call instance
number. For example, the following commands force the compiler to include two separate copies of
COSX:
SYSTEM_CALL[1] 'COSX' (45)
SYSTEM_CALL[2] 'COSX' (60)

This technique could be useful in cases where a system call contains a wait instruction that conflicts
when multiple calls to the same subroutine were made during a single wait period.
Function Subroutines
A function is similar to a DEFINE_CALL, but is intended for use either standalone or in-line as an
expression. Instead of requiring a string literal for its name, it requires a name that follows the rules for
naming constants and variables. This eliminates the need for using the CALL keyword to invoke the
subroutine. DEFINE_FUNCTION subroutines also differ from DEFINE_CALL by allowing values to be
returned using the RETURN statement (see below).

The return type may only be one of the 8 intrinsic types. Strings, arrays, structures,
classes and other user-defined types may not be returned.

Syntax:
DEFINE_FUNCTION [<return type>] FnName[(Param1,Param2,...)]
{
(* statements *)
}

You cannot declare and initialize variables in the same line.


You must group the declarations first, followed by the initialization.

Example:
DEFINE_FUNCTION INTEGER myFunction (INTEGER Var0)
{
INTEGER nBytes
STACK_VAR RESULT
nBytes = 0
RETURN = Var0 + nBytes
RETURN RESULT
}

When it is a NetLinx function, a syntax where there appears a ([ ]), the ( ) are NOT
OPTIONAL but the [ ] are optional.

The DEFINE_FUNCTION subroutine can be called as a single programming statement. For example,
the following syntax:

NetLinx Programming Language Reference Guide 57


Language Elements

ReadBuffer(Buffer,BufSize)
Can be used in an assignment statement such as:
Count = ReadBuffer(Buffer,BufSize)
or as part of an expression such as:
IF (ReadBuffer(Buffer,BufSize) > 0)
{
(* statements *)
}

The rules pertaining to calling parameters are the same for DEFINE_FUNCTION as they are for
DEFINE_CALL subroutines. The parameter list must appear in parentheses to the right of the function
name. If the function has no calling parameters a set of parentheses must still be included. For example,
MyFunc() // calling a function with no parameters

The return type may be omitted, as an alternate way of defining a subroutine. In this case the function
cannot be used as part of an expression or in an assignment statement.
DEFINE_FUNCTION also allows the use of the RETURN keyword that serves two purposes:
To return prematurely from a function.
To return a value from a function.
The format of the return statement is:
RETURN [<return value>]

If a return statement is encountered anywhere in the function, execution of the function is terminated
immediately and the value (if any) specified as the <return value> is returned to the caller.
A function that returns a value through the RETURN keyword must be declared with a return type.
Conversely, a function that is declared without a return type cannot return a value.
In the example below, GetBufferSize returns an unsigned 16-bit integer, BufSize.
The return type is indicated before the DEFINE_FUNCTION keyword.
DEFINE_FUNCTION INTEGER GetBufferSize()
LOCAL_VAR INTEGER BufSize = 0;
{
.
.
.
RETURN BufSize;
}

To call this function and to retrieve the RETURN value, use the following syntax:
BufSize = GetBufferSize()

where BufSize is declared to be of type INTEGER.


Even if a function returns a value, it is not necessary to assign the return value to a variable. Both forms
of the following call are valid. In the second case, the return value is simply thrown away.
Count = ReadBuffer(Buffer,BufSize)
ReadBuffer(Buffer,BufSize) // return value is ignored

The return type may only be one of the 8 intrinsic types (see Data Types). Strings,
arrays, structures, classes and other user-defined types may not be returned.

58 NetLinx Programming Language Reference Guide


Language Elements

Calling parameters
Parameters may be passed to any NetLinx function or subroutine. Calling parameters are simply
variables or constants that originate from the caller and are received by the function or subroutine being
invoked.
The NetLinx compiler passes all variables by reference. This means that the variable the subroutine
operates on is the same variable the caller passed. Any change made to a variable passed as a calling
parameter updates the value of the variable from the perspective of the caller. You can take advantage of
this pass by reference feature to return an updated value through a calling parameter rather than as the
return value.
Constants, on the other hand, are passed by value. When this happens, a copy of the parameter is
delivered to the subroutine. Any change made to the variable representing the constant is lost once the
function or subroutine finishes.
Function and subroutine declarations must include the type and name of each parameter expected. If the
type is omitted, the default type is assumed; arrays are CHAR type and non-array parameters are
INTEGER.
To specify an array as a function or subroutine parameter, one set of brackets for each array dimension
must follow the variable name, as shown in the following example:
DEFINE_CALL 'Process Array' (CHAR Array[ ][ ])
{
(* body of subroutine *)
}

The parameter Array is declared to be a 2-dimensional array, by including two sets of brackets after the
name. For compatibility with existing programs, the array dimensions may be specified inside the
brackets. These dimensions are not required and are ignored by the compiler. The NetLinx interpreter
will do bounds checking on the array and generate a run-time error if the array bounds are exceeded.
When calling a subroutine that takes an array as one of its parameters, pass only the name of the array as
the calling parameter, as shown below:
CHAR Buffer[10][20]
CALL 'Process Array' (Array)

If dimensions are specified in the call statement, the compiler will interpret that as specifying a subset of
the array. For example, suppose Array were defined as a 3-dimensional array. The third table of that
dimensional array could be passed to 'Process Array' as follows:
CHAR Buffer[5][5][10]
CALL 'Process Array' (Array [3])

NetLinx Programming Language Reference Guide 59


Language Elements

60 NetLinx Programming Language Reference Guide


Event Handlers

Event Handlers
The NetLinx language provides a special program section called DEFINE_EVENT to define handlers for
incoming events/notifications. These handlers are stored in an event table providing quick access to code
that must be executed when an event is received. There are handlers to support five types of events:
Button events include pushes, releases, and holds, which are associated with a push or release
on a particular device-channel.
Channel events occur when an output change (On/Off) is detected on a device-channel.
Data events include commands, strings, status, and error messages.
Level events are received as a result of a level change on a particular device.
Timeline events trigger events based on a sequence of times.

The processing of an event associated with a given member of a device, channel,


device-channel, level, or device-level array must be completed before processing can
begin on another event associated with the same array.

All incoming events are stored in a queue pending processing. Messages are processed in the order they
are received. The steps to processing an event are:
1. Check all events for a handler matching the specified event. If a handler is found, run it.
2. If there is no event handler, run MAINLINE.

Event
handler NO
Start Run Mainline
available?

YES

Run event
handler Stop

FIG. 1 Steps involved in processing an event

More than one handler can be defined for the same event. In this case, the handlers
are executed in the order in which they are defined in the program.

The event handler descriptions are:


DEVICE refers to a device specification:

DEVICE A single device number constant


D:P:S A constant device specification such as 128:1:0
DEV[ ] A device array

NetLinx Programming Language Reference Guide 61


Event Handlers

CHANNEL refers to:

CHANNEL A single channel number constant


CHAN[ ] An integer array of channel numbers
DEVCHAN[ ] A device-channel array

LEVEL refers to:

LEVEL A single level number constant


LEV[ ] An integer array of level numbers
DEVLEV[ ] A device-level array

The processing of an event associated with a given member of a device, channel,


device-channel, level, or device-array must be completed before processing can
begin on another event associated with the same array.

Button events
Button events include pushes, releases, and holds. These events are associated with a push or release on
a particular device-channel. A sample button event is shown below:
BUTTON_EVENT[DEVICE,CHANNEL] or BUTTON_EVENT[(DEVCHAN[ ])]
{
PUSH:
{
// PUSH event handler
}
RELEASE:
{
// RELEASE event handler
}
HOLD[TIME]: or HOLD[TIME, REPEAT]:
{
// HOLD event handler
}
}

A HOLD event handler specifies the actions that should be performed when a button is pressed and held
for a minimum length of time indicated by the TIME parameter (TIME is specified in .10 second
increments). The REPEAT keyword specifies that the event notification should be repeated in TIME
increments as long as the button is held.
The BUTTON object is available to the button event handler as a local variable. The following table lists
the information contained in Button Objects.

62 NetLinx Programming Language Reference Guide


Event Handlers

Button Objects
Property Name Type Description
Button.Input DEVCHAN Device + Channel
Button.Input.Channel INTEGER Channel
Button.Input.Device DEV Device
Button.Input.Device.Number INTEGER Device number
Button.Input.Device.Port INTEGER Device port
Button.Input.Device.System INTEGER System number
Button.Holdtime LONG Current hold time in .10 second increments
Button.SourceDev DEV Source device of button event
Button.SourceDev.Number INTEGER Source device number
Button.SourceDev.Port INTEGER Source device port
Button.SourceDev.System INTEGER Source device system.

If the event handler is specified using an array for DEV,CHANNEL, or a DEVCHAN array, GET_LAST
can determine which index in the array caused the event to run.
Channel events
A channel event is generated when PULSE, TO, MIN_TO, ON or OFF is called. An example channel event
is shown below:
Channel_Event[DEVICE,CHANNEL] or Channel_Event[(DEVCHAN[ ])]
{
ON:
{
// Channel ON event handler
}
OFF:
{
// Channel OFF event handler
}
}

The Channel object is available to the channel event handler as a local variable.

The following table lists the information contained in Channel events:

NetLinx Programming Language Reference Guide 63


Event Handlers

Channel Objects
Property Name Type Description
Channel.Device DEV Device
Channel.Device.Number INTEGER Device number
Channel.Device.Port INTEGER Device port
Channel.Device.System INTEGER System number
Channel.Channel INTEGER Device channel
Channel.SourceDev DEV Source Device of Channel Event
Channel.SourceDev.Number INTEGER Source Device Number
Channel.SourceDev.Port INTEGER Source Device Port
Channel.SourceDev.System INTEGER Source Device System.

If the event handler is specified using an array for DEV, CHANNEL, or a DEVCHAN array, GET_LAST
can be used to determine which index in the array caused the event to run.
Data events
The data object is available to the data event handler as a local variable. An example data event is:
DATA_EVENT[DEVICE] or DATA_EVENT[DEV[ ]]
{
COMMAND:
{
// COMMAND event handler
}
STRING:
{
// STRING event handler
}
ONLINE:
{
// ONLINE event handler
}
OFFLINE:
{
// OFFLINE event handler
}
ONERROR:
{
// ONERROR event handler
}
}

64 NetLinx Programming Language Reference Guide


Event Handlers

The following table lists the information contained in data objects:


Data Objects
Property Name Type Description
Data.Device DEV Device
Data.Device.Number INTEGER Device number
Data.Device.Port INTEGER Device port
Data.Device.System INTEGER System number
Data.Number LONG Event number
Data.SourceDev DEV Source Device of Data Event
Data.SourceDev.Number INTEGER Source Device Number
Data.SourceDev.Port INTEGER Source Device Port
Data.SourceDev.System INTEGER Source Device System
Data.Text CHAR Array Text associated with the event

The event number is a number associated with a command, error condition or the device ID
associated with an online/offline event. The numeric value is stored as either a floating-point
number or integer, as appropriate; the value can be assigned to a variable of any numeric type.
This field could be a value associated with a command event or error condition.
Text associated with the event is associated with a command, string, or error notification. It
can also be the device ID string in the case of an online/offline event.
The following table shows the fields that contain relevant information for data or notifications received
via Internet protocol (IP):
Data Objects Received Via the Internet Protocol (IP)
Property Name Type Description
Data.SourceIP CHAR Array IP address of the client/source application
Data.SourcePort LONG Server/source port number

Not all fields in the DATA object apply to all types of events. The following table lists the fields and the
corresponding events. An 'X' indicates that the field applies (or could apply) to the given event.
Data Object Fields
Property Name Command String OnLine OffLine OnError
Data.Device X X X X X
Data.Number X X X
Data.Text X X X X X
Data.SourceIP X X X X X
Data.ServerIP X X X X X
Data.SourcePort X X X X X

Level events
The level object is available to the level event handler as a local variable. Level events are triggered by a
level change on a particular device. This eliminates having to constantly evaluate a level against a
previous value. In Axcess, a level needs to be created in the DEVICE_START section and then a
conditional statement appears in the mainline to evaluate and update the level. The format of the
LEVEL_EVENT is:

NetLinx Programming Language Reference Guide 65


Event Handlers

LEVEL_EVENT[DEVICE,LEVEL] or LEVEL_EVENT[([DEVLEV[ ])]


{
// level event handler
}

It contains the information shown in the table below.


Level Objects
Property Name Type Description
Level.Input DEVLEV Device + Level that caused the event to occur
Level.Input.Device DEV Device
Level.Input.Device.Number INTEGER Device number
Level.Input.Device.Port INTEGER Device port
Level.Input.Device.System INTEGER System number
Level.Input.Level INTEGER Level number
Level.SourceDev DEV Source Device of Level Event
Level.SourceDev.Number INTEGER Source Device Number
Level.SourceDev.Port INTEGER Source Device Port
Level.SourceDev.System INTEGER Source Device System
Level.Value Numeric Level value

The numeric value is stored either as a floating-point number or integer, as appropriate; but the value can
be assigned to a variable of any numeric type.
Existing Axcess code:
DEFINE_START
.
.
CREATE_LEVEL TEMP, 1, TEMP_LEVEL
.
.
DEFINE_PROGRAM
.
.
IF (TEMP_LEVEL >= COOL_POINT)
{
ON[RELAY,FAN]
}
ELSE IF (TEMP_LEVEL <= HEAT_POINT)
{
OFF[RELAY,FAN]
}
.
.

66 NetLinx Programming Language Reference Guide


Event Handlers

NetLinx Button Event:


LEVEL_EVENT [TEMP, 1]
{
IF (LEVEL.VALUE>= COOL_POINT)
{
ON[RELAY,FAN]
}
ELSE IF (LEVEL.VALUE <= HEAT_POINT)
{
OFF[RELAY,FAN]
}
}

LEVEL_VALUE is an embedded object value in the LEVEL_EVENT statement. If the event handler is
specified using an array for DEV, CHANNEL, or a DEVCHAN array, GET_LAST can be used to determine
which index in the array caused the event to run.
Custom events
A custom event is generated by certain devices in response to query commands or unique device events.
For instance, G4 touch panels generate custom events in response to button query commands or mouse
clicks. An example channel event is shown below:
CUSTOM_EVENT[DEVICE,ADDRESS,EVENTID] or CUSTOM_EVENT[DEVCHAN,EVENTID]
{
}

The EVENTID is specific to each device. For instance, the EVENTID sent in response to a button text
query command for G4 touch panels is 1001. For more information on EVENTID values and the values
of the custom event for each EVENTID, see the programming section of the device manual with which
you are working.
The following table lists the information contained in Custom events:
Channel Objects
Property Name Type Description
Custom.Device DEV Device
Custom.Device.Number INTEGER Device number
Custom.Device.Port INTEGER Device port
Custom.Device.System INTEGER System number
Custom.ID INTEGER The address that generated the event
Custom.Type INTEGER The EVENTID of the event
Custom.Flag INTEGER A flag associated with the event
Custom.Value1 SLONG The first value associated with the event
Custom.Value2 SLONG The second value associated with the event
Custom.Value3 SLONG The third value associated with the event
Custom.Text CHAR[] Text associated with the event
Custom.Encode CHAR[] A string encoded with VARIABLE_TO_STRING encoding for
complex data types.
Custom.SourceDev DEV Source device of custom event
Custom.SourceDev.Number INTEGER Source device number
Custom.SourceDev.Port INTEGER Source device port
Custom.SourceDev.System INTEGER Source device system.

NetLinx Programming Language Reference Guide 67


Event Handlers

If the event handler is specified using an array for DEV, INTEGER, or a DEVCHAN array, GET_LAST
can determine which index in the array caused the event to run.
Event Parameters
It has already been stated that DEFINE_EVENT handlers are stored in an event table providing quick
access to code that must be executed when an event is received. The event table keeps a list of all events
in a sorted order to more quickly determine which code needs to be accessed for a giving incoming
event. The event table is built before DEFINE_START runs and it not changed anytime after that. As a
result, there are certain rules that must be applied to the parameters used in DEFINE_EVENTs.
Since the event table is built before DEFINE_START, all event parameters must contain the correct
information prior to DEFINE_START. This requires that all EVENT parameters must be defined at
compile time. In addition, many parameter "shortcuts" to help fulfill this requirement.
Using BUTTON_EVENT as an example, the simplest version of event parameters is a device and channel
reference. In the following example:
Example 1:
DEFINE_DEVICE
dvTp = 128:1:0

DEFINE_EVENT

BUTTON_EVENT[dvTp,1]
{
PUSH:
Send_String 0,'Button 1 of dvTp was pushed'
}

The device, dvTp, was defined in the DEFINE_DEVICE section, which has the effect of making it an
initialized variable of type DEV, and the channel number was a hard-coded value of 1. Since both of
these value were defined at compile time, the event is entered into the event table correctly. Let's take
another example:
Example 2:
DEFINE_DEVICE
dvTp = 128:1:0

DEFINE_VARIABLE
Integer nMyChannel

DEFINE_START
nMyChannel = 1

DEFINE_EVENT

BUTTON_EVENT[dvTp,nMyChannel]
{
PUSH:
Send_String 0,"'Button ',ITOA(nMyChannel),' of dvTp was pushed'"
}

68 NetLinx Programming Language Reference Guide


Event Handlers

In this example, the event will not perform as the previous one did. When the code is compiled, the
event parameters are dvTp, which is already assigned, and nMyChannel, which has a value of 0.
nMyChannel does not get assigned a value of 1 until DEFINE_START, at which time the event has
already been added to the event table. If you were to run this code, you would discover that it did in fact
run when button 1 was pushed, leading us to one of the "shortcuts":
<bold>

A value of 0 for a Channel or Level Number in a BUTTON_EVENT, CHANNEL_EVENT or LEVEL_EVENT


will be interpreted as an event handler for all events of that type from the given device number(s).
</bold>

So, the reason the above example runs when button 1 was pushed is that the above example runs when
any button on dvTp is pushed. This "shortcut" was added so you could define an event handler for all
buttons, channel or levels of a device without having to define a DEVCHAN of DEVLEV containing every
value you may want to handle.
To make the example 2 behave like the example 1, we simply need to make sure the value of
nMyChannel contains a value of 1 at compile time. This is simply done by initializing nMyChannel a
value of 1 in the DEFINE_VARIABLE section. The new example reads:
Example 3:
DEFINE_DEVICE
dvTp = 128:1:0

DEFINE_VARIABLE
Integer nMyChannel = 1

DEFINE_EVENT

BUTTON_EVENT[dvTp,nMyChannel]
{
PUSH:
Send_String 0,"'Button ',ITOA(nMyChannel),' of dvTp was pushed'"
}

You may be tempted to use a more traditional variable as the channel number, mainly PUSH_CHANNEL
or RELEASE_CHANNEL. It is important to realize that the identifiers are nothing more than global
(system) variable. At compile time, the values are defined and contain a value of 0. So the following
code:
Example 4:
DEFINE_EVENT

BUTTON_EVENT[dvTp,PUSH_CHANNEL]
{
PUSH:
Send_String 0,"'Button ',ITOA(BUTTON.INPUT.CHANNEL),' of dvTp was pushed'"
RELEASE:
Send_String 0,"'Button ',ITOA(BUTTON.INPUT.CHANNEL),' of dvTp was released'"
}

NetLinx Programming Language Reference Guide 69


Event Handlers

Will have the effect you expect button probably for a different reason than you expect. Although the
event will run for both the push and release of all buttons for dvTp, you may also be tempted to think that
you need to make sure the event runs for RELEASE_CHANNEL by adding the following:
Example 5:
DEFINE_EVENT
BUTTON_EVENT[dvTp,PUSH_CHANNEL]
BUTTON_EVENT[dvTp,RELEASE_CHANNEL]
{
PUSH:
Send_String 0,"'Button ',ITOA(BUTTON.INPUT.CHANNEL),' of dvTp was pushed'"
RELEASE:
Send_String 0,"'Button ',ITOA(BUTTON.INPUT.CHANNEL),' of dvTp was released'"
}

However, since both PUSH_CHANNEL and RELEASE_CHANNEL have a value of 0 at compile time, you
are in effect stacking two events that are interpreted as running for any button pushed on the panel and as
a result, the event is run twice every time a button is pushed or released. This may not seem like a big
problem until you try to toggle a variable in the event: since the event runs twice for every button push,
the variable toggles on then toggles off again.
There are some additional parameter "shortcuts" available. In all cases, the following rules apply:
When a DEV can be used, a DEV array can also be used.
When a DEVCHAN can be used, a DEVCHAN array can be used.
When a DEVLEV can be used, a DEVLEV array can be used.
When a Char, Integer or Long can be used, a Char, Integer or Long array can also be
used.
You can apply more then 1 of the above rules at a time in a given event handler.
GET_LAST() can be used to determine which index of an array (any type) caused the event to
fire.
The above rules can let you write some interesting event handler. Let's say you wanted to handle 4
buttons from 6 panels all with one button event. You could write:
Example 6:
DEFINE_DEVICE
dvPanel1 = 128:1:0
dvPanel2 = 129:1:0
dvPanel3 = 130:1:0
dvPanel4 = 131:1:0
dvPanel5 = 132:1:0
dvPanel6 = 133:1:0

DEFINE_VARIABLE
DEV dvMyPanels[] = { dvPanel1, dvPanel2, dvPanel3, dvPanel4, dvPanel5, dvPanel6
}
INTEGER nMyButtons[] = { 4, 3, 2, 1 }
INTEGER nPanelIndex
INTEGER nButtonIndex

DEFINE_EVENT
Continued

70 NetLinx Programming Language Reference Guide


Event Handlers

BUTTON_EVENT[dvMyPanels,nMyButtons]
{
PUSH:
{
nPanelIndex = GET_LAST(dvMyPanels)
nButtonIndex = GET_LAST(nMyButtons)
Send_String 0,"'Button Index=',ITOA(nButtonIndex),' was pushed on Panel
Index=',ITOA(nPanelIndex)"
}
}

This event will be run for all combinations of dvMyPanel and nMyButtons, 24 buttons in all. The
GET_LAST() function is very useful when running event using array as parameters. GET_LAST()
returns an index value, starting at 1, for the element that triggered the event. In the case of
nButtonIndex, it will contain a value of 1 when button 4 was pressed, a value of 2 when button 3 was
pressed, ... This can be very useful in the case of transmitters and wired panels where the channel
number may not reflect a numerical sequence you would like, such as with Numeric Keypads.

Timeline Functions
The NetLinx timeline functions provide a mechanism for triggering events based upon a sequence of
times. The sequence of times is passed into the timeline functions as an array of LONG values, with each
value representing a time period (in milliseconds) that is either relative to the start time of the timeline or
to the previously triggered event.

Timelines introduce the capability to dynamically set up a timed sequence, provide


the user with a mechanism to modify the sequence, and allow the user to create,
delete, and modify sequences.

The old way of programming timed sequences was to cascade or nest WAITs. Using nested WAITs hard-
coded the timed sequence; so, the only way to modify the timing was to modify the NetLinx program,
recompile, and download.
Timelines make adding, deleting and editing the sequence much simpler for the programmer. Timeline
functions and debugging allow the timings to be modified without the modify/ compile/ download cycle
because the array of times may be modified via NetLinx debugging. Once the timings have been
tweaked, the changes can be incorporated in the NetLinx program.
Creating a timeline
Timelines are represented by the illustration in (FIG. 2). When the TIMELINE_CREATE function is
executed, the timeline starts at zero and begins counting. When the timer value equals a value in the
TIMES array, a TIMELINE_EVENT is triggered. Within the timeline event, a TIMELINE structure is
available to get information about the specific time from the TIMES array that generated the event. When
a relative timeline is created, the NetLinx Master converts the provided relative times into absolute times
that are stored internally.
The TIMELINE structure contains the following members:
STRUCTURE TIMELINE
{
INTEGER ID //user supplied ID
INTEGER SEQUENCE //index in Times array
LONG TIME //time since start of timeline
INTEGER RELATIVE //0=absolute 1=relative
LONG REPETITION //# of loops for repeating timeline
Continued

NetLinx Programming Language Reference Guide 71


Event Handlers

TIMELINE_EVENT[TL1]
Triggered

TIMELINE_CREATE

Time 0
1000 2000 3000 4000 5000
Time (1mS resolution)

Timeline.Sequence = 1 2 3 4 5

FIG. 2 Timeline representation

}
Each TIMELINE data member is defined as follows:

ID The ID that the user assigned to the timeline in the TIMELINE_CREATE func-
tion.
SEQUENCE The index of the time in the Times array that was passed to the
TIMELINE_CREATE function. The SEQUENCE data member is used to deter-
mine what action to take for the event and is normally decoded with a SWITCH/
CASE structure (as shown in the example).
TIME The amount of time that has elapsed since the timeline started. For repeating
timelines, the TIME and REPETITION data members can be used to calculate
the total amount of time it has been running.
RELATIVE If the timeline is operating in relative mode, this data member is equal to
TIMELINE_RELATIVE. If the timeline is absolute, it is equal to
TIMELINE_ABSOLUTE.
REPETITION If the timeline was created with TIMELINE_REPEAT, this data member holds
the number of times the timeline has been executed. REPETITION contains
zero for the first pass through the timeline. Thus, the calculation to determine
the total amount of time the timeline has been running is simply:
TIMELINE.TIME * TIMELINE.REPETITION.

Return Valuess:

0 Successful
1 Timeline ID already in use
2 Specified array is not an array of LONGs
3 Specified length is greater than the length of the passed array
4 Out of memory

Example:
DEFINE_VARIABLE
LONG TimeArray[100]

DEFINE_CONSTANT
TL1 = 1
TL2 = 2

DEFINE_EVENT

Continued

72 NetLinx Programming Language Reference Guide


Event Handlers

TIMELINE_EVENT[TL1] // capture all events for Timeline 1


{
switch(Timeline.Sequence) // which time was it?
{
case 1: { SEND_COMMAND dvPanel,"'TEXT1-1 1'" }
case 2: { SEND_COMMAND dvPanel,"'TEXT1-1 2'" }
case 3: { SEND_COMMAND dvPanel,"'TEXT1-1 3'" }
case 4: { SEND_COMMAND dvPanel,"'TEXT1-1 4'" }
case 5: { SEND_COMMAND dvPanel,"'TEXT1-1 5'" }
}
}
TIMELINE_EVENT[TL2]
{
switch(Timeline.Sequence)
{
case 1: { SEND_COMMAND dvPanel,"'TEXT2-2 1'" }
case 2: { SEND_COMMAND dvPanel,"'TEXT2-2 2'" }
case 3: { SEND_COMMAND dvPanel,"'TEXT2-2 3'" }
case 4: { SEND_COMMAND dvPanel,"'TEXT2-2 4'" }
case 5: { SEND_COMMAND dvPanel,"'TEXT2-2 5'" }
}
}

DEFINE_PROGRAM

PUSH[dvPanel,1]
{
TimeArray[1] = 1000
TimeArray[2] = 2000
TimeArray[3] = 3000
TimeArray[4] = 4000
TimeArray[5] = 5000
TIMELINE_CREATE(TL1, TimeArray, 5, TIMELINE_ABSOLUTE,
TIMELINE_REPEAT)
}

PUSH[dvPanel,2]
{
TimeArray[1] = 1000
TimeArray[2] = 1000
TimeArray[3] = 1000
TimeArray[4] = 1000
TimeArray[5] = 1000
TIMELINE_CREATE(TL2, TimeArray, 5, TIMELINE_RELATIVE, TIMELINE_ONCE)
}

The example above creates two timelines (TL1 and TL2) that trigger events at the same rate (once per
second).

NetLinx Programming Language Reference Guide 73


Event Handlers

TL1 uses TIMELINE_ABSOLUTE to specify that the times in TimeArray are absolute with
respect to the start of the timeline. Since TL1 specifies the TIMELINE_REPEAT, it is also
repeating and will generate a TIMELINE_EVENT every second iterating through all five times
in a round-robin fashion: 1,2,3,4,5,1,2,3,4,5,1,2,3, and so on.
TL2 uses TIMELINE_RELATIVE to specify that the times in TimeArray are relative to each
other (i.e. each events occurs 1000 milliseconds after the previous). Since TL2 specifies the
TIMELINE_ONCE parameter, it will execute the entire timeline once, then stop: 1,2,3,4,5.

TIMELINE example
The following code is an example of how to use TIMELINE functions.
PROGRAM_NAME='TimelineExample'
(*{{PS_SOURCE_INFO(PROGRAM STATS) *)
(***********************************************************)
(* FILE CREATED ON: 05/22/2001 AT: 12:05:56 *)
(***********************************************************)
(* FILE_LAST_MODIFIED_ON: 05/22/2001 AT: 12:15:56 *)
(***********************************************************)
(* ORPHAN_FILE_PLATFORM: 1 *)
(***********************************************************)
(*!!FILE REVISION: *)
(* REVISION DATE: 05/22/2001 *)
(* *)
(* COMMENTS: *)
(* *)
(***********************************************************)
(*}}PS_SOURCE_INFO *)
(***********************************************************)
(***********************************************************)
(* DEVICE NUMBER DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_DEVICE

dvPanel = 128:1:0
dvDebug = 0:0:0

(***********************************************************)
(* CONSTANT DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_CONSTANT

MY_LINE_1 = 1
MY_LINE_2 = 2

(***********************************************************)
(* VARIABLE DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_VARIABLE

Continued

74 NetLinx Programming Language Reference Guide


Event Handlers

LONG TimeArray[100]
INTEGER iLoop

(***********************************************************)
(* STARTUP CODE GOES BELOW *)
(***********************************************************)
DEFINE_START

(***********************************************************)
(* THE EVENTS GOES BELOW *)
(***********************************************************)
DEFINE_EVENT

TIMELINE_EVENT[MY_LINE_1]
{
switch(Timeline.Sequence)
{
case 1: { SEND_COMMAND dvPanel,"'TEXT1-1 1'" }
case 2: { SEND_COMMAND dvPanel,"'TEXT1-1 2'" }
case 3: { SEND_COMMAND dvPanel,"'TEXT1-1 3'" }
case 4: { SEND_COMMAND dvPanel,"'TEXT1-1 4'" }
case 5: { SEND_COMMAND dvPanel,"'TEXT1-1 5'" }
}
SEND_STRING dvDebug,"'Timer ',ITOA(Timeline.ID),' Event
',ITOA(Timeline.Sequence), ' Time= ',ITOA(Timeline.Time),
'Repetition = ',ITOA(Timeline.Repetition),' Relative =
',ITOA(Timeline.Relative)"
}

TIMELINE_EVENT[MY_LINE_2]
{
switch(Timeline.Sequence)
{
case 1: { SEND_COMMAND dvPanel,"'TEXT2-2 1'" }
case 2: { SEND_COMMAND dvPanel,"'TEXT2-2 2'" }
case 3: { SEND_COMMAND dvPanel,"'TEXT2-2 3'" }
case 4: { SEND_COMMAND dvPanel,"'TEXT2-2 4'" }
case 5: { SEND_COMMAND dvPanel,"'TEXT2-2 5'" }
}

SEND_STRING dvDebug,"'Timer ',ITOA(Timeline.ID),' Event


',ITOA(Timeline.Sequence), ' Time = ',ITOA(Timeline.Time),
' Repetition = ',ITOA(Timeline.Repetition),' Relative =
',ITOA(Timeline.Relative)"
}
(***********************************************************)
(* THE ACTUAL PROGRAM GOES BELOW *)
(***********************************************************)

Continued

NetLinx Programming Language Reference Guide 75


Event Handlers

DEFINE_PROGRAM

(***********************************************************)
(* create will sort the order of the times but index stays *)
(* with the time. This example will execute 1 2 4 3 5 *)
(* sequence numbers *)
(***********************************************************)
PUSH[dvPanel,1]
{
TimeArray[1] = 1000
TimeArray[2] = 2000
TimeArray[4] = 3000
TimeArray[3] = 4000
TimeArray[5] = 5000
TIMELINE_CREATE(MY_LINE_1,TimeArray,5,TIMELINE_ABSOLUTE,TIMELINE_ONCE)
}

PUSH[dvPanel,2]
{
TimeArray[1] = 1000
TimeArray[2] = 2000
TimeArray[3] = 3000
TimeArray[4] = 4000
TimeArray[5] = 5000
TIMELINE_CREATE(MY_LINE_2,TimeArray,5,TIMELINE_ABSOLUTE,TIMELINE_REPEAT)
}

(***********************************************************)
(* Modify the timeline my kill, pause and restarting *)
(***********************************************************)
PUSH[dvPanel,3]
{
IF(TIMELINE_ACTIVE(MY_LINE_1))TIMELINE_KILL(MY_LINE_1)
IF(TIMELINE_ACTIVE(MY_LINE_2))TIMELINE_KILL(MY_LINE_2)
}

PUSH[dvPanel,4]
{
IF(TIMELINE_ACTIVE(MY_LINE_1))TIMELINE_PAUSE(MY_LINE_1)
IF(TIMELINE_ACTIVE(MY_LINE_2))TIMELINE_PAUSE(MY_LINE_2)
}

PUSH[dvPanel,5]
{
IF(TIMELINE_ACTIVE(MY_LINE_1))TIMELINE_RESTART(MY_LINE_1)
IF(TIMELINE_ACTIVE(MY_LINE_2))TIMELINE_RESTART(MY_LINE_2)
Continued

76 NetLinx Programming Language Reference Guide


Event Handlers

(***********************************************************)
(* Force time to a different value *)
(***********************************************************)
PUSH[dvPanel,6]
{
IF (TIMELINE_ACTIVE(MY_LINE_1))
TIMELINE_SET(MY_LINE_1,2000)
}

(***********************************************************)
(* Get the current time from create *)
(***********************************************************)
PUSH[dvPanel,7]
{
SEND_COMMAND dvPanel,"'TEXT3-','Timer 1 Time is
',ITOA(TIMELINE_GET(MY_LINE_1))"
SEND_COMMAND dvPanel,"'TEXT4-','Timer 2 Time is
',ITOA(TIMELINE_GET(MY_LINE_2))"
}

(***********************************************************)
(* Pause and restart the timeline at new locations *)
(***********************************************************)
PUSH[dvPanel,8]
{
TIMELINE_PAUSE(MY_LINE_1)
TIMELINE_PAUSE(MY_LINE_2)
TIMELINE_SET(MY_LINE_1,0)
TIMELINE_SET(MY_LINE_2,0)
TIMELINE_RESTART(MY_LINE_1)
TIMELINE_RESTART(MY_LINE_2)
}

(***********************************************************)
(* END OF PROGRAM *)
(* DO NOT PUT ANY CODE BELOW THIS COMMENT *)
(***********************************************************)

NetLinx Programming Language Reference Guide 77


Event Handlers

TIMELINE IDs
When creating a TIMELINE_EVENT, the timeline ID must be a user defined long constant. The NetLinx
compiler will not semantic check the type of the timeline ID, and the NetLinx runtime system will
attempt to cast the contents of the timeline ID constant, to a long constant. A runtime error will occur if
the cast is unsuccessful.
Here's an example of TIMELINE code:
DEFINE_VARIABLE
CONSTANT LONG TimelineID_1 = 1
CONSTANT LONG TimelineID_2 = 2
CONSTANT LONG TimelineID_3 = 3
CONSTANT LONG TimelineID_4 = 4
LONG TimeArray[4] =
{
1000, // 1 second
2000, // 2 seconds
3000, // 3 seconds
4000 // 4 seconds
}
DEFINE_START
TIMELINE_CREATE
(TimelineID_1,TimeArray,LENGTH_ARRAY(TimeArray),TIMELINE_RELATIVE,TIMELINE_REP
EAT)
TIMELINE_CREATE
(TimelineID_2,TimeArray,LENGTH_ARRAY(TimeArray),TIMELINE_RELATIVE,TIMELINE_REP
EAT)
TIMELINE_CREATE
(TimelineID_3,TimeArray,LENGTH_ARRAY(TimeArray),TIMELINE_RELATIVE,TIMELINE_REP
EAT)
TIMELINE_CREATE
(TimelineID_4,TimeArray,LENGTH_ARRAY(TimeArray),TIMELINE_RELATIVE,TIMELINE_REP
EAT)
DEFINE_EVENT
// typical TIMELINE_EVENT statement
TIMELINE_EVENT[TimelineID_1] // capture all events for Timeline 1
{
SEND_STRING 0,"'TL ID = ', itoa(timeline.id),', sequence =
',itoa(timeline.sequence)"
}
// example of "stacked" TIMELINE_EVENT statements
TIMELINE_EVENT[TimelineID_2] // capture all events for Timeline 2
TIMELINE_EVENT[TimelineID_3] // capture all events for Timeline 3
TIMELINE_EVENT[TimelineID_4] // capture all events for Timeline 4
{
SEND_STRING 0,"'TL ID = ', itoa(timeline.id),', sequence =
',itoa(timeline.sequence)"
}
// end

78 NetLinx Programming Language Reference Guide


Combining Devices, Levels, and Channels

Combining Devices, Levels, and Channels


The Axcess language supports the concept of combining several panels to make them behave as if they
were one panel, in order to simplify code. This feature allows the combination of functionally identical
devices, such as identically programmed Touch Panels and Softwire Panels. When the program
references one of these devices, all other combined device arrays are also referenced.
In Axcess, device combine operations are done in the DEFINE_COMBINE section of the code, and can
produce mixed results (any time one or more panels are dropped off-line).
The NetLinx language further addresses the issues surrounding combining panels (and their associated
channels and levels), and allows you to combine and un-combine panels on the fly. The primary
difference between the way that the Axcess and NetLinx languages handles combine operations is that
NetLinx utilizes the concept of the virtual device. A virtual device is a device that does not physically
exist but merely represents one or more devices.

If you have combined Devices, Levels and/or Channels, they must be un-combined
before they can be added as part of a new COMBINE function.

Combining and Un-Combining Devices


To approach setting up combine and un-combine operations in NetLinx, let's first look at the way that
combine operations are done in the Axcess language.
Combining devices
The example below illustrates how an Axcess program combines three touch panels to act as one.
DEFINE_DEVICE
TP1 = 128
TP2 = 129
TP3 = 130

DEFINE_COMBINE
(TP1, TP2, TP3)

DEFINE_PROGRAM
RELEASE[TP1,1]
{
(*Do Something*)
}

The code shown in the Axcess example will not work in NetLinx, due to
incompatibilities between the languages (i.e. Axcess does not allow virtual devices,
which are required for Combine/Uncombine operations in NetLinx).

This combines a common level to each of three devices TP1 , TP2 , and TP3 . If an input change occurs
on any of the three devices, Axcess sees the input as coming only from the first device in the list (TP1).
If button [TP2,12] is pressed, Axcess will see the input coming from [TP1,12] due to the
combination. Likewise, any output change sent to any device in the list will automatically be sent to all

NetLinx Programming Language Reference Guide 79


Combining Devices, Levels, and Channels

devices in the list. This includes level changes. For example, the statement ON [TP1,5Ø] will turn on
channel 50 for all three devices in the list.
Now let's see how the code example shown above would translate into NetLinx.
DEFINE_COMBINE
DEFINE_DEVICE

VIRTUAL1 = 33000
TP1 = 128
TP2 = 129
TP3 = 130

DEFINE_COMBINE
(VIRTUAL1, TP1, TP2, TP3)

DEFINE_PROGRAM
RELEASE[VIRTUAL1,1]
{
(*Do Something*)
}

Note the use of the virtual device (VIRTUAL1) in the above example. Combine operations in NetLinx
require that the first device in the list (the primary device) must be a virtual device. By specifying a
virtual device as the primary device in a DEFINE_COMBINE statement, NetLinx code can be written
targeting the virtual device, but effectively operating on each physical device. Furthermore, since a
virtual device is not an actual physical device, the primary device cannot be taken off-line or removed
from the system (which avoids the potential problems that occurred in Axcess).
The virtual device's address number must be in the range of 32768 to 36863.
The example above combines the three touch panel devices: TP1, TP2 and TP3. Whenever an input
change occurs on any of the three devices, NetLinx detects the input as coming only from VIRTUAL1.
For example, if button [TP3, 5] is pressed, NetLinx sees input coming from [VIRTUAL1, 5] as a
result of the combination.
Output changes (including level changes) sent to any device in the list will automatically be sent to all
devices in the list. For instance, the statement: ON [VIRTUAL1, 50] turns on channel 50 on all three
panels and OFF [VIRTUAL1, 10] turns off channel 10 on all three panels.
The example below illustrates the use of a device array (Dev[ ]), instead of specifying the individual
devices (TP1, TP2, and TP3). Device arrays can further simplify your code and allow you to
dynamically combine/un-combine devices. Any input events for any device in the array will appear to
the program as coming from the virtual device. Output changes, directed to the virtual device or any
device in the array, are sent to all devices in the array. Here's a syntax example:
COMBINE_DEVICES (VIRTUAL1, TP1, TP2, TP3)

In addition to virtual devices and device arrays, the NetLinx language contains several new keywords for
combine and un-combine operations:
COMBINE_DEVICES, UNCOMBINE_DEVICES
COMBINE_LEVELS, UNCOMBINE_LEVELS
COMBINE_CHANNELS, UNCOMBINE_CHANNELS

80 NetLinx Programming Language Reference Guide


Combining Devices, Levels, and Channels

Refer to the Combining and Un-Combining Levels section on page 82 for more
information.

Un-combining devices
UNCOMBINE_DEVICES reverses the effect of COMBINE_DEVICES. All combines related to the
specified virtual device are disabled. A syntax example is:
UNCOMBINE_DEVICES (VDC)
Parameters:

VDC The virtual device-channel passed to COMBINE_DEVICES.

COMBINE_DEVICES (VDC, DCSet)


.
.
UNCOMBINE_DEVICES (VDC)

The following NetLinx code example illustrates combining and un-combining the panels from the
previous example:

Input and output changes occurring on non-combined panels will not affect combined
panels, and vice versa.

DEFINE_DEVICE
VIRTUAL1 = 33000
TP1 = 128
TP2 = 129
TP3 = 130

TP4 = 131

DEFINE_PROGRAM
(* Activate dynamic device combine*)
RELEASE[TP4,1]
{
COMBINE_DEVICES(VIRTUAL1, TP1, TP2, TP3)
}
(*Remove dynamic device combine*)

RELEASE[TP4,1]
{
UNCOMBINE_DEVICES(VIRTUAL1)
}
(*Pushes come here when a combine is active*)

Continued

NetLinx Programming Language Reference Guide 81


Combining Devices, Levels, and Channels

RELEASE[VIRTUAL1,1]
{
(*Do Something*)
}
(*This will only see pushes when combine is NOT active*)
RELEASE[TP1,1]
{
(*Do Something*)
}

Combining and Un-Combining Levels


To approach setting up level combine and un-combine operations in NetLinx, let's first look at the way
that level combine operations are done in the Axcess language. The example below illustrates how an
Axcess program would combine three Touch Panel levels to act as one.

The code shown in the Axcess example will not work in NetLinx, due to
incompatibilities between the languages (i.e. Axcess does not allow virtual devices,
which are required for Combine/Uncombine operations in NetLinx).

DEFINE_DEVICE
TP1 = 128
TP2 = 129
TP3 = 130

DEFINE_CONNECT_LEVEL
(TP1,1, TP2,1, TP3,1)

TP1, TP2, and TP3 are devices; this example combines Level 1 on each device. If a level change occurs
on any of the three devices, Axcess sees the level coming only from the first device in the list (TP1).
Likewise, any level change sent to any device in the list will automatically be sent to all devices in the
list.
Now let's see how the code example shown above would translate into NetLinx. This is code that would
function correctly within a NetLinx system, but still uses the Axcess-based.
DEFINE_CONNECT_LEVEL
DEFINE_DEVICE
VIRTUAL1 = 33000
TP1 = 128
TP2 = 129
TP3 = 130

DEFINE_CONNECT_LEVEL
(VIRTUAL1, 1, TP1,1, TP2,1, TP3,1)

The example above combines the levels for the three touch panels: TP1, TP2 and TP3. Whenever a level
change occurs on any of the three devices, NetLinx detects the level as coming only from VIRTUAL1.
The example below illustrates the use of a device array (Dev[ ]), instead of specifying the individual
devices (TP1, TP2, and TP3). Device arrays further simplify code and allow you to dynamically
combine/un-combine levels. Any input events for any device in the array will appear to the program as

82 NetLinx Programming Language Reference Guide


Combining Devices, Levels, and Channels

coming from the virtual device. Output changes, directed to the virtual device or any device in the array,
are sent to all devices in the array. The syntax must follow one of these two forms:
DEFINE_CONNECT_LEVEL
(Vdevice1, 1, DEVLEV [ ])

- or -
DEFINE_CONNECT_LEVEL
(VDEVLEV, DEVLEV [ ])

Combining levels
COMBINE_LEVELS connects a single device-level array (DEVLEV[ ]) to a DEVLEV array.
Any element in a DEVLEV array appears to come from the virtual device-level representing the group,
and output to any element in a DEVLEV array is directed to all elements in the group. Here's a syntax
example:
COMBINE_LEVELS (DEVLEV VDLSET, DEVLEV[ ] DLSETS)

Parameters:

VDLSET Virtual device-level. Each element will represent one device-level combine group.
DLSETS Device-level sets containing the device-level pairs to combine. Corresponding ele-
ments in each set are combined with the corresponding element in the virtual device-
level array.

Un-combining levels
UNCOMBINE_LEVELS undoes the effect of COMBINE_LEVELS. All combines related to the specified
virtual device-level are disabled.
UNCOMBINE_LEVELS (DEVLEV)
Parameters:

VDL The virtual device-level passed to COMBINE_LEVELS.


DEVLEV The device-level passed to COMBINE_LEVELS.

COMBINE_LEVELS(VDL, DLSet)
.
.
UNCOMBINE_LEVELS(VDL)

The NetLinx code example below illustrates how to dynamically combine and un-combine levels.

Input and output changes occurring on non-combined panels will not affect combined
panels, and vice versa.

DEFINE_DEVICE
VIRTUAL1 = 33000
TP1 = 128
TP2 = 129
TP3 = 130

Continued

NetLinx Programming Language Reference Guide 83


Combining Devices, Levels, and Channels

TP4 = 131

DEFINE_PROGRAM
(*Activate dynamic level combine*)
RELEASE[TP4,1]
{
COMBINE_LEVELS(VIRTUAL1,1,TP1,1,TP2,1,TP3,1)
}

(*Remove dynamic level combine*)


RELEASE[TP4,1]
{
UNCOMBINE_LEVELS(VIRTUAL1,1)
}

Combining and Un-combining Channels


Combining channels
COMBINE_CHANNELS connects a single virtual device-channel to one or more channels on another
device (or devices).
Stated another way, COMBINE_CHANNELS combines a single virtual DEVCHAN or [DEV,CHAN] pair to
one or more DEVCHANs or [DEV,CHAN] pairs.
Any element in a DEVCHAN[ ] set combined appears to come from the virtual device-channel
representing the group, and output to the virtual device-channel is directed to all elements in the
DEVCHAN[] set.
COMBINE_CHANNELS (DEVCHAN VDC, DEVCHAN[ ] DCSets)
Parameters:
When using COMBINE_XXXX and UNCOMBINE_XXXX functions dynamically
based upon a button event, the combining and combining must be done on the
release of the button (the active event must be complete before a COMBINE_XXXX
or UNCOMBINE_XXXX function is invoked).

VDC Virtual device-channel that represents one device-channel combine group.


DCSets Device-channel array containing the device-channel pairs to combine. The VDC is
combined with each element in the device-channel array.

Un-combining channels
UNCOMBINE_CHANNELS reverses the effect of COMBINE_CHANNELS. All combines related to the
specified virtual device-channel are disabled.
UNCOMBINE_CHANNELS (DEVCHAN VDC)
Parameters:

VDC The virtual device-channel passed to COMBINE_CHANNELS.

.
UNCOMBINE_CHANNELS (VDC)

84 NetLinx Programming Language Reference Guide


Combining Devices, Levels, and Channels

The 6 examples in the program below demonstrate the use of COMBINE_CHANNELS and
UNCOMBINE_CHANNELS:
PROGRAM_NAME='CombineChannelsExample'
DEFINE_DEVICE // common devices for all examples below
dvTP = 128:1:0
dvREL10 = 301:1:0
dvIO10 = 310:1:0
vdvControl = 33000:1:0
// example of combining a DEVCHAN set to a virtual [DEV,CHAN] pair
DEFINE_VARIABLE
DEVCHAN dc1[] = {{dvIO10,1},{dvREL10,1},{dvTP,1}}
DEFINE_EVENT
BUTTON_EVENT[dvTP,11] // combine_channels 1
{
RELEASE:
{
COMBINE_CHANNELS (vdvControl,1,dc1)
}
}
BUTTON_EVENT[dvTP,12] // uncombine_channels 1
{
RELEASE:
{
UNCOMBINE_CHANNELS (vdvControl,1)
}
}
BUTTON_EVENT[vdvControl,1] // this will work when the combine_channels above is
invoked
{
PUSH:
{
TO[BUTTON.INPUT]
}
}
// example of combining individual DEVCHANs to a virtual [DEV,CHAN] pair
DEFINE_VARIABLE
DEVCHAN dc2[] = {{dvIO10,2},{dvREL10,2},{dvTP,2}}
DEFINE_EVENT
BUTTON_EVENT[dvTP,13] // combine_channels 2
{
RELEASE:
{
COMBINE_CHANNELS (vdvControl,2,dc2[1],dc2[2],dc2[3])
}
}
Continued

NetLinx Programming Language Reference Guide 85


Combining Devices, Levels, and Channels

BUTTON_EVENT[dvTP,14] // uncombine_channels 2
{
RELEASE:
{
UNCOMBINE_CHANNELS (vdvControl,2)
}
}
BUTTON_EVENT[vdvControl,2] // this will work when the combine_channels above is
invoked
{
PUSH:
{
TO[BUTTON.INPUT]
}
}

// example of combining individual [DEV,CHAN] pairs to a virtual [DEV,CHAN] pair


DEFINE_VARIABLE
DEVCHAN dc3[] = {{dvIO10,3},{dvREL10,3},{dvTP,3}}
DEFINE_EVENT
BUTTON_EVENT[dvTP,15] // combine_channels 3
{
RELEASE:
{
COMBINE_CHANNELS (vdvControl,3,
dc3[1].DEVICE,
dc3[1].CHANNEL,
dc3[2].DEVICE,
dc3[2].CHANNEL,
dc3[3].DEVICE,
dc3[3].CHANNEL)
}
}
BUTTON_EVENT[dvTP,16] // uncombine_channels 3
{
RELEASE:
{
UNCOMBINE_CHANNELS (vdvControl,3)
}
}
BUTTON_EVENT[vdvControl,3] // this will work when the combine_channels above is
invoked
Continued

86 NetLinx Programming Language Reference Guide


Combining Devices, Levels, and Channels

{
PUSH:
{
TO[BUTTON.INPUT]
}
}
// example of combining a DEVCHAN set to a virtual DEVCHAN
DEFINE_VARIABLE
DEVCHAN vdc4 = {vdvControl,4}
DEVCHAN dc4[] = {{dvIO10,4},{dvREL10,4},{dvTP,4}}
DEFINE_EVENT
BUTTON_EVENT[dvTP,17] // combine_channels 4
{
RELEASE:
{
COMBINE_CHANNELS (vdc4,dc4)
}
}
BUTTON_EVENT[dvTP,18] // uncombine_channels 4
{
RELEASE:
{
UNCOMBINE_CHANNELS (vdc4)
}
}
BUTTON_EVENT[vdc4] // this will work when the combine_channels above is invoked
{
PUSH:
{
TO[BUTTON.INPUT]
}
}

// example of combining individual DEVCHANs to a virtual DEVCHAN


DEFINE_VARIABLE
DEVCHAN vdc5 = {vdvControl,5}
DEVCHAN dc5[] = {{dvIO10,5},{dvREL10,5},{dvTP,5}}
DEFINE_EVENT
BUTTON_EVENT[dvTP,19] // combine_channels 5
Continued

NetLinx Programming Language Reference Guide 87


Combining Devices, Levels, and Channels

{
RELEASE:
{
COMBINE_CHANNELS (vdc5,dc5[1],dc5[2],dc5[3])
}
}
BUTTON_EVENT[dvTP,20] // uncombine_channels 5
{
RELEASE:
{
UNCOMBINE_CHANNELS (vdc5)
}
}
BUTTON_EVENT[vdc5] // this will work when the combine_channels above is invoked
{
PUSH:
{
TO[BUTTON.INPUT]
}
}
// example of combining individual [DEV,CHAN] pairs to a virtual DEVCHAN
DEFINE_VARIABLE
DEVCHAN vdc6 = {vdvControl,6}
DEVCHAN dc6[] = {{dvIO10,6},{dvREL10,6},{dvTP,6}}
DEFINE_EVENT
BUTTON_EVENT[dvTP,21] // combine_channels 6
{
RELEASE:
{
COMBINE_CHANNELS (vdc6,
dc6[1].DEVICE,
dc6[1].CHANNEL,
dc6[2].DEVICE,
dc6[2].CHANNEL,
dc6[3].DEVICE,
dc6[3].CHANNEL)
}
}
BUTTON_EVENT[dvTP,16] // uncombine_channels 6
{
RELEASE:
{
UNCOMBINE_CHANNELS (vdc6)
}
}
Continued

88 NetLinx Programming Language Reference Guide


Combining Devices, Levels, and Channels

BUTTON_EVENT[vdc6] // this will work when the combine_channels above is invoked


{
PUSH:
{
TO[BUTTON.INPUT]
}
}
// end

NetLinx Programming Language Reference Guide 89


Combining Devices, Levels, and Channels

90 NetLinx Programming Language Reference Guide


Master-To-Master (M2M)

Master-To-Master (M2M)
The functionality of Master-to-Master (M2M) includes several new features including Master routing
and intersystem control. Master routing supports the ability to route messages to any other Master or
device and is the foundation of all M2M functionality. Intersystem control allows a Master, or its
NetLinx program, to control and get status of any other device (or master) connected to another Master.
The illustration below depicts a typical system of two interconnected NetLinx control systems with
several devices connected to each one.
The top portion of the illustration shows the physical connections and the devices represented. The
bottom portion shows the logical connections that have been assigned.

FIG. 1 Physical and logical connections

NetLinx Programming Language Reference Guide 91


Master-To-Master (M2M)

Master Routing
Master routing primarily involves the communication of routing tables between masters. Routing tables
are exchanged between masters upon their initial connection, and updates to the routing tables are
exchanged as the connections change.
NetLinx masters do not automatically connect to other NetLinx masters by virtue of being on the same
network. The URL List of the NetLinx master is used to force the master to initiate a TCP connection to
the specified URL/IP address. Therefore, the first step in assembling an M2M system is to setup the
URL in at least one of the masters to point to the other master. For example, in FIG. 1 NetLinx Master
System #1 could have its URL set with a single entry that contains the IP address of the NetLinx Master
System #7.
Note that any TCP/IP device, including NetLinx masters, that utilizes DHCP to obtain its TCP/IP
configuration are subject to having their IP address change at any time. Therefore, a NetLinx master's IP
address must be static, unless the network supports Dynamic DNS and a DHCP server capable of
updating the DNS tables on behalf of the DHCP client. If Dynamic DNS/DHCP servers are available, the
NetLinx master's host name may be used in the URL list. As of this writing, only Windows 2000's DNS
server/DHCP servers support the required dynamic capabilities.
Once the systems are connected, they exchange routing information so each master will learn about all
the masters connected to the other. As a diagnostic aid, the "show route" command can be issued from a
Telnet session to show how masters are connected to each other. Consider the following system of
interconnected NetLinx masters:

NetLinx Master
System #1
192.168.12.105

NetLinx Master NetLinx Master


System #2 System #3
192.168.12.76 192.168.12.105

NetLinx Master NetLinx Master NetLinx Master


System #5 System #106 System #111
192.168.12.79 192.168.12.106 192.168.12.105

NetLinx Master
System #4
192.168.12.80

FIG. 2 System of interconnected NetLinx Masters

In FIG. 2, arrows depict the direction of the initiated connection. I.e. System #1 initiated the connection
to System #2 by having the IP address of System #2 in its URL List.
The following sample output is from a Telnet session connected to System #5. The connection of the
NetLinx system is depicted in FIG. .
>show route
System Route Metric PhyAddress
-----------------------------------------
1 2 2 TCP Socket=18 IP=192.168.12.76 Index=3
2 2 1 TCP Socket=18 IP=192.168.12.76 Index=3
3 2 2 TCP Socket=18 IP=192.168.12.76 Index=3
4 4 1 TCP Socket=16 IP=192.168.12.80 Index=1
->5 5 0 AXlink
106 106 1 TCP Socket=19 IP=192.168.12.106 Index=2
111 106 2 TCP Socket=19 IP=192.168.12.106 Index=2

92 NetLinx Programming Language Reference Guide


Master-To-Master (M2M)

-> The "->" to the left of system # 5 indicates that system # 5 is the local system
(i.e. the system that the telnet session is connected to).

System column Lists all of the systems in the master's routing table.

Route column Indicates which system number packets are to be routed to in order to get to their
destination. For example, to send a message from System #5 to System #1, the
message must be sent to/through System #2. You can see this by examining the
Route entry for System #1 in the "show route" table.

Metric column Indicates the number of system masters the message must transverse in order to
get to its destination. For the example above, the metric is 2 because the message
must enter System #2, then System #1. Note that a metric of 16 indicates a "dead"
route (i.e. a "dead" route is a route that used to exist but is no longer valid). Fur-
thermore, since the maximum usable metric is 15, there is a limit of 16 masters in
the width plus height of the master topology (see the Design considerations and
constraints section on page 93).

PhyAddress column Indicates the internal connection parameters used by the master to maintain the
connection information.

The end result of the routing and connection data is that any device or master can communicate with any
other device or Master, regardless of the physical connection of the device. Note that Masters may only
be "connected" to each other via Ethernet/TCP/IP. As an example (FIG. 1 on page 91), NetLinx Studio is
running on a PC connected to System #7 as device number 32002. The routing capabilities of the
NetLinx Master allow NetLinx Studio to download IR codes to the NXC-IRS4 (S=7 D=24), a master
firmware upgrade to NetLinx Master #1, and new touch panel pages to the touch panel on Master #1. All
of this is possible simply by having NetLinx Studio connected to a NetLinx Master with M2M firmware.
Design considerations and constraints
The routing metric limit of 15 usable hops imposes some constraints on the topology of the
interconnected NetLinx masters. While the limit of 15 hops may seem very limiting, this is not really the
case if you carefully architect the topology. FIG. 3 illustrates a single dimensional view of the 15-hop
limit.

FIG. 3 Single dimensional view of the maximum number of interconnected NetLinx masters

This shows a maximum of 15 masters connected to each other, such that any master is routeable to any
other master. FIG. 4 expands FIG. 3 into two dimensions and takes advantage of the fact that each
NetLinx master supports multiple connections to masters.

FIG. 4 Two-dimensional view of the maximum number of interconnected NetLinx masters

NetLinx Programming Language Reference Guide 93


Master-To-Master (M2M)

FIG. 4 shows that a maximum of 64 systems can be interconnected using a two-dimensional


interconnection topology. Using a three-dimensional topology, even more systems can be interconnected
(FIG. 5).

FIG. 5 Three-dimensional view of the maximum number of interconnected NetLinx masters

FIG. 5 shows that a maximum of 512 systems can be interconnected using a three-dimensional
interconnection topology. Note that for the diagram in FIG. 4 that a single NetLinx master may have up
to eight connections to remote masters (all 6 sides of the "box" plus two diagonal connections).
The maximum number of TCP/IP connections supported by a single master is 200 simultaneous TCP/IP
connections.
Another possible connection topology is to establish communication hubs that optimize the traffic with
adjacent masters but still allows connections to other masters, as shown in FIG. 6.

FIG. 6 Clustered master topology

When determining the interconnection topology of many NetLinx Masters, special consideration should
be made to the Masters that communicate large amounts of information with each other. Thus, if you
have 2 systems that share devices, control, or information, they should be side-by-side in the topology,
not at opposite ends of the connection Matrix where each message is forced to pass through several
NetLinx Masters.

94 NetLinx Programming Language Reference Guide


Master-To-Master (M2M)

Control/NetLinx Language Support


The features of control to M2M include channel control (PUSH/RELEASE/ON/OFF/TO), level control,
send commands, and send strings.
Channel controls allow one NetLinx master to PUSH/RELEASE a channel on a device of another system
via the DO_PUSH/DO_RELEASE functions. Additionally, ON, OFF, TO, and feedback statements can
control channels on devices of remote systems. If a channel has a characteristic modifier associated with
it, that modifier still applies to the channel, regardless of whether the channel is manipulated locally or
remotely. For example, if a group of channels and variables is mutually exclusive, an ON to one of the
channels will turn off all other channels and variables in the group prior to turning on the desired
channel.
Levels, strings, and commands are forwarded to the destination device.
Note that control is not limited to physical devices, and NetLinx program defined virtual devices may
also be manipulated by a remote system. This allows a local system to define a virtual device that can
receive PUSH/RELEASEs, ONs, OFFs, etc. and make program decisions based upon that control.
Additionally, notification of control messages is not limited to "mainline" functions like PUSH and
RELEASE; rather, all EVENT based code will operate normally regardless of the source of the original
control message/function.
Design considerations and constraints
In order to reference devices of other NetLinx systems, the devices must be defined in the
DEFINE_DEVICE section of the NetLinx program. Conversely, only devices that are necessary should
be placed in the DEFINE_DEVICE section to avoid any unnecessary network traffic between NetLinx
masters.
DEFINE_LATCHING - A remote device's channel is not allowed in the DEFINE_LATCHING
section.
DEFINE_MUTUALLY_EXCLUSIVE- A remote device's channel is not allowed in the
DEFINE_MUTUALLY_EXCLUSIVE section.
DEFINE_TOGGLING - A remote device's channel is not allowed in the DEFINE_TOGGLING
section.
The proper way to modify a channel's behavior is to place the modifiers in the remote device's master.
General Master-to-Master Issues
When multiple masters exist within a large NetLinx installation, the significance of the System number
component cannot be over emphasized. Out of habit, it is easy to ignore the system field within NetLinx
Studio because its value has not meant anything in the past.
When NetLinx Studio connects to a single master, yet allows the user to access all other system masters,
some confusion will occur. Therefore, it is a good idea to document each system's, number and the
topology of the interconnections.

NetLinx Programming Language Reference Guide 95


Master-To-Master (M2M)

96 NetLinx Programming Language Reference Guide


Mainline

Mainline
Mainline is the program section executed continuously by the NetLinx Central Controller as long as the
Controller has power. DEFINE_PROGRAM contains the code known as mainline.
A typical NetLinx program is composed of a number of different sections. Each section defines some
aspect of a program such as device definitions, variable declarations, channel characteristics, or event
processing. The sections that can comprise a NetLinx program are listed in the following table.
Program Sections
DEFINE_DEVICE DEFINE_MUTUALLY_EXCLUSIVE
DEFINE_COMBINE DEFINE_TOGGLING
DEFINE_CONSTANT DEFINE_CALL
DEFINE_TYPE DEFINE_FUNCTION
DEFINE_VARIABLE DEFINE_START
DEFINE_CONNECT_LEVEL DEFINE_EVENT
DEFINE_LATCHING DEFINE_PROGRAM

Not all of the sections listed above are required to create a complete program. In an Axcess system, only
DEFINE_PROGRAM is required. In a NetLinx system, either DEFINE_PROGRAM or DEFINE_EVENT is
required. Other sections are required only to support code in one of these two sections, although the
Compiler might require more.
Axcess communication updates occur only between passes through mainline (or after each iteration
through LONG_WHILE loops). This places timing constraints on mainline processing in order for the
system to operate properly. NetLinx avoids these constraints by processing network activity through a
separate thread of execution. Bus activity is serviced concurrently with event processing and mainline
execution.
The event processing that previously could occur only through mainline code can now be handled
through code in the DEFINE_EVENT section. This provides a more efficient mechanism for processing
events; mainline does not have to be traversed to process a single I/O request. A handler can be defined
for processing device-specific events, as well as, providing feedback for the device initiating the event
notification. If a handler is present, mainline will not be called to process the event; the handler is called
instead. Once the handler completes its execution, the system is ready to process the next input message.
When no more messages are pending, mainline runs. In effect, mainline becomes an idle time process.
With the addition of the DEFINE_EVENT section for processing events, the role of mainline in a NetLinx
program becomes greatly diminished if not totally eliminated. Programs can still be written using the
traditional technique of processing events and providing feedback through mainline code. However,
programs written using the event table structure, provided in the NetLinx system, will likely run faster
and be much easier to maintain.
FIG. 1 illustrates message and mainline processing as it appears in the NetLinx system. Note that bus
servicing is taken care of by a separate process thread (Connection Manager & Message Dispatcher)
and, therefore, is not a task that must follow mainline.

NetLinx Programming Language Reference Guide 97


Mainline

FIG. 1 Message and Mainline Processing in the NetLinx System

98 NetLinx Programming Language Reference Guide


Reserved Identifiers

Reserved Identifiers
Compiler Directives
The compiler directives supported by NetLinx are described in the table below.
Compiler Directives
#DEFINE This directive defines a symbol to be used only by #IF_DEFINED and
#IF_NOT_DEFINED directives.
#DEFINE <symbol> [<constant expression>]
The name of the symbol must be unique among all other identifiers in the pro-
gram. The symbol can be defined anywhere in the program file but cannot be
used in any statement that appears before it is defined.
Example:
#DEFINE STRING_1 `Hello World`
#DEFINE STRING_2 "`Hello Letter `,65"
#DEFINE STRING_3 "65,66,67,68,69,70"

DEFINE_PROGRAM

PUSH[TP,1]

{
send_string 0,STRING_1 // This will send out `Hello
World`

send_string 0,STRING_2 // This will send out `Hello


Letter A`

send_string 0,STRING_3 // This will send out `ABCDEF`


}
#END_IF This directive marks the end of an #IF_DEFINED or #IF_NOT_DEFINED code
block.
#ELSE This directive specifies a counter condition; used optionally in conjunction with
#IF_DEFINED and #IF_NOT_DEFINED.
#IF_DEFINED This directive defines conditional compilation. The code following the
#IF_DEFINED and before #ELSE (or before #END_IF, if #ELSE is not present)
is compiled only if a symbol is defined (see #DEFINE above). If a symbol is not
defined and the #ELSE directive is present, the code following #ELSE and
before #END_IF is compiled instead.
#IF_DEFINED symbol
// code block
#ELSE
// code block
#END_IF
#IF_NOT_DEFINED This directive defines conditional compilation similar to #IF_DEFINED. The
code following the #IF_NOT_DEFINED and before #ELSE (or before #END_IF,
if #ELSE is not present) is compiled only if symbol is not defined (see #DEFINE
above). If a symbol is defined and the #ELSE directive is present, the code fol-
lowing #ELSE and before #END_IF is compiled instead.
#IF_NOT_DEFINED symbol
// code block
#ELSE
// code block
#END_IF

NetLinx Programming Language Reference Guide 99


Reserved Identifiers

Compiler Directives (Cont.)


#INCLUDE To include a file in a program, use the keyword #INCLUDE followed by the file-
name in single quotes.
DEFINE_PROGRAM
(* Program statements can go here *)
#INCLUDE 'TEST.AXI'
(* More program statements can go here *)
When the compiler reaches the #INCLUDE statement, it jumps into the speci-
fied file and continues compiling. When it has reached the end of that file, it
comes back to the line following the #INCLUDE statement and continues com-
piling.
#WARN This compiler directive displays a warning message after the program is com-
piled. Its primary purpose is to remind you of certain conditions related to the
program.
#WARN 'This code is obsolete'
#WARN 'This code is obsolete'

Keywords & Run-Time Library Functions


The keywords and run-time library function supported by NetLinx are described in the table below.
Keywords & Run-Time Library Functions
__DATE__ __DATE__ is replaced by a string (mm/dd/yy) containing the date of compila-
tion. The example below sends the date of compilation to a variable text button
on a touch panel.
SEND_COMMAND TP, "'!T',1,__DATE__"
__FILE__ At compile time, this keyword is replaced with a string that contains the filename
of the currently executing program file.
__LDATE__ At compile time, this keyword is replaced by a string (mm/dd/yyyy), containing
the date of compilation. The example below sends the date of compilation to a
variable text button on a touch panel.
SEND_COMMAND TP, "'!T',1,__LDATE__"
__LINE__ At compile time, this keyword is replaced by a constant that contains the line
number the keyword is on.
SEND_STRING 0,"ITOA(__LINE__)"
__NAME__ At compile time, this keyword is replaced by a string that contains the
PROGRAM_NAME description found on the first line of the program.
__TIME__ At compile time, this keyword is replaced by a string (hh:mm:ss) representing
the time of compilation. The example below sends the time of compilation to a
variable text button on a touch panel.
SEND_COMMAND TP, "'!T',1,__TIME__"
ABS_VALUE ABS_VALUE provides the absolute value of a variable. It will take any intrinsic
variable type and return the same type.
AbsVal ABS_VALUE (Value)

DEFINE_VARIABLE
SLONG Var1, Var2
DEFINE_START
Var1 = -1
DEFINE_PROGRAM
Var2 = ABS_VALUE(Var1) // Var2 = 1
ACTIVE See SELECT...ACTIVE on page 148.

100 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


ADD_URL_ENTRY This function adds a URL entry to the specified device. The function requires a
pre-initialized URL_STRUCT that will be sent to the specified device.
SLONG ADD_URL_ENTRY (DEV Device, URL_STRUCT Url)
Parameters:
• Device: Device number of the device that stores the URL. Typically, it is
stored on the local master (0:1:0); if you are currently connected to another
master, you can use <0:1:system number of remote master>.
• Url: URL_STRUCT that will be programmed into the device.
Result:
• 0: Success
• -1: Specified device is invalid or is not online
• -2: Time out occurred
• -3: Function is already actively adding a URL entry (i.e. busy)
• -4: Add failed
Note that NetLinx will automatically set bit 5 of the Flags member of the
URL_STRUCT structure.
See GET_URL_LIST for a description of the URL_STRUCT structure.
AND (&&) This logical operator evaluates two logical conditions. Both conditions must be
true for the entire expression to be true.
ASTRO_CLOCK This routine calculates the time of sunset and sunrise at a specified location
(longitude and latitude) on a specified date.
SINTEGER ASTRO_CLOCK(DOUBLE Longitude,DOUBLE
Latitude,DOUBLE
HoursFromGMT,CHAR[] Date,CHAR[] Sunrise,CHAR[] Sunset)
Parameters:
• Longitude: Longitude in Degrees. Fraction of Degrees. West longitudes
must be negative.
• Latitude: Latitude in Degrees. Fraction of Degrees. South latitudes must be
negative.
• HoursFromGMT: Number of hours from GMT. Hours West of GMT can be
entered as negative (e.g., -5 for EST, -4 for EDT).
• Date: In mm/dd/yyyy format.
• Sunrise: Value gets filled in by the function in 24-hour format.
• Sunset: Value gets filled in by the function in mm/dd/yyyy format.
Result:
• 0: Success
• -1: Latitude entry error
• -2: Longitude entry error
• -3: Hours entry error
• -4: Date entry error

NetLinx Programming Language Reference Guide 101


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


ATOI Converts a character representation of a number to an signed 32-bit integer.
The syntax:
SLONG ATOI (CHAR STRING[ ])
Parameters:
• STRING - string containing the character representation of the integer.
Result:
• A 32-bit signed integer representing the converted string.
• Any non-numeric characters in the string are ignored.
• ATOI returns the value representing the first complete set of characters that
represents an integer.
• Valid characters are "0" through "9" and "-" (minus sign), if it occurs before the
number. If no valid characters are found, zero is returned as a result.
Example:
Num = ATOI('100') // Num = 100
Note: While you can pass in larger values, ATOI will truncate any value outside
the range -2147483648 to 2147483647 to the value -2147483648 (if negative)
or 2147483647 (if positive).
ATOF This function converts a character representation of a number to a 64-bit float-
ing-point value. It recognizes a character representation of a signed integer or
floating-point number (with or without exponent).
FLOAT ATOF (CHAR STRING[ ])
Parameters:
• STRING: An input string containing the character representation of the
floating-point number.
The result is a 64-bit floating-point number representing the converted string.
Any non-numeric characters in the string are ignored. ATOF returns the value
representing the first complete set of characters that represents a floating-point
value. Valid characters are "0" through "9", ".", the sign designators ("+" and
"-"), and the exponent ("e" or "E"). If no valid characters are found, zero is
returned as a result.
Num = ATOF('The total = -1.25e-3')// Num = -0.00125
ATOL This function converts a character representation of a number to a signed 32-bit
integer.
SLONG ATOL (CHAR STRING[ ])
Parameters:
• STRING: A string containing the character representation of the integer.
The result is a 32-bit signed integer representing the converted string. Any non-
numeric characters in the string are ignored. ATOL returns the value represent-
ing the first complete set of characters that represents an integer. Valid charac-
ters are "0" through "9" and the sign designators "+" and "-". If no valid
characters are found, zero is returned as a result.
Num = ATOL('Value = -128000') // Num = -128000
BAND (&) This operator performs a bitwise AND on two data items, which can be constants
or variables.
BNOT (~) This operator performs a bitwise NOT on a constant or variable.
BOR (|) This operator performs a bitwise OR on two data items, which can be constants
or variables.

102 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


BREAK The BREAK command terminates execution of the current WHILE,
LONG_WHILE, or FOR loop and resumes program execution at the first instruc-
tion following that loop. BREAK also jumps to the end of a SWITCH statement.
WHILE (<condition>)
{
// statements
IF (<condition>)
{
BREAK // Go to statement: X = X + 1
}
}
// Execution continues here after BREAK or
// after normal completion of the WHILE loop.
X = X + 1
BUTTON_EVENT This keyword defines a button event handler and can only be used in the
DEFINE_EVENT section of the program. This type of handler processes PUSH,
RELEASE, and HOLD events.
BUTTON_EVENT[DEVICE,CHANNEL] or
BUTTON_EVENT [(DEVCHAN[ ])]
{
PUSH:
{
// Push statements go here
}
RELEASE:
{
// Release statements go here
}
HOLD[TIME,[REPEAT]]:
{
// Hold statements go here
}
}
See the Event Handlers section on page 61.
BXOR (^) This operator performs a bitwise XOR operation between two data items, which
can be constants or variables.
CALL Use the CALL keyword and the name of the subroutine in single quotes to tell
NetLinx to execute a subroutine. For example, to execute the subroutine Lights
Off, type the following where you want the CALL to occur:
CALL 'Lights Off'
When NetLinx executes the CALL, program execution jumps to the first line
inside the braces of the DEFINE_CALL. The subroutine is executed only once,
and then NetLinx returns to the statement directly following the CALL statement.
CANCEL_ALL_WAIT This keyword cancels all WAITs (named or unnamed) in the WAIT list.
CANCEL_ALL_WAIT_ This keyword cancels all (named or unnamed) WAIT_UNTIL and
UNTIL TIMED_WAIT_UNTIL commands.
CANCEL_WAIT This keyword cancels a specified wait. Only named waits can be canceled.
CANCEL_WAIT '<wait name>'

NetLinx Programming Language Reference Guide 103


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


CANCEL_WAIT_UNTIL This keyword cancels a specified WAIT_UNTIL or TIMED_WAIT_UNTIL. Only
named WAIT_UNTIL and named TIMED_WAIT_UNTIL commands can be can-
celed.
CANCEL_WAIT_UNTIL '<wait name>'
CASE See SWITCH..CASE on page 153.
CHANNEL_EVENT The CHANNEL keyword defines a channel event handler. This type of handler is
invoked when an output change occurs on the specified device-channel and
can only be used in the DEFINE_EVENT section of the program.
CHANNEL[DEVICE,CHANNEL] or
CHANNEL[(DEVCHAN[ ])]
{
ON:
{
// Channel ON event handling
}
OFF:
{
// Channel OFF event handling
}
}
DEVICE refers to:
• Device – a single device number constant.
• D:P:S – a constant device specification such as TP:1:0.
CHANNEL refers to:
• Channel – a single channel number constant.
DEVCHAN[ ] refers to a device-channel array.
See the Event Handlers section on page 61 for more information on
CHANNEL_EVENTs.
CHAR This keyword defines an intrinsic data type representing an 8-bit unsigned inte-
ger. This data type is used with ANSI character strings.
CHARD Sets the delay between all transmitted characters to that specified in
100-microsecond increments.
The syntax:
CHARD-<time in 100 microsecond increments>
Example:
SEND_COMMAND device,'CHARD-100'
Sets a 10mS delay between all transmitted characters.
CHARDM Sets the delay between all transmitted characters to that specified in
1-millisecond increments.
The syntax:
CHARDM-<time in 1 millisecond increments>
Example:
SEND_COMMAND device,'CHARDM-100'
Sets a 10 mS delay between all transmitted characters.
CLEAR_BUFFER This command sets the contents of the specified text buffer to zero; therefore,
subsequent GET_BUFFER_CHAR calls will not return anything. The
CLEAR_BUFFER command does not modify the data in the buffer, just the inter-
nal length value.
CLEAR_BUFFER Buffer
CLEAR_BUFFER does not delete the data in the buffer; it only sets the length to
zero.

104 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


CLKMGR_ADD_USER Adds a user-defined time server entry.
DEFINED_TIMESERVER CLKMGR_ADD_USERDEFINED_TIMESERVER (CONSTANT CHAR IP[],
CONSTANT CHAR URL[], CONSTANT CHAR LOCATION[])
CLKMGR_DELETE_USER Deletes the user-defined entry that has its IP-ADDRESS matching the parame-
DEFINED_TIMESERVER ter.
CLKMGR_DELETE_USERDEFINED_TIMESERVER (CONSTANT CHAR IP[])
CLKMGR_GET_ACTIVE_ Populates the TIMESERVER structure with the currently active time server's
TIMESERVER data.
CLKMGR_GET_ACTIVE_TIMESERVER (CLKMGR_TIMESERVER_STRUCT T)
The function returns a negative SLONG value if it encounters an error.
CLKMGR_GET_DAYLIGHT Populates the TIMEOFFSET structure with the current Daylight Savings Offset
SAVINGS_OFFSET configured.
CLKMGR_GET_DAYLIGHTSAVINGS_OFFSET
(CLKMGR_TIMEOFFSET_STRUCT T)
The function returns a negative SLONG value if it encounters an error.
CLKMGR_GET_END_ Gets a string representation of when Daylight Savings is supposed to END.
DAYLIGHTSAVINGS_RULE The Fixed-Date rules have the form:
"fixed:DAY,MONTH,HH:MM:SS"
with all fields as numeric except for the word "fixed".
The Occurrence-Of-Day rules have the form:
"occurence:OCCURENCE,DAY-OF-WEEK,MONTH,HH:MM:SS"
with all fields as numeric except for the word "occurence".
DAY-OF-WEEK translates as:
• 1=Sunday
• 2=Monday
• 3=Tuesday
• 4=Wednsday
• 5=Thursday
• 6=Friday
• 7=Saturday
CLKMGR_GET_RESYNC_ Returns the Clock Manager's re-sync period in minutes.
PERIOD The default setting is one (1) hour.
This setting has no effect if the Clock Manager mode is set to STANDALONE.
CLKMGR_GET_START_ Gets a string representation of when Daylight Savings is supposed to START.
DAYLIGHTSAVINGS_RULE The Fixed-Date rules have the form:
"fixed:DAY,MONTH,HH:MM:SS"
with all fields as numeric except for the word "fixed".
The Occurrence-Of-Day rules ave the form:
"occurence:OCCURENCE, DAY-OF-WEEK,MONTH,HH:MM:SS"
with all fields as numeric except for the word "occurence".
DAY-OF-WEEK translates as:
• 1=Sunday
• 2=Monday
• 3=Tuesday
• 4=Wednsday
• 5=Thursday
• 6=Friday
• 7=Saturday

NetLinx Programming Language Reference Guide 105


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


CLKMGR_GET_ Populates the currently configured time server entries from the Clock Manager
TIMESERVERS into the specified TIMESERVER array.
CLKMGR_GET_TIMESERVERS (CLKMGR_TIMESERVER_STRUCT T[])
The function returns a negative SLONG value if it encounters an error, other-
wise the return value is set to the number of records populated into the
CLKMGR_TIMESERVER_STRUCT array.
CLKMGR_GET_TIMEZONE Returns Timezone as a string in the format:
UTC[+|-]HH:MM
CLKMGR_IS_ Returns FALSE/0 or TRUE/1.
DAYLIGHTSAVINGS_ON The default setting is FALSE/0.
CLKMGR_IS_NETWORK_ Returns FALSE/0 or TRUE/1.
SOURCED The default setting is FALSE/0.
CLKMGR_SET_ACTIVE_ Sets the time server entry that has the matching IP-ADDRESS to the IP param-
TIMESERVER eter as the active time server entry.
CLKMGR_SET_ACTIVE_TIMESERVER (CONSTANT CHAR IP[])
CLKMGR_SET_CLK_ CLKMGR_SET_CLK_SOURCE (CONSTANT INTEGER MODE)
SOURCE Can be set to:
CLKMGR_MODE_NETWORK
or
CLKMGR_MODE_STANDALONE.
CLKMGR_SET_DAYLIGHT CLKMGR_SET_DAYLIGHTSAVINGS_MODE (CONSTANT INTEGER ONOFF)
SAVINGS_MODE Can be set to:
ON/TRUE
or
OFF/FALSE.
CLKMGR_SET_DAYLIGHT Sets the Daylight Savings Offset to the specified value.
SAVINGS_OFFSET CLKMGR_SET_DAYLIGHTSAVINGS_OFFSET (CONSTANT
CLKMGR_TIMEOFFSET_STRUCT T)
CLKMGR_SET_END_ Sets the END Daylight Savings rule to the specified string which must be in
DAYLIGHTSAVINGS_RULE either
the Fixed-Date format or the Occurence-Of-Day format.
CLKMGR_SET_END_DAYLIGHTSAVINGS_RULE (CONSTANT CHAR
RECORD[])
The function returns a negative SLONG value if it encounters an error.
The Fixed-Date rules have the form:
"fixed:DAY,MONTH,HH:MM:SS"
with all fields as numeric except for the word "fixed"
(e.g.: "fixed:21,3,02:00:00"===> March 21 @ 02:00:00AM).
The Occurrence-Of-Day rules have the form:
"occurence:OCCURENCE,DAY-OF-WEEK,MONTH,HH:MM:SS"
with all fields as numeric except for the word "occurence"
DAY-OF-WEEK translates as:
• 1=Sunday
• 2=Monday
• 3=Tuesday
• 4=Wednsday
• 5=Thursday
• 6=Friday
• 7=Saturday
(e.g.: "occurence:3,1,10,02:00:00" ===> 3rd Sunday in October @
02:00:00AM).

106 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


CLKMGR_SET_RESYNC_ Sets the re-sync period to the specified minute value.
PERIOD CLKMGR_SET_RESYNC_PERIOD (CONSTANT INTEGER PERIOD)
The upper bound is 480 minutes (i.e., 8 hours).
CLKMGR_SET_START_ Sets the START Daylight Savings rule to the specified string which must be in
DAYLIGHTSAVINGS_RULE either
the Fixed-Date format or the Occurence-Of-Day format.
CLKMGR_SET_START_DAYLIGHTSAVINGS_RULE (CONSTANT CHAR
RECORD[])
The function returns a negative SLONG value if it encounters an error.
The Fixed-Date rules have the form:
"fixed:DAY,MONTH,HH:MM:SS"
with all fields as numeric except for the word "fixed"
(e.g.: "fixed:21,3,02:00:00" ===> March 21 @ 02:00:00AM).
The Occurrence-Of-Day rules have the form:
"occurence:OCCURENCE,DAY-OF-WEEK,MONTH,HH:MM:SS"
with all fields as numeric except for the word "occurence"
DAY-OF-WEEK translates as:
• 1=Sunday
• 2=Monday
• 3=Tuesday
• 4=Wednsday
• 5=Thursday
• 6=Friday
• 7=Saturday
(e.g.: "occurence:3,1,10,02:00:00" ===> 3rd Sunday in October @
02:00:00AM).
CLKMGR_SET_TIMEZONE CLKMGR_SET_TIMEZONE (CONSTANT CHAR TIMEZONE[])
Input string must have the correct format:
UTC[+|-]HH:MM
CLOCK Sets the date and time on the Master. The date and time settings are propa-
gated over the local bus.
'CLOCK <mm-dd-yy> <hh:mm:ss>'
Example:
SEND_COMMAND 0,"'CLOCK 04-12-05 09:45:31'"
COMBINE_CHANNELS This command connects a single virtual device-channel to one or more chan-
nels on another device (or devices). Any element in a DEVCHAN[ ] set appears
to come from the virtual device-channel representing the group, and output to
the virtual device-channel is directed to all elements in the DEVCHAN[] set.
COMBINE_CHANNELS (DEVCHAN VDC, DEVCHAN[ ] DCSets)
Parameters:
• VDC: Virtual device-channel that represents one device-channel combine
group.
• DCSets: Device-channel array containing the device-channel pairs to
combine. Each element in each set is combined with the virtual
device-channel.

NetLinx Programming Language Reference Guide 107


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


COMBINE_DEVICES This keyword defines the combination of functionally identical devices, such as
identically programmed touch panels. When the program references one of
these devices, all other combined devices in the array are also referenced. The
devices in a given array must be enclosed in parentheses.
A virtual device is one that does not actually exist but merely represents one or
more physical devices.
The first device in the list (the primary device) must be a virtual device. By spec-
ifying a virtual device as the primary device, NetLinx code can target the virtual
device but have the effect of operating on each physical device. Furthermore,
since a virtual device is not an actual physical device, the primary device cannot
be taken off-line or removed from the system. An example of virtual devices is
shown below:
COMBINE_DEVICES (VIRTUAL1, TP1, TP2, TP3)
The example above combines the three touch panel devices: TP1, TP2 and
TP3. Whenever an input change occurs on any of the three devices, NetLinx
detects the input as coming only from VIRTUAL1. For example, if button [TP3,
5] is pressed, NetLinx sees input coming from [VIRTUAL1, 5] as a result of
the combination.
Output changes (including level changes) sent to any device in the list will auto-
matically be sent to all devices in the list. For instance, ON[VIRTUAL1, 50]
will turn on channel 50 on all three panels and OFF[VIRTUAL1, 10] will turn
off channel 10 on all three panels.
The example below is equivalent to the first except that it uses a device array
(Dev[ ]) instead of specifying the individual devices (TP1, TP2, and TP3). Any
input events for any device in the array will appear to the program as coming
from the virtual device. Output changes directed to the virtual device or any
device in the array are sent to all devices in the array.
COMBINE_DEVICES
( VIRTUAL1, Dev[ ])
When using a device array, the array can be manipulated at run-time to add or
remove devices. A device that is added to the array is combined with the others
and a device that is removed is uncombined. The process of adding or remov-
ing devices does not require the system to be powered down and restarted.
COMBINE_LEVELS This keyword connects a single device-level array (DEVLEV[ ]) to a DEVLEV
array. Any element in a DEVLEV array appears to come from the virtual device-
level representing the group, and output to any element in a DEVLEV array is
directed to all elements in the group.
COMBINE_LEVELS (DEVLEV VDLSET, DEVLEV[ ] DLSETS)
Parameters:
• VDLSET: Virtual device-level sets; each element represents one device-level
combine group.
• DLSETS: Device-level sets containing the device-level pairs to combine.
Corresponding elements in each set are combined with the corresponding
element in the virtual device-level array.
COMMAND This keyword defines a section in a DATA event handler for processing
SEND_COMMAND instructions.

108 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


COMPARE_STRING This keyword compares two character strings. If either string contains a '?' char-
acter, the matching character in the other string is not compared. The '?' is
equivalent to a wilcard. For example:
DEFINE_LIBRARY_FUNCTION LONG COMPARE_STRING(CHAR A[],
CHAR B[])
Here is some useful debugging code:
tstStr = 'ALEXERICRYAN'
ulError = COMPARE_STRING ( tstStr, 'ALEX' )
if( ulError == 0 )
SEND_STRING dvDebug, 'ALEXERICRYAN != ALEX'
else
SEND_STRING dvDebug, 'ALEXERICRYAN == ALEX... BAD!'

tstStr = 'ALEXERICRYAN'
ulError = COMPARE_STRING ( tstStr, 'ALEXERICRYAN' )
if ( ulError == 0 )
SEND_STRING dvDebug, 'ALEXERICRYAN !=
ALEXERICRYAN...BAD!'
else
SEND_STRING dvDebug, 'ALEXERICRYAN == ALEXERICRYAN'

tstStr = 'ALEXERICRYAN'
ulError = COMPARE_STRING ( tstStr, 'ALEX????RYAN' )
if ( ulError == 0 )
SEND_STRING dvDebug, 'ALEXERICRYAN !=
ALEX????RYAN...BAD!'
else
SEND_STRING dvDebug, 'ALEXERICRYAN == ALEX????RYAN
Another example of a use for this feature is if you want an event to occur every
hour. You would enter a time string that would contain a '??;00 ;00' (hours/
minute/sec) for the recurring event that in this case would occur every hour.
Result: The returned result can only be True (1) or False (0).
• 0 = the strings don't match
• 1 = the strings are the same
CONSTANT This keyword is used as part of a variable declaration to specify that the variable
cannot be changed at run-time. If a variable is declared with this keyword, it
must be initialized in its declaration.
CREATE_BUFFER This keyword creates a buffer and can only appear in the DEFINE_START
section of the program.
CREATE_BUFFER DEV, Buffer
CREATE_BUFFER directs NetLinx to place any strings received from the speci-
fied device into the specified buffer (character array). When strings are added
to the buffer, the length of the buffer is automatically adjusted. If the buffer is
full, all bytes in the buffer are shifted to make room for the new string. A buffer
can be manipulated in the same way as a character array.

NetLinx Programming Language Reference Guide 109


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


CREATE_LEVEL This keyword creates an association between a specified level of a device and
a variable that will contain the value of the level. This can only appear in the
DEFINE_START section of the program.
CREATE_LEVEL DEV, Level, Value
Parameters:
• DEV: The device from which to read the level.
• Level: The level of the device to read.
• Value: Variable in which to store the level value.
• DevLev: A DEVLEV structure.
• Value: Variable in which to store the level value CREATE_LEVEL DevLev,
Value.
During execution of the program, NetLinx continuously updates the variable to
match the level it represents.
CREATE_MULTI_BUFFER This keyword is the same as CREATE_BUFFER except that it accepts strings
from a range of devices. Two forms of this command are supported:
The first form of the command is provided for backward-compatibility; it accepts
two device numbers as the range of devices.
CREATE_MULTI_BUFFER FirstDevice, LastDevice, Buffer
Parameters:
• FirstDevice: First number in the range of devices.
• LastDevice: Last number in the range of devices.
• Buffer: Text buffer to receive the strings.
Each command string placed in the multi-buffer has a three-byte header associ-
ated with it:
• The first header byte, $FF, marks the start of a new command string.
• The second header byte is either the number of the device or the index of the
DEV[ ] member that received the command string.
• The third header byte is the length of the string.
$FF, device number or DEV[ ] index, length, <string>
The second form of the command takes a device array rather than the device
number pair.
CREATE_MULTI_BUFFER DeviceSet, Buffer
Parameters:
• DeviceSet: Set of devices for which the buffer will accept strings.
• Buffer: Text buffer to receive the strings.
Each command string placed in the multi-buffer has a three-byte header associ-
ated with it.
• The first header byte, $FF, marks the start of a new command string
• The second header byte is the index into the DeviceSet of the device that
received the string.
The third header byte is the length of the string.
$FF, device number or DEV[ ] index, length, <string>
This command is not recommended for use in NetLinx due to its limitations.
The main limitations to note are:
• For the first form of the command, using FirstDevice and LastDevice,
only devices using the same port and system will be allowed. The device in
between the First Device and Last Device will be the sequential device
numbers using the same port and system (i.e. 1:1:0, 2:1:0, 3:1:0, etc…)
• For the second form of the command, using DeviceSet, only 255 devices
will be allowed in the array. This is required since only one byte is used to
represent the DeviceSet index in the return string so it has an upper limit of
255.

110 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


CREATE_MULTI_BUFFER • Strings from a device longer than 255 bytes will be broken up into multiple
(Cont.) "multi" strings within the buffer. For instance, if 300 characters are received
from a port, the multi buffer will contain:
"$FF,<index>, 255,<first 255 characters>,$FF,45,
<last 45 characters>"
The recommended replacement for CREATE_MULTI_BUFFER and
GET_MULTI_BUFFER_STRING is to use a DeviceSet and a DATA_EVENT to
capture strings from multiple devices. An example is shown below:
DEFINE_DEVICE
Dev1 = 1:1:0
Dev2 = 1:2:0
Dev3 = 1:3:0
DEFINE_VARIABLE
DEV DeviceSet[] = {Dev1, Dev2, Dev3}
INTEGER DeviceIndex
CHAR DeviceString[1000]
DEFINE_EVENT
DATA_EVENT[DeviceSet]
{
STRING:
{
DeviceIndex = GET_LAST(DeviceSet)
DeviceString = DATA.TEXT
}
}
See GET_MULTI_BUFFER_STRING, page 131, for more information.
DATA_EVENT This keyword defines a data event handler. This type of handler processes
COMMAND, STRING, ONLINE, OFFLINE and ONERROR events. It can only be
used in the DEFINE_EVENT section of the program.
DATA_EVENT[DEVICE]
{
COMMAND:
{
// Command processing goes here
}
STRING:
{
// String processing goes here
}
ONLINE:
{
// OnLine processing goes here
}
OFFLINE:
{
// OffLine processing goes here
}
ONERROR:
{
// OnError processing goes here
}
}
See the Event Handlers section on page 61 for more information on
DATA_EVENT handlers.

NetLinx Programming Language Reference Guide 111


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


DATE The system variable DATE returns the current date in (mm/dd/yy) string format.
The wildcard character "?" is not allowed for string comparisons because the
actual date is needed.
IF (DATE = '12/25/00')
{
}
You can replace the wildcard feature by using the COMPARE_STRING function.
DAY The system variable DAY returns the current day of the week as one of the fol-
lowing strings: 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT' or 'SUN'.
IF (DAY = 'SUN')
{
}
DATE_TO_DAY This function returns an sinteger representing the day portion of a date string.
The S in SINTEGER allows a negative value to be returned.
SINTEGER DATE_TO_DAY (CHAR LDATE[ ])
Parameters:
• LDATE: [Input] string containing the date in mm/dd/yyyy format.
If successful, this function returns an integer (1-31) representing the day portion
of the date string. If the specified date is invalid, this function returns -1.
SINTEGER nDaynDay = DATE_TO_DAY ('2/9/1999') // nDay = 9
DATE_TO_MONTH This function returns an sinteger representing the month portion of a date string.
SINTEGER DATE_TO_MONTH (CHAR LDATE[ ])
Parameters:
• LDATE: [Input] string containing the date in mm/dd/yyyy format.
If successful, this function returns an integer (1-12) representing the month por-
tion of the date string. If the specified date is invalid, this function returns -1.
SINTEGER nMonthNMonth = DATE_TO_MONTH ('2/9/1999')
// nMonth = 2
DATE_TO_YEAR This function returns an sinteger representing the year portion of a date string.
SINTEGER DATE_TO_YEAR (CHAR LDATE[ ])
Parameters:
• LDATE: [Input] string containing the date in mm/dd/yyyy format.
If successful, this function returns a 4-digit integer representing the year portion
of the date string. If the specified date is invalid, this function returns -1.
SINTEGER nYearnYear = DATE_TO_YEAR ('2/9/1999')
// nYear = 1999
DAY_OF_WEEK This function returns the day of the week for the specified date.
SINTEGER DAY_OF_WEEK (CHAR LDATE[ ])
Parameters:
• LDATE: String containing the date in mm/dd/yyyy format.
This function returns an sinteger representing the day of the week (1 = Sunday,
2 = Monday, etc.).
SINTEGER nDay = DAY_OF_WEEK ('2/13/1999')
// nDay = 7 (Saturday)
DEFAULT This keyword specifies the default case in a SWITCH…CASE statement.
See SWITCH...CASE on page 153.

112 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


DEFINE_CALL This keyword defines the implementation of a NetLinx subroutine.
DEFINE_CALL '<name>' [(P1,P2,...)]
{
// body of subroutine
}
The subroutine name cannot be a previously defined device name, constant, or
variable, or a name assigned to a buffer or a wait statement. DEFINE_CALL
names are case sensitive and may contain spaces.
Note: Subroutines must be defined before they can be used. For this reason,
DEFINE_CALLS should appear before the DEFINE_START, DEFINE_EVENT,
and DEFINE_PROGRAM sections.
DEFINE_COMBINE This keyword defines the combination of functionally identical devices, such as
identically programmed touch panels. When the program references one of
these devices, all other combined devices are also referenced. The devices in
a given combine must be enclosed in parentheses.
The first device in the list (the primary device) must be a virtual device.
DEFINE_COMBINE(VDevice, Panel1, Panel2, Panel3)
The example below uses a device array (DEV[ ]) instead of specifying the indi-
vidual devices (Panel1, Panel2, and Panel3). Any input events for any device in
the array will appear to the program as coming from the virtual device. Output
changes directed to the virtual device or any device in the set is sent to all
devices in the array.
DEFINE_COMBINE(VDevice, DEV[ ])
See COMBINE_DEVICES,on page 108, for more information on virtual devices
and device arrays.
DEFINE_CONNECT_ This keyword defines level connections. A single connection is defined by list-
LEVEL ing the device-level pairs inside parentheses.
The first level in the list (the primary level) must be a virtual level (a level on a
virtual device). A virtual level does not actually exist but merely represents one
or more levels on physical devices.
The example below combines the levels [Device1, Level1] and
[Device2, Level2].
(VDevice, Level1, Device1, Level1, Device2, Level1)
The next example combines all levels in the device-level array. Changes to any
level listed in the connection will automatically be reflected in the other levels so
that all level values are the same.
DEFINE_CONNECT_LEVEL(VDevLev, MyDL[ ])
By specifying a virtual level as the primary level, NetLinx code targets the virtual
level but operates on each physical level. Since the primary level is virtual, the
primary device (a virtual device) cannot be taken off-line or removed from the
system.
DEFINE_CONSTANT This keyword defines program constants; the value of a constant cannot be
changed within the program.
DEFINE_CONSTANT
PLAY = 1
STOP = 2
STRING='HELLO'

NetLinx Programming Language Reference Guide 113


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


DEFINE_DEVICE This keyword defines the devices referenced in the program.
DEFINE_DEVICE
TP1 = 128:1:0// device number = 128, port = 1, system = 0
TP2 = 129:1:0// device number = 129, port = 1, system = 0
TP3 = 130:1:0// device number = 130, port = 1, system = 0
VCR1 = 10:1:0 // device number = 10, port = 1, system = 0
VCR2 = 11:1:0 // device number = 11, port = 1, system = 0
Devices can be specified by a single device number such as "TP = 128" or as
a fully-qualified device specification such as "TP = 128:1:0"
DEFINE_EVENT This keyword provides the basis for the construction of the event table, which is
where event-handling code is placed. When NetLinx receives an incoming
event, the event table is searched for a handler for that event. A handler is a
block of code that performs the necessary processing for an event notification
received from a given device (and possibly associated with a particular chan-
nel).
See the Event Handlers section on page 61 for more information.
DEFINE_FUNCTION This keyword defines the implementation of a NetLinx function.
DEFINE_FUNCTION [<return type>] FnName(P1,P2,...)
{
// function statements
}
The return type is optional and can be any intrinsic data type or array of intrinsic
types that NetLinx supports except a structure or an array of structures. The
function name must not be a previously defined constant or variable or a name
assigned to a buffer, a wait, DEFINE_CALL, or Function. Function names are
not case sensitive.
DEFINE_LATCHING This keyword section is where latching channels and variables are defined. A
latching channel is one that changes its state once per activation. If a latching
channel is activated by a TO keyword, it changes its state. When the TO is
stopped by releasing the button that started it, the channel does not go back to
its previous state. The status of a latching channel (that is not part of a mutually
exclusive group) will always reflect the on/off state of the channel.
In the following example, the device-channel [RELAY, SYSTEM_POWER] is
defined as latching. The next statement uses the double periods (..) to define
a range of VCR channels as latching. In the last statement, the variable VAR1 is
defined as latching.
DEFINE_LATCHING
[RELAY, SYSTEM_POWER]
[VCR, PLAY]..[VCR, REWIND]
VAR1
DEFINE_MODULE This keyword declares a module that will be used by either the main program or
another module. It is the counterpart to the MODULE_NAME entry that appears as
part of the implementation of the module.
DEFINE_MODULE '<module name>' InstanceName(<parameter
list>)
Parameters:
• <module name>: The name of the module as specified in the MODULE_NAME
statement in the module implementation file.
• InstanceName: The name to assign to the instance of the module.
• <parameter list>: The list of parameters available to the module.

114 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


DEFINE_MUTUALLY_ When a channel is turned on in a mutually exclusive set, it activates its physical
EXCLUSIVE output as long as the button is pressed. When the button is released, the phys-
ical output stops. Even after the physical output stops, the feedback still indi-
cates the channel is on until another channel in the mutually exclusive set is
activated. The status remains on to indicate which channel in the set was acti-
vated last (last button pushed feedback). When a channel or variable in a mutu-
ally exclusive set is activated, all other members of the set are turned off
beforehand (break before make logic).
Members of a mutually exclusive set are placed in parentheses underneath the
DEFINE_MUTUALLY_EXCLUSIVE keyword. The double period (..) specifies a
range of channels on the particular device to be defined as mutually exclusive.
DEFINE_MUTUALLY_EXCLUSIVE
([RELAY,SCREEN_UP], [RELAY,SCREEN_DOWN])

DEFINE_TOGGLING
[RELAY,SCREEN_UP][RELAY,SCREEN_DOWN]
The last entry specifies a set of mutually exclusive variables - VCR_SELECT,
CD_SELECT, and CASS_SELECT. If any one of the three variables is turned on
(e.g., "ON [VCR_SELECT]") the other two are turned off.
If a channel is defined to be both mutually exclusive and latching, it has the
same behavior described above except that the channel stays on even after the
button that activated it is released. Theoretically, a channel in a mutually exclu-
sive latching set cannot be turned off without activating another channel in the
same set. In NetLinx, you can bypass this rule by using TOTAL_OFF. The
TOTAL_OFF function turns a channel or variable off. Unlike OFF, TOTAL_OFF
turns off the status of a channel or variable that is in a mutually exclusive set.
DEFINE_PROGRAM This keyword defines the mainline code, which is executed continuously to pro-
cess input and to provide device feedback.
See the Mainline section on page 97 for more information.
DEFINE_START This keyword contains instructions that are executed once at program startup;
in other words, at power-up or after a system reset.
DEFINE_TOGGLING When a channel is defined as mutually exclusive and latching, there is no way
to turn off the channel without activating another. Mutually exclusive toggling
allows a channel to be turned on or off by successive presses of the same but-
ton, like a normal latching channel. The channel is still affected by its mutually
exclusive characteristics; if the channel is on, it can be turned off by activating
another channel in the set. The status of a mutually exclusive toggling button
operates the same way as a mutually exclusive latching button.
In order to make a channel toggling, it must be defined as both mutually exclu-
sive and toggling, as shown below:
DEFINE_MUTUALLY_EXCLUSIVE([RELAY, SCREEN_UP], [RELAY,
SCREEN_DOWN])DEFINE_TOGGLING[RELAY, SCREEN_UP][RELAY,
SCREEN_DOWN]
DEFINE_TYPE This keyword section defines custom data types such as structures and arrays.
An example DEFINE_TYPE section is shown below.
DEFINE_TYPE
STRUCTURE MyStruct
{
LONG Num
CHAR Name[30]
}
See the Data Types section on page 10 for a discussion of structures.

NetLinx Programming Language Reference Guide 115


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


DEFINE_VARIABLE This keyword declares global variables. Any variable defined in this section is
static (its value is maintained throughout the duration of program execution)
with module scope (it is accessible from any instruction in the current module).
DEFINE_VARIABLE
INTEGER INT1
FLOAT FP1
VOLATILE INTEGER BIGARRAY[1000][1000]
Note: 1000 marks the limit of the string.
See the Variables section on page 11 for more information.
DELETE_URL_ENTRY This function deletes a URL entry to the specified device. The function requires
a pre-initialized URL_STRUCT that will be sent to the specified device.
SLONG DELETE_URL_ENTRY (DEV Device, URL_STRUCT Url)
Parameters:
• Device: Device to which the URL will be sent.
• Url: URL_STRUCT that will be programmed into the device.
Result:
• 0: Success
• -1: Specified device is invalid or is not online
• -2: Time out occurred
• -3: Function is already actively deleting a URL entry (i.e. busy)
• -4: Delete failed
See GET_URL_LIST for a description of the URL_STRUCT structure.
DEV This keyword defines a data type (structure) used to represent a specific device,
port, and system. In NetLinx, the DEV structure is the actual (internal) represen-
tation of a NetLinx device.
STRUCTURE DEV{INTEGER NumberINTEGER PortINTEGER System}
DEVCHAN This keyword defines a data type (structure) containing fields used to represent
a specific device number, port, system, and channel.
STRUCTURE DEVCHAN
{
DEV Device
INTEGER Channel
}
DEVICE_ID Every device in the NetLinx system has a unique ID number identifying its
device type, such as an infrared/serial card or touch panel. The DEVICE_ID
keyword returns the ID number pertaining to the specified device. If the device
does not exist in the system, zero is returned. This keyword is usually used to
determine whether or not a device is present in the system.
DeviceID = DEVICE_ID(Device)
For example:
IF (DEVICE_ID(55:1:0) <> 0)
{
// device 55 exists in the system
}
DEVICE_ID_STRING This keyword returns a string description/model number for the specified
device.
DeviceString = DEVICE_ID_STRING(55:1:0)

116 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


DEVICE_INFO NetLinx stores information, such as manufacturer, device name and device ID,
for each device in the system. The DEVICE_INFO keyword allows a program-
mer to access all available information for any device. If the device does not
exist in the system, a Device ID of zero is returned. This keyword is usually
used to determine the firmware version of a device in the system.
DEVICE_INFO(DEV Device, DEV_INFO_STRUCT Info)
Parameters:
• Device: The device to query.
• Info: A DEV_INFO_STRUCT variable to populate with the device information.
Result:
DEVICE_INFO does not return a result. However, if the DEVICE_INFO call is
successful, the DEVICE_ID element of the structure will be non-zero. If
DEVICE_ID is zero, the structure contains no useful information.
The DEV_INFO_STRUCT contains the following information:
• Info. MANUFACTURER_STRING - A string identifying the manufacturer of the
device.
• Info. MANUFACTURER - A integer identifying the manufacturer.
• Info. DEVICE_ID_STRING - A string description/model number for the
specified device. This is the same information returned by the
DEVICE_ID_STRING keyword.
• Info. DEVICE_ID - A unique ID number identifying its device type, such as an
infrared/serial card or touch panel. This is the same information returned by
the DEVICE_ID keyword.
• Info. VERSION - A string identifying the firmware version of the device. This is
not available for AXLink devices.
• Info. FIRMWARE_ID - A unique ID number identifying the firmware for this
device. This is not available for AXLink devices.
• Info.SERIAL_NUMBER - A 16-character serial number of the specified
device. The serial number of every device is established when manufactured.
This is the same information returned by GET_SERIAL_NUMBER keyword.
This is not available for AXLink devices.
• Info. SOURCE_TYPE - An integer identifying how the device is connected to
the master. This value can be any of the following:
$00 (SOURCE_TYPE_NO_ADDRESS) - There is no source address.
$01 (SOURCE_TYPE_NEURON_ID) - The device is connected via ICSNet.
$02 (SOURCE_TYPE_IP_ADDRESS) - The device is connected via IP.
$03 (SOURCE_TYPE_AXLINK) - The device is connected via ICSNet.
$10 (SOURCE_TYPE_NEURON_SUBNODE_ICSP) - The device is connected
via ICSNet.
$11 (SOURCE_TYPE_NEURON_SUBNODE_PL) - The device is connected via
ICSNet.
$12 (SOURCE_TYPE_IP_SOCKET_ADDRESS) - This device is a NetLinx
socket.
$13 (SOURCE_TYPE_RS232) - This device is connected via RS232.
$20 (SOURCE_TYPE_INTERNAL) - This device is internal to the NetLinx
controlled.
• Info. SOURCE_STRING - A string identifying the source address. Normally,
this contains only useful information when Info.SOURCE_TYPE is $02 (IP), in
which case this contains the IP address of the device.

NetLinx Programming Language Reference Guide 117


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


DEVICE_INFO Example:
(Cont.) DEFINE_DEVICE
dvNL = 0:1:0
DEFINE_VARIABLE
DEV_INFO_STRUCT sDeviceInfo
DEFINE_EVENT
DATA_EVENT[dvNL]
{
ONLINE:
{
DEVICE_INFO(dvNL, sDeviceInfo)
SEND_STRING 0,"'MANUFACTURER_STRING=',
sDeviceInfo.MANUFACTURER_STRING"
SEND_STRING
0,"'MANUFACTURER=',ITOA(sDeviceInfo.MANUFACTURER)"
SEND_STRING 0,"'DEVICE_ID_STRING=',
sDeviceInfo.DEVICE_ID_STRING"
SEND_STRING
0,"'DEVICE_ID=',ITOA(sDeviceInfo.DEVICE_ID)"
SEND_STRING 0,"'VERSION=', sDeviceInfo.VERSION"
SEND_STRING
0,"'FIRMWARE_ID=',ITOA(sDeviceInfo.FIRMWARE_ID)"
SEND_STRING 0,"'SERIAL_NUMBER=',
sDeviceInfo.SERIAL_NUMBER"
SEND_STRING
0,"'SOURCE_TYPE=',ITOA(sDeviceInfo.SOURCE_TYPE)"
SEND_STRING 0,"'SOURCE_STRING=',
sDeviceInfo.SOURCE_STRING"
}
}
}
Telnet displays this information:
MANUFACTURER_STRING=AMX Corp.
MANUFACTURER=1
DEVICE_ID_STRING=NXC-ME260
DEVICE_ID=256
VERSION=v2.30.128
FIRMWARE_ID=256
SERIAL_NUMBER=2010-00372
SOURCE_TYPE=1
SOURCE_STRING=00A066452001
DEVLEV This keyword defines a data type (structure) containing fields used to represent
a specific device number, port, system, and level. This structure is used to
implement an array DEVLEV[ ].
STRUCTURE DEVLEV
{
DEV Device
INTEGER Level
}

118 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


DO_PUSH This keyword causes an input change from OFF to ON to occur on a specified
device-channel without the device-channel being activated by external means.
To prevent the program from stalling mainline too long, there is a 0.5 second
timeout on DO_PUSH. DO_PUSH defaults to a 0.5 second push on a channel
before issuing a DO_RELEASE for you (unless another DO_PUSH is executed for
the same channel). NetLinx will forcibly exit the DO_PUSH after 0.5 seconds,
regardless of the operation it is executing. If the channel is already ON, no
event is generated.
Note: The timeout feature is used to prevent un-released pushes and out of
control ramping.
DO_PUSH(DEVICE, CHANNEL)
DO_PUSH_TIMED Similar to DO_PUSH, except DO_PUSH_TIMED lets you specify the timeout, so
you can control the length of time that will pass before the automatic
DO_RELEASE is generated.
DO_PUSH_TIMED(DEV Device, INTEGER Channel, LONG Timeout)
Parameters:
• Device: The device to PUSH.
• Channel: The channel to PUSH.
• Timeout: The time (in 1/10ths of seconds) the PUSH remains active. If zero is
specified as the timeout then the timeout is 0.5 seconds. If
DO_PUSH_TIMED_INFINITE is specified as the timeout then the push never
times out.
DO_PUSH_TIMED (dvTouchPanel, 5, 10) // push button 5 for
1.0S
DO_RELEASE This keyword causes an input change from ON to OFF to occur on a specified
device and channel without the channel being deactivated by external means.
If the channel is already OFF, no event is generated.
DO_RELEASE(DEVICE, CHANNEL)
DOUBLE This keyword defines an intrinsic data type representing a 64-bit (double preci-
sion) signed floating-point value.
DUET_MEM_SIZE_GET Displays the amount of memory allocated for Duet Java pool.
This is the current Java memory heap size as measured in Megabytes.
An example is a value of 5 = 5 MB.
DUET_MEM_SIZE_SET Set the amount of memory allocated for Duet Java pool. This is the current Java
memory heap size as measured in Megabytes.
This feature is used so that if a NetLinx program requires a certain size of mem-
ory be allotted for its currently used Duet Modules, it can be reserved on the tar-
get Master.
Valid values are:
• 2 - 8 for 32MB systems
• 2 - 36 for 64MB systems
This setting does not take effect until the next reboot.
Note:"DUET_MEM_SIZE_SET(int)" should call REBOOT() following a set.
ELSE If the corresponding IF statement is false, the program will jump to the ELSE
section of the IF…ELSE set of statements.
FALSE This keyword is a CHAR constant contains the value 0.
While NetLinx does not support a BOOLEAN data type, zero is consider false
conditional expressions.

NetLinx Programming Language Reference Guide 119


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


FILE_CLOSE This function closes a file opened with FILE_OPEN. This function should be
called when all reading or writing to the file is completed.
SLONG File_Close (LONG hFile)
Parameters:
• hFile: Handle to the file returned by File_Open.
Result:
• 0: Operation was successful
• -1: Invalid file handle
• -5: Disk I/O error
• -7: File already closed
There is a limit to the number of file handles available from the system. If files
are not closed, it may not be possible to open a file.
Result = File_Close(hFile)
FILE_COPY This function copies the specified file.
SLONG File_Copy(CHAR SrcFilePath[ ], CHAR DstFilePath[ ])
Parameters:
• SrcFilePath: Path name of the file to copy (source).
• DstFilePath: Path name of the copied file (destination).
Result:
• 0: Operation was successful
• -2: Invalid file name
• -5: Disk I/O error
• -11: Disk full
If either path name fails to specify a directory, the current directory is assumed.
The current directory is either the top-level directory or the subdirectory speci-
fied in the last call to File_SetDir.
// copy OLDFILE.TXT in the current directory to
NEWFILE.TXT
Result = File_Copy('OLDFILE.TXT', 'NEWFILE.TXT')

CHAR Buffer[1024]
SLONG NumFiles = 1
LONG Entry = 1

WHILE (NumFiles > 0)


{
NumFiles = FILE_DIR ('AAA:', Buffer, Entry)
Entry = Entry + 1
// add code to display contents of Buffer
}

120 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


FILE_CREATEDIR Creates a specified directory path.
Syntax:
SLONG File_CreateDir (CHAR DirPath[ ])
This function will not create the number of subdirectories needed to complete
the directory path if they do not exist. The subdirectories must be created one
level at a time.
Note: The LONG command cannot pass negative numbers, so if you have
errors these will never be recognized. SLONG must be assigned or errors will
be typecast to positive numbers.
Parameters:
• DirPath - string containing the directory path to create.
Result:
• 0 = operation was successful
• -4 = invalid directory path
• -5 = disk I/O error
• -13 = directory name exists
Example:
File_CreateDir('\CDLIST\')
File_CreateDir('\CDLIST\TEMP\')
Creates both \CDLIST and \CDLIST\TEMP subdirectories.
FILE_DELETE This function deletes the specified files.
SLONG FILE_DELETE (CHAR FilePath[ ])
Parameters:
• FilePath: Path name of the file to delete.
Result:
• 0: Operation was successful
• -2: Invalid file path or name
• -5: Disk I/O error
// delete all files in the directory \CDLIST\TEMP\Result =
File_Delete('\CDLIST\TEMP\')
FILE_DIR This function returns a list of files located at the specified path. The syntax:
SLONG FILE_DIR (CHAR DirPath[ ], CHAR Buffer[ ], LONG
Entry)
Parameters:
• DirPath: String containing the path to the requested directory.
• Buffer: Buffer to hold the directory list.
• Entry: Requested directory entry.
This function returns the number of remaining files in the directory, or:
• -4: Invalid directory path
• -5: Disk I/O error
• -6: Invalid parameter (i.e. Entry points beyond the end of the directory, or is 0)
• -10: Buffer too small
• -12: Directory not loaded
Note: The LONG command cannot pass negative numbers, so if you have errors
these will never be recognized. SLONG must be assigned or errors will be type-
cast to positive numbers.

NetLinx Programming Language Reference Guide 121


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


FILE_GETDIR This function returns the current working directory.
SLONG FILE_GETDIR (CHAR DirPath[ ])
Parameters:
• DirPath: Buffer to receive the current working directory.
Result:
• 0: Operation was successful
• -10: Size of DirPath buffer insufficient to hold directory path name
CHAR Buffer[256]Result = FILE_GETDIR (Buffer)
FILE_OPEN This function opens a file for reading or writing.
SLONG FILE_OPEN (CHAR FilePath[ ], LONG IOFlag)
Parameters:
• FilePath: String containing the path to the file to be opened
• IOFlag:
1 Read: The file is opened with READ ONLY status. The constant
FILE_READ_ONLY is defined as a value of 1 for specifying this flag.
2 R/W New: The file is opened with READ WRITE status. If the file currently
exists, its contents are erased. The constant FILE_RW_NEW is defined as a
value of 2 for specifying this flag.
3 R/W Append: The file is opened with READ WRITE status. The current
contents of the file are preserved and the file pointer is set to point to the end
of the file. The constant FILE_RW_APPEND is defined as a value of 3 for
specifying this flag.
If the open operation is successful, this function returns a non-zero integer
value representing the handle to the file. This handle must be used in subse-
quent read, write, and close operations.
• >0: Handle to file (open was successful)
• -2: Invalid file path or name
• -3: Invalid value supplied for IOFlag
• -5: Disk I/O error
• -14: Maximum number of files are already open
If the file is opened successfully, it must be closed after all reading or writing is
completed, by calling FILE_CLOSE. If files are not closed, subsequent file open
operations may fail due to the limited number of file handles available.
// Open MYFILE.TXT for reading hFile =
FILE_OPEN('MYFILE.TXT', FILE_READ_ONLY)

122 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


FILE_READ This function reads a block of data from the specified file.
SLONG FILE_READ (LONG hFile, CHAR Buffer[ ], LONG BufLen)
Parameters:
• hFile: Handle to the file returned by File_Open
• Buffer: Buffer to hold the data to be read
• BufLen: Maximum number of bytes to read
Result:
• >0: The number of bytes actually read
• -1: Invalid file handle
• -5: Disk I/O error
• -6: Invalid parameter
• -9: End-of-file reached
This function reads (from the current location of the file pointer) the number of
bytes specified by BufLen (or fewer bytes if the end of file is reached). The
bytes are read from the file identified by hFile and are stored in Buffer. The
file pointer will automatically be advanced the correct number of bytes so the
next read operation continues where the last operation left off.
CHAR Buffer[1024]nBytes = FILE_READ (hFile, Buffer, 1024)
FILE_READ_LINE This function reads a line of data from the specified file.
SLONG FILE_READ_LINE (LONG hFile, CHAR Buffer[ ], LONG
BufLen)
Parameters:
• hFile: Handle to the file returned by File_Open
• Buffer: Buffer to hold the data to be read
• BufLen: Maximum number of bytes to read
Result:
• =0:The number of bytes actually read
• -1: Invalid file handle
• -5: Disk I/O error
• -6: Invalid parameter (buffer length must be greater than zero)
• -9: End-of-file reached
This function reads from the current location of the file pointer up to the next
carriage return or to the end-of-file (EOF), whichever comes first. A complete
line will not be read if the buffer length is exceeded before a carriage return (or
EOF) is encountered. The bytes are read from the file identified by hFile and
are stored in Buffer. The <CR> or <CR><LF> pair will not be stored in Buffer.
If a complete line is read, the file pointer is advanced to the next character in the
file after the <CR> or <CR><LF> pair or to the EOF if the last line was read.
CHAR Buffer[80]nBytes = FILE_READ_LINE (hFile, Buffer,
80)

NetLinx Programming Language Reference Guide 123


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


FILE_REMOVEDIR This function removes the specified directory path, but it will not remove files or
directories below it.
CAUTION: If a subdirectory or files exist in the directory that you are trying to
remove, the operation will fail and will return a -5 (disk IO error).
SLONG FILE_REMOVEDIR (CHAR DirPath[ ])
Parameters:
• DirPath: String containing the directory path to remove.
Result:
• 0: Operation was successful
• -4: Invalid directory path
• -5: Disk I/O error
If you have \CDLIST\TEMP, and there are no files in either directory, the follow-
ing code will fail to delete the \CDLIST directory.
FILE_REMOVEDIR('\CDLIST')
The following code will delete the \CDLIST directory.
FILE_REMOVEDIR('\CDLIST\TEMP')FILE_REMOVEDIR('\CDLIST')
FILE_RENAME This function renames the specified file.
SLONG FILE_RENAME (CHAR FilePath[ ], CHAR NewFileName[ ])
Parameters:
• FilePath: Path name of the file to rename.
• NewFileName: New file name. This name must not contain a directory path.
Result:
• 0: Operation was successful
• -2: Invalid file name
• -5: Disk I/O error
• -8: File name exists
// renames \CDLIST\OLDFILE.TXT to
\CDLIST\NEWFILE.TXTResult = FILE_RENAME
('\CDLIST\OLDFILE.TXT', 'NEWFILE.TXT')
FILE_SEEK This function sets the file pointer to the specified position.
SLONG FILE_SEEK (LONG hFile, LONG Pos)
Parameters:
• hFile: Handle to the file returned by File_Open.
• Pos: The byte position to set the file pointer (0 = beginning of file, -1 = end of
file).
Result:
• >=0: Operation was successful and the result is the current file pointer value
• -1: Invalid file handle
• -5: Disk I/O error
• -6: Invalid parameter; pos points beyond the end-of-file (position is set to the
end-of-file)
After FILE_SEEK is successfully called, subsequent read or write operations
begin at the byte number specified by Pos.
// Sets the file pointer to byte number 1000. Subsequent
// read or write operations will begin at byte number
1000.Result = FILE_SEEK (hFile, 1000)

124 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


FILE_SETDIR This function sets the current working directory to the specified path.
SLONG FILE_SETDIR (CHAR DirPath[ ])
Parameters:
• DirPath: String containing the directory path.
Result:
• 0: Operation successful
• -4: Invalid directory path
• -5: Disk I/O error
Result = FILE_SETDIR ('\CDLIST\TEMP\')
FILE_WRITE This function writes a block of data to the specified file.
SLONG FILE_WRITE (LONG hFile, CHAR Buffer[ ], LONG BufLen)
Parameters:
• hFile: Handle to the file returned by File_Open.
• Buffer: Buffer containing the data to write.
• BufLen: Number of bytes to write.
Result:
• >0: The number of bytes actually written
• -1: Invalid file handle
• -5: Disk I/O error
• -6: Invalid parameter (buffer length must be greater than zero)
• -11: Disk full
The data will overwrite or append to the current contents of the file depending
on the current position of the file pointer.
CHAR Buffer[1024]Result = FILE_WRITE (hFile, Buffer,
1024)
FILE_WRITE_LINE This function writes a line of data to the specified file.
SLONG FILE_WRITE_LINE (LONG hFile, CHAR Line[ ], LONG
LineLen)
Parameters:
• hFile: Handle to the file returned by File_Open.
• Line: Buffer containing the line of data to write.
• LineLen: Number of bytes to write.
Result:
• >0: The number of bytes actually written
• -1: Invalid file handle
• -5: Disk I/O error
• -6: Invalid parameter (LineLen must be greater than zero)
• -11: Disk full
A <CR><LF> character pair is automatically appended to the end of the line.
CHAR Line[80]Result = FILE_WRITE_LINE (hFile, Line, 80)

NetLinx Programming Language Reference Guide 125


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


FIND_STRING This function searches through a string for a specified sequence of characters.
INTEGER FIND_STRING (CHAR STRING[ ], CHAR Seq[ ], INTEGER
Start)INTEGER FIND_STRING (WIDECHAR STRING[ ], WIDECHAR
Seq[ ], INTEGER Start)
Parameters:
• STRING: The string of character to search.
• Seq: The sequence of characters to search for.
• Start: The starting character position for the search.
Result:
A 16-bit unsigned integer representing the character location of Seq in STRING.
If the character string is found at the beginning of the string, this
function returns 1; any error condition returns 0.
POS = FIND_STRING(STRING, 'ABC', 1)
FIRST_LOCAL_PORT This keyword contains the lowest number that may be assigned as a local port
number. See the IP Communication section on page 189 for more information.
FLOAT This keyword defines an intrinsic data type representing a 32-bit signed
floating-point value.
FOR This keyword defines a FOR loop. The looping structure allows you to define ini-
tialization statements, statements to execute after each pass through the loop
and a condition to test after each pass. If the condition evaluates to true,
another pass is made; otherwise the loop is terminated.
FOR (<initial>; <condition>; <after pass>)
{
(* for loop statements *)
}
See the FOR loops section on page 18 for more information.

126 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


FORMAT Provides a mechanism similar to 'C's printf statement for formatting the dis-
play of numbers. This function is similar to ITOA but is infinitely more powerful.
CHAR[] FORMAT(CHAR FormatLine[],CHAR Value)CHAR[]
FORMAT(CHAR FormatLine[],WIDECHAR Value)CHAR[]
FORMAT(CHAR FormatLine[],INTEGER Value)CHAR[] FORMAT(CHAR
FormatLine[],SINTEGER Value)CHAR[] FORMAT(CHAR
FormatLine[],LONG Value)CHAR[] FORMAT(CHAR
FormatLine[],SLONG Value)CHAR[] FORMAT(CHAR
FormatLine[],FLOAT Value)CHAR[] FORMAT(CHAR
FormatLine[],DOUBLE Value)
Parameters:
• FormatLine: A formatted string of text that defines how the (return) string
should be formatted. The format string contains plain characters and a
conversion specification. Plain characters are copied, as is, directly.
Conversion characters conform to the following format:
%[flags][width][.prec]type
- flags: Output justification, numeric signs, decimal points, trailing zeros,
octal and hex prefixes. By default, output is right justified. Use a '-' to left justify
as in %-5d.
-: Causes left justification, padding with blanks
0: Zeros are used to pad instead of spaces if a field length is given.
+: Output always begins with + or -.
Blank: Positive values begin with a blank.
- width: Minimum number of characters to print. If the output would be less
than this width, it is padded with spaces to be width characters wide. If the
output is larger than width the entire output is provided (i.e. it is not truncated).
- .prec: Maximum number of characters to print or number of digits to the
right of the decimal point for a float or double type.
- type: Conversion type:
c: Value is treated as an integer, and presented as the character with that
ASCII value.
d: Value is treated as a signed integer, and presented as a decimal number.
f: Value is treated as a double, and presented as a floating-point number.
o: Value is treated as a signed integer, and presented as an octal number.
u: Unsigned integer.
x: Value is treated as an integer and presented as a hexadecimal number
(with lowercase letters).
X: Value is treated as an integer and presented as a hexadecimal number
(with uppercase letters).
%: A literal percent character.
• Value: The value to be converted to a string.
The result is a formatted text string.
fTemperature = 98.652
STR = FORMAT('The current temperature is
%3.2f',fTemperature)
// Displays "The current temperature is 98.65"
The table below shows some examples of the output of FORMAT for several dif-
ferent format lines and values:
FORMAT Statement Result of FORMAT function
FORMAT('%-5.2f',123.234) '123.23'
FORMAT('%5.2f',3.234) '3.23'
FORMAT('%+4d',6) '+6'

NetLinx Programming Language Reference Guide 127


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


FORMAT (Cont.) The result is a formatted text string.
fTemperature = 98.652
STR = FORMAT('The current temperature is
%3.2f',fTemperature)
// Displays "The current temperature is 98.65"
The table below shows some examples of the output of FORMAT for several dif-
ferent format lines and values:
FORMAT Statement Result of FORMAT function
FORMAT('%-5.2f',123.234) '123.23'
FORMAT('%5.2f',3.234) '3.23'
FORMAT('%+4d',6) '+6'
FTOA This function converts a floating-point value to an ASCII string containing the
decimal representation of the number.
CHAR[ ] FTOA (DOUBLE Num)
Parameters:
• Num: Floating-point number to convert to a decimal string.
The result is a character string that contains the decimal representation of the
specified floating-point number. The character representation will use expo-
nents if necessary.
STRING = FTOA(123.4) // STRING = '123.4'
GET_BUFFER_CHAR This keyword removes characters from a buffer.
Result = GET_BUFFER_CHAR (Array)
Array may be either a character array or wide character array; the operation is
identical in either case.
The result is a CHAR or WIDECHAR value depending on the variable type of
Array.
GET_BUFFER_CHAR has a two-part operation:
1. Retrieve the first character in the buffer.
2. Remove the retrieved character from the buffer and shift the remaining
characters by one to fill the gap.
GET_BUFFER_STRING This function removes characters from a buffer.
Result = GET_BUFFER_STRING (Array, Length)
Array may be either a character array or wide character array; the operation is
identical in either case. Length is the number of characters to remove.
Result is a CHAR or WIDECHAR value depending on the variable type of Array.
GET_BUFFER_STRING has a two-part operation:
1. Retrieve <length> number of characters from the buffer.
2. Remove the retrieved character from the buffer and shift the remaining
characters up to fill the gap.

128 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


GET_DNS_LIST This function returns the domain name and list of DNS server IP addresses that
the specified device is programmed to utilize. The order of the returned list is
the preferred server order.
DNS_STRUCT DnsListresult = GET_DNS_LIST(0:0:0,DnsList)
SLONG GET_DNS_LIST(DEV Device,DNS_STRUCT DnsList )
Parameters:
• Device: Device from which the DNS servers will be retrieved.
• DnsList: A DNS_STRUCT that will receive the device's DNS server list.
Result:
• 0: Operation was not successful
• -1: Specified device is invalid or is not online
• -2: Request timed out
• -3: Busy
The function requires a DNS_STRUCT. The DNS_STRUCT is predefined as fol-
lows:
STRUCTURE DNS_STRUCT
{
CHAR DomainName[68] // domain suffix (e.g. amx.com)
CHAR DNS1[15] // IP address of 1st DNS server
CHAR DNS2[15] // IP address of 2nd DNS server
CHAR DNS3[15] // IP address of 3rd DNS server
}
GET_IP_ADDRESS This function returns the TCP/IP configuration of the specified device. The con-
figuration information includes DHCP/Static configuration, IP address,
subnet mask, gateway, and host name.
SLONG GET_IP_ADDRESS(DEV Device,IP_ADDRESS_STRUCT
IPAddress)
Parameters:
• Device: Device from which the TCP/IP configuration will be retrieved.
• IPAddress: An IP_ADDRESS_STRUCT that will receive the device's TCP/IP
configuration.
Result:
• 0: Operation was successful
• -1: Specified device is invalid or is not online
• -2: Request timed out
• -3: Busy
The function requires an IP_ADDRESS_STRUCT..
The IP_ADDRESS_STRUCT is predefined as follows:
STRUCTURE IP_ADDRESS_STRUCT
{
CHAR Flags // Configuration flags
CHAR HostName[128] // Host name
CHAR IPAddress[15] // IP address unit
CHAR SubnetMask[15] // subnet mask
CHAR Gateway[15] // IP address of gateway
}
The following definitions exist for the Flags member of the
IP_ADDRESS_STRUCT structure.
CONSTANT CHAR IP_Addr_Flg_DHCP = 1 // Use DHCP

NetLinx Programming Language Reference Guide 129


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


GET_IP_ADDRESS (Cont.) The Flags member is a bit field that may be used for several different purposes.
Each bit is defined below:

Differing configuration parameters may be obtained, depending upon the con-


figuration of the network DHCP server. It is possible that the DHCP server will
provide the host name, IP address, subnet mask, gateway, and even DNS infor-
mation. In a minimal configuration, the DHCP server will only supply the IP
address and subnet mask.
IP_ADDRESS_STRUCT IPAddressResult =
GET_IP_ADDRESS(0:0:0,IPAddress)
Note: For NetLinx Central Controllers, the "Host Name" can only consist of
alphanumeric characters.
GET_LAST This function returns the index of the array element that most recently caused
an event handler to be triggered.
DEFINE_VARIABLE
DEVCHAN dcMyDCSet[] = { {TP,5}, {TP,4}, {TP,3}, {TP,2},
{TP,1}}
INTEGER Index

BUTTON_EVENT[dcMyDCSet]
{
PUSH:
{
Index = GET_LAST(dcMyDCSet)
Switch (Index)
{
Case 1: {} (* Button 5 was pressed *)
Case 2: {} (* Button 4 was pressed *)
Case 3: {} (* Button 3 was pressed *)
Case 4: {} (* Button 2 was pressed *)
Case 5: {} (* Button 1 was pressed *)
}
}
}
Result:
• 0: No Event was triggered using this array.
• >0: The index that causes an event to be triggered.
Since the PUSH and RELEASE keywords can be written using DEVCHAN arrays,
this function can also be used to determine which element causes a push or
release to be triggered. The function can be called anywhere in code but is usu-
ally called from within an event handler. A classic application of this function is
to determine the keypad number pressed when the channel codes for the key-
pad are out of order, which they typically are for a wireless transmitter.
Note: GET_LAST works with BUTTON_EVENTS and CHANNEL_EVENTS, but not
with LEVEL_EVENTS.

130 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


GET_MULTI_BUFFER_ To access characters coming into a multi-buffer, you must first use
STRING GET_MULTI_BUFFER_STRING to transfer these characters into another array.
For example:
Device = GET_MULTI_BUFFER_STRING (Buffer, Array)
The next string in the specified buffer is copied to the specified array. All three
header bytes are stripped before the string is copied. If
CREATE_MUTLI_BUFFER was defined using a FirstDevice and LastDe-
vice, the return value Device is the device number (not the Port number) of
the card that received the string. If CREATE_MUTLI_BUFFER was defined using
a DeviceSet, the return value Device is the device index into the DeviceSet
array of the card that received the string.
GET_PULSE_TIME This keyword returns the current duration of PULSE and MINTO commands as
set by SET_PULSE_TIME. Time is measured in tenths of a second; the default
is 5 (0.5 seconds).
PulseTime = GET_PULSE_TIME
GET_SERIAL_NUMBER This function returns the 16-character serial number of the specified device.
The serial number of every device is established when manufactured.
SLONG GET_SERIAL_NUMBER(DEV Device,CHAR SerialNumber[ ] )
Parameters:
• Device: Device from which the serial number will be retrieved.
• SerialNumber: String that will receive the device's serial number.
Result:
• 0: Operation was successful
• -1: Specified device is invalid or is not online
Result = GET_SERIAL_NUMBER(128:1:0,serialNum)
GET_SYSTEM_NUMBER This function returns the system number of the NetLinx Master.
INTEGER GET_SYSTEM_NUMBER( )
The result is an integer representing the system number of the NetLinx Master.
SystemNum = GET_SYSTEM_NUMBER() // get local system num
Note: When it is a NetLinx function the ( ) are NOT OPTIONAL even if there are
no parameters.
GET_TIMER This keyword returns an unsigned long integer representing the value currently
held by the system timer. Time is measured in tenths of a second. The system
timer is set to zero on power-up.
SystemTime = GET_TIMER
GET_UNIQUE_ID This function returns a 48-bit hardware constant guaranteed to be unique in the
domain of NetLinx Masters. Possible uses for GET_UNIQUE_ID include identifi-
cation of a particular system for the purpose of providing system specific capa-
bility or limiting the functionality of a NetLinx program to operate on a specific
master.
CHAR[6] GET_UNIQUE_ID ( )
The result is a 48-bit constant returned as a 6-element character array.
SYSID = GET_UNIQUE_ID() // get the master's h/w ID
IF(sysID = "$00,$01,$09,$73,$25,$01")
{
// allow system to operate
normally
}

NetLinx Programming Language Reference Guide 131


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


GET_URL_LIST This function returns a list of URLs that the specified device is programmed to
actively attempt to connect to. The function requires an array of URL_STRUCT
Structures that will get filled in with the device's URL list.
SLONG Get_URL_List(DEV Device,URL_STRUCT
UrlList[ ],INTEGER Type )
Parameters:
• Device: Device number of the device from which the URLs will be retrieved.
Typically, they are stored on the local master (0:1:0), but if you are currently
connected to another master your can use <0:1:system number of remote
master>.
• UrlList: Array of URL_STRUCTs that will receive the device's URLs
• Type: Indicates the type(s) of URLs desired-NetLinx language programmed,
IDE programmed, or both
1: All URLs
2: NetLinx programmed URLs
3: IDE programmed URLs
The function returns the number of URLs updated in the supplied array of
URL_STRUCTs.
-1: Specified device is invalid or is not online
-2: Request timed out
-3: Busy
URLs may be programmed by either the Integrated Development environment
or via the ADD_URL_ENTRY function. The Type parameter filters the list of URLs
so that only the desired URLs are returned in the URL_STRUCT(s). The function
requires an array of URL_STRUCTs.
The URL_STRUCT is predefined as follows:
STRUCTURE URL_STRUCT
{
CHAR Flags // Connection Type (normally 1)
INTEGER Port // TCP port (normally 1319)
CHAR URL[128] // string: URL or IP address
}
The following definitions exist for the Flags member of the URL_STRUCT struc-
ture.
CONSTANT CHAR URL_Flg_TCP = 1 // TCP
connection
CONSTANT CHAR URL_Flg_TEMP = $10
CONSTANT CHAR URL_Flg_Stat_PrgNetLinx = $20 // URL set by
// NetLinx
// ADD_URL_ENTRY
CONSTANT CHAR URL_Flg_Stat_Mask = $C0 // status mask
CONSTANT CHAR URL_Flg_Stat_Lookup = $00 // Looking up
IP
CONSTANT CHAR URL_Flg_Stat_Connecting = $40 // connecting
CONSTANT CHAR URL_Flg_Stat_Waiting = $80 // waiting
CONSTANT CHAR URL_Flg_Stat_Connected = $C0 // connected

132 NetLinx Programming Language Reference Guide


Reserved Identifiers

The Flags member is a bit field that is used for several different purposes.
Each bit is defined in the table below:

GET_URL_LIST flags member bit fields


Bit Mathematical Normal Meaning
Value value
Bit 0 1 (0x01) 1 0 = Establishes a UDP connection.
1 = Establishes a TCP connection.
Bit 1 2 (0x02) 0 Unused
Bit 2 4 (0x04) 0 Unused
Bit 3 8 (0x08) 0 Unused
Bit 4 16 (0x10) 0 Establishes a Temp Connection. A Temp Connection is
one that is set, but is not stored in flash, and therefore is
not restored when the master reboots. If the NetLinx code
is adding URL entries, it is recommended to make them
temporary so that the flash is not constantly being written,
especially since the code handles all the connections any-
way.
Bit 5 32 (0x20) 0 Source of URL.
0 = Programmed by the IDE.
1 = Programmed by NetLinx ADD_URL_ENTRY.
Bit 6 64 (0x40) 0 Encoded status indication (Read only).
Bit 7 128 (0x80) These 2 bits together form one of 4 possible codes indicat-
ing the status of the connection.
• 0x00 - Looking up IP address or URL.
• 0x40 - Connecting to URL.
• 0x80 - Waiting for connection to establish.
• 0xC0 - Connected.

Keywords & Run-Time Library Functions (Cont.)


GET_URL_LIST (Cont.) Example:
URL_STRUCT UrlList [10]
Result = GET_URL_LIST(0:0:0,UrlList,0) (* Get ALL URLs *)
-or-
Result = GET_URL_LIST(0:0:0,UrlList,1)(* Get NetLinx-
programmed URLs *)
-or-
Result = GET_URL_LIST(0:0:0,UrlList,2)(* Get IDE-
programmed URLs *)
Note: There is a known issue with this function: If you have only 1 URL entry, it
will return nothing. If you have 2 entries, it will return the second entry.
HEXTOI This function converts an ASCII string containing the hexadecimal representa-
tion of a number to an unsigned 32-bit integer.
LONG HEXTOI (CHAR STRING[ ])
Parameters:
• STRING: Hexadecimal formatted string to be converted to an integer.
The result is a 32-bit unsigned integer representing the converted string. Any
non-hexadecimal characters in the string are ignored. HEXTOI returns a value
representing the first complete set of characters that represents an integer.
Valid characters are "0" through "9", "A" through "F" and "a" through "f". If no
valid characters are found, zero is returned as a result.
Num = HEXTOI('126EC') // Num = 75500

NetLinx Programming Language Reference Guide 133


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


HOLD This keyword defines a section in a BUTTON event handler for processing HOLD
events.
IF This keyword defines an IF statement; the IF statement provides conditional
branching of program execution.
IF (<expression>)
{
// statements
}
ELSE IF (<expression>)
{
// statements
}
ELSE
{
// statements
}
The ELSE IF and ELSE statements are optional. The braces delimiting the
statements, associated with each condition, are required only if there is more
than one statement. Refer to ELSE for more information. For example, the fol-
lowing syntax is correct:
IF (X > 0)
X = X - 1
INCLUDE This keyword allows you to include programming instructions from an external
file and have those instructions inserted at any point in the program.
INCLUDE '<filename>'
The parameter filename can be any valid (long) filename. If the file extension
is omitted, "AXI" is assumed. An INCLUDE statement can appear anywhere in
a program.
Note: There is no difference in functionality between the INCLUDE reserved
identifier and the #INCLUDE compiler directive. INCLUDE is supported for
backward-compatibility to Axcess.
INTEGER This keyword defines an intrinsic data type representing a 16-bit unsigned inte-
ger. This is the default data type if a non-array variable is declared without a
data type specified.
IP_CLIENT_CLOSE This function closes a port opened with IP_CLIENT_OPEN.
IP_CLIENT_CLOSE (INTEGER LocalPort)
Parameters:
• LocalPort: A non-zero integer value representing the local port on the
client machine to close.
Result: This function always returns 0. Errors are returned via the
DATA_EVENT ONERROR method. The following error may be returned:
9: Already closed
See the IP Communication section on page 189 or more information.

134 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


IP_CLIENT_OPEN This function opens a port for IP communication with a server.
SLONG IP_CLIENT_OPEN
(INTEGER LocalPort,
CHAR ServerAddress[ ],
LONG ServerPort,
INTEGER Protocol)
Parameters:
• LocalPort: A user-defined (non-zero) integer value representing the local
port on the client machine to use for this conversation. This local port
number must be passed to IP_Client_Close to close the conversation.
• ServerAddress: A string containing either the IP address (in dotted-quad-
notation) or the domain name of the server to connect to.
• ServerPort: The port number on the server that identifies the program or
service the client is requesting.
• Protocol: The transport protocol to use:
1 = TCP
2 = UDP
3 = UDP with Receive
If this parameter is not specified, TCP (1) is assumed. The constants
IP_TCP, IP_UDP and IP_UDP_2WAY can be used to specify this parameter.
Result:
This function always returns 0. Errors are returned via the DATA_EVENT
ONERROR method. The following errors may be returned:
2: General failure (out of memory)
4: Unknown host
6: Connection refused
7: Connection timed out
8: Unknown connection error
14: Local port already used
16: Too many open sockets
17: Local Port Not Open
Example:
IP_CLIENT_OPEN(PORT1, SvAddr, SvPort, IP_TCP)
Seethe IP Communication section on page 189 for more information.

NetLinx Programming Language Reference Guide 135


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


IP_MC_SERVER_OPEN This function opens a server port to listen for UDP multicast messages.
SINTEGER IP_MC_SERVER_OPEN(INTEGER LocalPort, CHAR
MultiCastIP[], LONG ServerPort)
Parameters:
• LocalPort: The local port number to open. This number must be passed to
IP_SERVER_CLOSE to close the port.
• MultiCastIP: A character string representing the multicast address to
receive on in the form of: '239.255.255.250'.
• ServerPort: The UDP multicast port number to listen on.
Result:
This function always returns 0. Errors are returned via the DATA_EVENT
ONERROR method. The following error may be returned:
2: General failure (out of memory)
10: Binding error
11: Listening error
14: Local port already used
15: UDP socket already listening
16: Too many open sockets
Example:
IP_MC_SERVER_OPEN (PORT1,'239.255.255.250',1900)
IP_SERVER_CLOSE This function closes a port opened with IP_SERVER_OPEN or
IP_MC_SERVER_OPEN.
IP_SERVER_CLOSE (INTEGER LocalPort)
Parameters:
• LocalPort: The number of the local port to close.
Result: This function always returns 0. Errors are returned via the
DATA_EVENT ONERROR method. The following error may be returned:
9: Already closed
Example:
IP_Server_Close(PORT1)
See the IP Communication section on page 189 for more information.

136 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


IP_SERVER_OPEN This function opens a server port to listen for client requests.
SLONG IP_SERVER_OPEN (INTEGER LocalPort,
LONG ServerPort,
INTEGER Protocol)
Parameters:
• LocalPort: The local port number to open. This number must be passed to
IP_Server_Close to close the port.
• ServerPort: The number of the server port to listen on.
• Protocol: The transport protocol to use:
1 = TCP
2 = UDP
If this parameter is not specified, TCP (1) is assumed. The constants
IP_TCP and IP_UDP can be used to specify this parameter.
Result (via ONERROR event):
2: General Failure
10: Binding error
11: Listening error
14: Local port already used
15: UDP socket already listening
16: too many open sockets
Example:
IP_SERVER_OPEN (PORT1, SvPort, IP_TCP)
SeeIP Communication section on page 189 for more information.
ITOA This function converts a 32-bit signed integer to a decimal ASCII string.
CHAR[ ] ITOA (LONG Num)
Parameters:
• Num: The 32-bit unsigned integer to convert to a decimal string.
Result:
A character string that contains the decimal representation of the specified
integer.
STRING = ITOA(501)// STRING = '501'
ITOHEX This function converts a 32-bit unsigned integer to an ASCII string containing
the hexadecimal representation of the number.
CHAR[ ] ITOHEX (LONG Num)
Parameters:
• Num: The 32-bit unsigned integer to convert to a hexadecimal string.
Result:
A character string that contains the hexadecimal representation of the speci-
fied integer.
STRING = ITOHEX(1000) // STRING = '3E8'
LDATE The system variable LDATE returns the current date in (mm/dd/yyyy) string for-
mat.
IF (LDATE = '12/25/2000'){}

NetLinx Programming Language Reference Guide 137


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


LEFT_STRING This function returns the specified number of characters from the beginning of
a string.
CHAR[ ] LEFT_STRING (CHAR STRING[ ], LONG Count)
WIDECHAR[ ] LEFT_STRING (WIDECHAR STRING[ ], LONG Count)
Parameters:
• STRING: The string from which to extract the characters.
• Count: The number of character to copy from the beginning of the string.
The result is a string containing a copy of the first Count characters from
STRING.
STRING = 'ABCDEFG'Substr = LEFT_STRING(STRING, 3)
// Substr = 'ABC'
LENGTH_ARRAY This function returns the effective length of a dimension of an array - implicitly
through array initialization or array manipulation operations (+ and -) or explic-
itly through a call to the function SET_LENGTH_ARRAY.
LONG LENGTH_ARRAY (<type> Array[ ])
Parameters:
• <type>: May be any intrinsic or user-defined data type
• Array: An array of any type.
The result is the effective (or working) length of the array.
INTEGER Len
INTEGER Array1[ ] = {3, 4, 5, 6, 7}
INTEGER Array2[ ] = {1, 2}
INTEGER My3DArray[5][3][4] =
{
{
{1,2,3,4},
{5,6,7,8},
{9,10,11}
}
{
{13,14}
}
}
Len = LENGTH_ARRAY(Array1) // Len = 5
Len = LENGTH_ARRAY(Array2) // Len = 2

Len = LENGTH_ARRAY(My3Darray)
(* Len = 2, the number of tables *)

Len = LENGTH_ARRAY(My3Darray[2])
(* Len = 1, the number of rows in table 2 *)

Len = LENGTH_ARRAY(My3Darray[1][3])
(* Len = 3, the number of columns in table 1, row 3 *)

See SET_LENGTH_ARRAY, on page 150, for more information.

138 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


LENGTH_STRING This function returns the length of a CHAR or WIDECHAR string. This function is
retained for compatibility with previous versions of Axcess and provides the
same information as LENGTH_ARRAY.
LONG LENGTH_STRING (CHAR STRING[ ])
LONG LENGTH_STRING (WIDECHAR STRING[ ])
Parameters:
• STRING: The input character string.
The result is the length of STRING. The string length can be set implicitly
through a literal or variable string assignment or explicitly by calling
SET_LENGTH_STRING. For example:
IF (LENGTH_STRING(STRING) > 0)
{
// process string
}
LENGTH_VARIABLE_TO_ This routine calculates how many bytes it takes to encode a variable.
STRING LONG LENGTH_VARIABLE_TO_STRING (VARIABLE Encode)
(VARIABLE Encode)
Parameters:
• Encode: The variable (any type) to be encoded.
Result:
• >0: Number of bytes required to encode variable.
• 0: Encoded variable error, unrecognized type
LENGTH_VARIABLE_TO_ CHAR LENGTH_VARIABLE_TO_XML(CONSTANT VARIANTARRAY A,
XML LONG B)
Where:
• A is the variable (any type) to be encoded.
• B is the encoding flag. These can be used together.
Value $01 is "Encode with Types". If the bit is set, types will be included for
every variable being encoded. The default is to not include types.
Value $10 is "Encoded CHAR arrays as using data list". See the Binary array
encoding section on pages 219.
Value $20 is "Array Encoding is Little-Ending".
The return is the length needed to encode the variable.
LEVEL_EVENT This keyword defines a level event handler and can only be used in the
DEFINE_EVENT section of the program. This type of handler is invoked when a
level change occurs on the specified device-channel. The level object is avail-
able to the level event handler as a local variable.
LEVEL_EVENT[DEVICE,LEVEL] or LEVEL_EVENT[([DEVLEV[ ])]
{
// level event handler
}
See the Event Handlers section on page 61 for more information.
LOCAL_VAR This keyword specifies a variable that is static. To provide compatibility with the
Axcess language, local variables may be declared right before the opening
brace for DEFINE_CALL declarations only.
If neither the LOCAL_VAR nor the STACK_VAR keyword is specified,
STACK_VAR is assumed.
See the Variables section on page 11 for more information.
LONG This keyword defines an intrinsic data type representing a 32-bit unsigned
value.

NetLinx Programming Language Reference Guide 139


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


LONG_WHILE This keyword is the same as a WHILE statement except that input messages
are retrieved after each pass to allow the LONG_WHILE statements to process
the input.
LONG_WHILE (<conditional expression>){(* conditional
statements *)}
See the Language Elements section on page 31 for more on programming
loop constructs.
LOWER_STRING This function changes all alphabetic characters in the specified string to lower
case.
CHAR[ ] LOWER_STRING (CHAR STRING[ ])
WIDECHAR[ ] LOWER_STRING (WIDECHAR STRING[ ])
Parameters:
• STRING: The character string to convert to lower case.
The result is the converted character string.
LCString = LOWER_STRING(STRING)
LSHIFT This keyword causes the bits in the associated integer field to be shifted left.
This has the effect of multiplying by 2n, where n is the number of bit positions
to shift. The symbol << is equivalent to LSHIFT. For example:
INT2 = INT1 LSHIFT 2
is equivalent to:
INT2 = INT1 << 2
Both statements shift INT1 left two positions. Either statement could be
replaced with the following:
INT2 = INT1 * 4
MASTER_SN This keyword contains the serial number of the master processor.
MASTER_SLOT This keyword represents the slot number the master card is plugged into. "0" is
the primary master; "1" is the secondary master. This keyword is primarily
associated with Axcess systems. NetLinx systems have only one master, so
MASTER_SLOT in NetLinx is always "0".
MAX_VALUE Provides the value of the highest of two variables. It will take any intrinsic vari-
able type and return the same type of the highest variable.
MaxVal MAX_VALUE (Var1,Var2)
DEFINE_VARIABLE
SLONG Var1, Var2, VarMax
DEFINE_START
Var1 = 100
Var2 = 200
DEFINE_PROGRAM
VarMax = MAX_VALUE (Var1,Var2) // VarMax = 200
MAX_LENGTH_ARRAY This function returns the maximum length of a dimension of an array.
LONG MAX_LENGTH_ARRAY (<type> Array[ ])
Parameters:
• <type>: May be any intrinsic or user-defined data type.
• Array: An array of any type.
Result:
The length of the specified dimension of Array.
FLOAT FPArray[10]
LONG NumArray[5][3][4]

Len = MAX_LENGTH_ARRAY(FPArray) // Len = 10


Len = MAX_LENGTH_ARRAY(NumArray) // Len = 5
Len = MAX_LENGTH_ARRAY(NumArray[1]) // Len = 3
Len = MAX_LENGTH_ARRAY(NumArray[1][1]) // Len = 4

140 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


MAX_LENGTH_STRING This function returns the dimensioned length of a CHAR or WIDECHAR string.
This function is retained for compatibility with previous versions of Axcess. It
provides the same information as MAX_LENGTH_ARRAY.
LONG MAX_LENGTH_STRING (CHAR STRING[ ])
LONG MAX_LENGTH_STRING (WIDECHAR STRING[ ])
Parameters:
• STRING: The input character string.
Result:
The dimensioned length of STRING.
MaxLen = MAX_LENGTH_STRING(STRING)
Len = LENGTH_STRING(STRING)

IF (MaxLen > Len)


{
// append character to STRING
}
MEDIUM_WHILE This keyword is obsolete in the new NetLinx system. The compiler will treat it
as a WHILE keyword. See the Language Elements section on pages 31 for
information on programming loop constructs.
MID_STRING This function returns the specified number of characters, starting at the speci-
fied location in the source string.
CHAR[ ] MID_STRING (CHAR STRING, LONG Start, LONG Count)
WIDECHAR[ ] MID_STRING (WIDECHAR STRING, LONG Start, LONG
Count)
Parameters:
• STRING: The input character string.
• Start: Starting location in the string.
• Count: Number of characters to extract.
The result is a character string containing the specified characters.
STRING = 'ABCDEFGHIJK'
Substr = MID_STRING(STRING, 5, 4)
(* Substr = 'EFGH' *)
MIN_VALUE Provides the value of the lowest of two variables. It will take any intrinsic vari-
able type and return the same type of the lowest variable.
MinVal MIN_VALUE (Var1,Var2)
DEFINE_VARIABLE
SLONG Var1, Var2, VarMin
DEFINE_START
Var1 = 100
Var2 = 200
DEFINE_PROGRAM
VarMin = MIN_VALUE (Var1,Var2) // VarMin = 100
MIN_TO This keyword operates just like the TO keyword, except that the specified chan-
nel or variable stays on for a minimum length of time, even if the corresponding
channel is released. The minimum length of time is set by SET_PULSE_TIME.
MIN_TO follows the same conditions of operation as the TO keyword.
See SET_PULSE_TIME, on page 150, for more information.

NetLinx Programming Language Reference Guide 141


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


MOD (%) This keyword is used to generate the remainder of a division function.
Note: You cannot take the mod of an integer without first loading the value into
a variable. For example:
VRAM_LSB = ((2 % 16)+$30) (* does not work *)
However,
ID = 2
OTHER = 16
VRAM_LSB = ((ID % OTHER) + $30) (* works *)
MODULE_NAME This keyword introduces the definition of a module. It must appear on the first
line of the module implementation file.
MODULE_NAME = '<module name>' (<parameter list>)
See DEFINE_MODULE, on page 142, for more information.
NOT (!) This keyword is used to negate a given expression.
IF (NOT (X > 10))
{
// statements to execute if X <= 10
}
NON_VOLATILE A variable declared with the NON_VOLATILE keyword is stored in non-volatile
memory. It retains its value in the event of a system power-down, but is reset to
zero if the program is reloaded. Unless specified otherwise, all variables are
stored in non-volatile memory.
OFF This keyword is used to turn a channel or variable off. If used with a variable,
OFF sets it to zero.
OFF[DEVICE,CHANNEL]
OFF[(DEVCHAN[ ])]
OFF[Variable]
OFFLINE This keyword defines a section in a DATA event handler for processing
OFFLINE notifications. This is one of the important aspects of the
DATA_EVENT that is triggered when the master recognizes that a device has
been dropped off the bus.
ON This keyword is used to turn a channel or variable on. If used with a variable,
ON sets it to 1.
ON[DEVICE,CHANNEL]
ON[(DEVCHAN[ ])]
ON[Variable]
ONERROR This keyword defines a section in a DATA event handler for processing
ONERROR notifications. Any error triggers an ONERROR event.
ONLINE This keyword defines a section in a DATA event handler for processing ONLINE
notifications. This is one aspect of DATA_EVENT that is triggered when the
master recognizes that a device has been added to the bus. In NetLinx, every
device triggers an ONLINE event when the master is reset. This ensures that
the device is initialized on startup and that the device is initialized any time the
device comes online.
OR (||) This keyword evaluates two conditions. If one or both conditions are true, the
entire expression evaluates to true.
PAUSE_ALL_WAIT This keyword suspends all WAITs currently in effect.
PAUSE_WAIT This keyword suspends the specified (named) WAIT until a RESTART_WAIT,
RESTART_ALL_WAIT, CANCEL_WAIT, or CANCEL_ALL_WAIT command is
issued.
PAUSE_WAIT '<wait name>'

142 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


PERSISTENT If a variable is declared with the PERSISTENT keyword, it is initialized to zero
the first time the program is loaded but will retain its value after power-down or
reload.
• The PERSISTENT attribute does not apply to non-static local variables, since
non-static local variables are allocated on the program stack (a block of
memory reserved for allocation of temporary variables).
• The PERSISTENT attribute does not apply to the individual members of a
structure.
PROGRAM_NAME This keyword declares the program name. It must appear on the first line of
the program and cannot appear more than once in any single program or
include file.
PROGRAM_NAME = '<program name>'
PULSE This keyword turns a channel or variable on for the length of time set by the
function SET_PULSE_TIME. Once the pulse time elapses, the channel or vari-
able is turned off. The default pulse time is 0.5 seconds.
PULSE [DEVICE,CHANNEL]
PULSE [DEVCHAN[ ]]
PULSE [Variable]
PUSH This keyword declares a block of code to be executed when a push event is
received for the associated device and channel. An example PUSH statement
is shown below:
PUSH [DEVICE,CHANNEL]PUSH [(DEVCHAN[ ])]
{// statements}
This keyword also defines a section in the BUTTON_EVENT handler for pro-
cessing PUSH events.
PUSH_CHANNEL This keyword contains the channel number that was just turned on due to an
input change. The value remains valid for one pass through mainline. The inac-
tive state of this variable is all fields equal to zero.
PUSH_DEVCHAN This keyword contains the device-channel (a DEVCHAN structure) that was just
turned on due to an input change. Individual fields of this DEVCHAN structure
can be accessed using dot-operator syntax, as shown below:
PUSH_DEVCHAN.Device
PUSH_DEVCHAN.Device.Number
PUSH_DEVCHAN.Device.Port
PUSH_DEVCHAN.Device.System
PUSH_DEVCHAN.Channel
These fields remain valid for one pass through mainline. The inactive state of
this variable is all fields equal to zero.
PUSH_DEVICE This keyword contains the number of the device that was just turned on due to
an input change. The value remains valid for one pass through mainline. The
inactive state of this variable is all fields equal to zero.
RANDOM_NUMBER This function returns a random number X in the range 0 <= X < Max.
LONG RANDOM_NUMBER (LONG Max)
Parameters:
• Max: An unsigned long integer (must be greater than zero) that will serve as
the upper limit for the random number generator.
The result is an unsigned long integer >= 0 and < Max.
Num = RANDOM_NUMBER(1000) // 0 <= Num < 1000
RAW_BE This routine takes an intrinsic variable and converts it into a Character Array in
Big Endian Format representing the variable.
CHAR[] RAW_BE(IntrinsicVariable)
RAW_LE This routine takes an intrinsic variable and converts it into a Character Array in
Little Endian Format representing the variable.
CHAR[] RAW_LBE(IntrinsicVariable)

NetLinx Programming Language Reference Guide 143


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


REBOOT This keyword causes the device to reset and is equivalent to doing a power
down and up on the master.
REBOOT (DEVICE)
Parameters:
• DEVICE = ICSP device number to reboot.
Note: Not all ICSP devices implement the reboot command.
DEVICE refers to:
- Device – a single device number.
- Dps – a DEV structure.
- D:P:S – a device specification such as 128:1:0.
- DEV[ ] – a device array.
Examples:
REBOOT (0:0:0)
or
REBOOT (0:1:0) or REBOOT (0)
Any of these examples will cause the master to reboot.
REBUILD_EVENT() The NetLinx runtime supports a new NetLinx function, REBUILD_EVENT(),
that rebuilds the NetLinx event table for level, channel, button, timeline, and
data events. Modifications to variables used in event declarations affect
NetLinx event handling when REBUILD_EVENT() is called after the variables
are modified.
REBUILD_EVENT() works on a module-by-module basis (i.e. calling the func-
tion in one module does not affect the event table of another module).
REBUILD_EVENT() rebuilds the event table for variables modified in the same
block of code in which it resides.
With no braces, a REBUILD_EVENT() in DEFINE_START rebuilds event
tables that use any variable modified in DEFINE_START, above the
REBUILD_EVENT() statement.
You can reduce the scope of the REBUILD_EVENT() by delineating a block
with braces as shown at the bottom of the following example:
The code below demonstrates how to use the NetLinx REBUILD_EVENT()
function:
DEFINE_DEVICE
dvApoc1 = 128:1:0
dvApoc2 = 1505:1:0
dvApoc3 = 1303:1:0
(*----------------------------------------------------*)
(* CONSTANT DEFINITIONS GO BELOW *)
(*----------------------------------------------------*)
DEFINE_CONSTANT
DEV panel[] = {dvApoc1,dvApoc2}
(*----------------------------------------------------*)
(* DEFINE TYPE DEFINITIONS GO BELOW *)
(*----------------------------------------------------*)
DEFINE_TYPE
(*----------------------------------------------------*)
(* VARIABLE DEFINITIONS GO BELOW *)
(*----------------------------------------------------*)
DEFINE_VARIABLE
DEV curModApoc
(*----------------------------------------------------*)
(* EVENT DEFINITIONS GO BELOW *)
(*----------------------------------------------------*)

144 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


REBUILD_EVENT() (Cont.) DEFINE_EVENT
BUTTON_EVENT[panel,1]
{
PUSH:
{
ON[panel,1]
curModApoc = dvApoc2

// updates program event table to handle


// BUTTON_EVENT[1505:1:0,5]
REBUILD_EVENT()
}
RELEASE: OFF[panel,1]
}
BUTTON_EVENT[panel,2]
{
PUSH:
{
ON[panel,2]
curModApoc = dvApoc3

// updates program event table to handle


// BUTTON_EVENT[1303:1:0, 5]
REBUILD_EVENT()

// the following assignment has no affect on the program


// event table
curModApoc = dvApoc1
}
RELEASE: OFF[panel,2]
}
BUTTON_EVENT[curModApoc,5]
{
PUSH: ON[dvApoc3,5]
RELEASE: OFF[dvApoc3,5]
}
// end
// REBUILD_EVENT() rebuilds the event table for
// variables modified in the same block of code in which
// it resides.
//
// With no braces, a REBUILD_EVENT() in DEFINE_START
// should rebuild the event tables that use any variable
// modified in DEFINE_START, above the REBUILD_EVENT()
// statement.

// You can reduce the scope of the REBUILD_EVENT() by


// delineating a block with braces:
DEFINE_DEVICE
dvTP = 10001:1:0
DEFINE_VARIABLE
INTEGER X // loop counter
INTEGER nBTNS[4000]
DEFINE_START
FOR (X = 1; X <= 4000; X++)
{
nBtns[X] = X
}
// the braces below enclose a variable update and
// rebuild_event statement in a single block

NetLinx Programming Language Reference Guide 145


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


REBUILD_EVENT() (Cont.) {
SET_LENGTH_ARRAY(nBtns,4000)
REBUILD_EVENT()
}
BUTTON_EVENT[dvTP,nBtns]
{
PUSH:
{
// ...
}
}
// end
REDIRECT_STRING This keyword is used to pass all strings from device 1 to device 2 and all
strings from device 2 to device 1. This is called a redirection and you can
assign up to eight at one time.
REDIRECT_STRING (Number, DEV1, DEV2)
The parameter Number identifies the particular redirection (1-8). To cancel a
redirection, pass zero for Device1 and Device2.
Note: Redirections are lost if system power is turned off.
RELEASE This keyword declares a block of code to be executed when a release event is
received for the associated device and channel.
RELEASE [DEVICE,CHANNEL]
RELEASE [DEVCHAN[ ]]
{
// statements
}
This keyword also defines a section in a BUTTON_EVENT handler for process-
ing RELEASE events.
RELEASE_CHANNEL This keyword contains the number of the channel that was just turned off due
to an input change. The value remains valid for one pass through mainline.
The inactive state of this variable is all fields equal to zero.
RELEASE_DEVCHAN This keyword contains the device-channel (a DEVCHAN structure) that was just
turned off due to an input change. Individual fields of this DEVCHAN structure
can be accessed using dot-operator syntax, as shown below:
RELEASE_DEVCHAN.Device
RELEASE_DEVCHAN.Device.Number
RELEASE_DEVCHAN.Device.Port
RELEASE_DEVCHAN.Device.System
RELEASE_DEVCHAN.Channel
These fields remain valid for one pass through mainline. The inactive state of
this variable is all fields equal to zero.
RELEASE_DEVICE This system variable contains the number of the device associated with the
channel that was just turned off due to an input change. The value remains
valid for one pass through mainline. The inactive state of this variable is all
fields equal to zero.

146 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


REMOVE_STRING This function removes characters from the specified string. All characters up to
and including the first occurrence of the specified sequence are removed.
CHAR[ ] REMOVE_STRING (CHAR STRING, CHAR Seq[ ], LONG
Start)
WIDECHAR[ ] REMOVE_STRING (WIDECHAR STRING, WIDECHAR Seq[
], LONG Start)
Parameters:
• STRING: String from which to find and remove characters.
• Seq: Sequence of characters to find.
• Start: Starting position in the string to begin search.
The result is a string containing the removed characters. If the character
sequence was not found, an empty string is returned.
STRING = 'ABCDEF'
Substr = REMOVE_STRING(STRING, 'BC', 1)
(* Substr = 'ABC' *)
(* STRING = 'DEF' *)
REPEAT This keyword may be used with the HOLD keyword to specify that the (hold but-
ton) event should be allowed to repeat.
See the Event Handlers section on page 61 for more information.
RESTART_ALL_WAIT This command resumes all waits that were previously paused. This includes
both named and unnamed waits.
RESTART_WAIT This keyword resumes the specified (named) wait previously paused by a
PAUSE_WAIT command.
RESTART_WAIT '<wait name>'
RETURN This keyword is used in a DEFINE_FUNCTION or DEFINE_CALL subroutine to
prematurely terminate execution and/or to return a value to the caller. Only
DEFINE_FUNCTION functions can return values using the RETURN statement.
The syntax of the RETURN statement is either:
RETURN // DEFINE_CALL or function with no return value
- or -
RETURN Value // function with return value
Upon execution of the RETURN statement, program control is immediately
returned to the caller. If the function containing the RETURN statement has a
declared return type, the parameter Value must be included and match the
specified type. If the function has no declared return type, the parameter Value
must be omitted.
RIGHT_STRING Returns the specified number of characters from the end of a string.
CHAR[ ] RIGHT_STRING (CHAR STRING[ ], LONG Count)
WIDECHAR[ ] RIGHT_STRING (WIDECHAR STRING[ ], LONG Count)
Parameters:
• STRING: The string from which to extract the characters.
• Count: The number of character to copy from the end of the string.
The return is a string containing a copy of the last Count characters from
STRING.
STRING = 'ABCDEFG'
Substr = RIGHT_STRING(STRING, 3) // Substr = 'EFG'

NetLinx Programming Language Reference Guide 147


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


RSHIFT This keyword causes the bits in the associated value field to be shifted right.
This has the effect of dividing by 2n where n is the number of bit positions to
shift. The symbol >> is equivalent to RSHIFT. For example:
INT2 = INT1 RSHIFT 2
is equivalent to:
INT2 = INT1 >> 2
Both statements shift INT1 right two positions. Either statement could be
replaced with:
INT2 = INT1 / 4
SELECT…ACTIVE This keyword statement provides a programming construct for selective execu-
tion of code blocks based on the evaluation of a series of conditions.
See the Conditionals & Loops section on page 17 for more information.
SEND_COMMAND This keyword sends device-specific commands to a NetLinx device. The syn-
tax is:
SEND_COMMAND DEV, '<command string>'
- or -
SEND_COMMAND DEV[ ], '<command string>'
SEND_LEVEL This keyword sends a value to a specific level on a NetLinx device/port. The
syntax follows any one of the four following examples:
SEND_LEVEL DEV, Level, Value
SEND_LEVEL DEV[ ], Level, Value
SEND_LEVEL DEVLEV, Value
SEND_LEVEL DEVLEV[ ], Value
Parameters:
• DEV: Device containing the specified level.
• Level: Number of the level to receive the new value.
• Value: New level value.
• DEV[ ]: Device array (each device contains the specified level).
• DEVLEV: Device-level to receive the new value.
• DL[ ]: Device-level array (each will receive the new value).
SEND_STRING This keyword sends a string to a NetLinx device/port. The syntax is:
SEND_STRING DEV, '<string>'
- or -
SEND_STRING DEV[ ], '<string>'
When sending to an IP socket, you may receive the following error (via
ONERROR event):
17 Local Port Not Open
This error means you are trying to send a string to a local port on which
IP_CLIENT_OPEN or IP_SERVER_OPEN has not been called.

148 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


SET_DNS_LIST This function programs a domain name and the list of DNS servers that the
specified device will use to lookup domain names. It requires a pre-initialized
DNS_STRUCT structure that will be sent to the specified device.
SLONG SET_DNS_LIST(DEV Device,DNS_STRUCT DnsList )
Parameters:
• Device: Device to which the DNS list will be sent
• DnsList: A DNS_STRUCT that contains the list of DNS server IP addresses
that will be programmed in to the device
Result:
• 0: Operation was successful
• -1: Specified device is invalid or is not online
• -2: Time out occurred
• -3: Function is already actively attempting to set a DNS list (i.e. busy)
• -4: Set DNS failed
• -5: A portion of the DNS structure contains invalid information
DNS_STRUCT DnsList
DnsList.DomainName = 'amx.com'
DnsList.DNS1 = '19.00.100.00'
DnsList.DNS2 = ''
DnsList.DNS3 = ''

Result = SET_DNS_LIST(0:0:0,DnsList) // set master's list


See GET_DNS_LIST, on page 129, for a description of the DNS_STRUCT struc-
ture.
SET_IP_ADDRESS This function programs the TCP/IP configuration of the specified device. The
function requires a pre-initialized IP_ADDRESS_STRUCT structure that will be
sent to the specified device.
SLONG SET_IP_ADDRESS(DEV Device,IP_ADDRESS_STRUCT
IPAddress )
Note: SET_IP_ADDRESS takes effect after the system is rebooted.
Parameters:
• Device: Device to which the IPAddress list will be sent.
• IPAddress: An IP_ADDRESS_STRUCT containing the desired TCP/IP
configuration for the specified device.
Result:
• 0: Operation was successful.
• -1: Specified device is invalid or is not online.
• -2: Time out occurred.
• -3: Function is already actively attempting to set an IP Address (i.e. busy).
The function requires an IP_ADDRESS_STRUCT..
The IP_ADDRESS_STRUCT is predefined as follows:
STRUCTURE IP_ADDRESS_STRUCT
{
CHAR Flags // Configuration flags
CHAR HostName[128] // Host name
CHAR IPAddress[15] // IP address unit
CHAR SubnetMask[15] // subnet mask
CHAR Gateway[15] // IP address of gateway
}

NetLinx Programming Language Reference Guide 149


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


SET_IP_ADDRESS (Cont.) The following definitions exist for the Flags member of the
IP_ADDRESS_STRUCT structure.
CONSTANT CHAR IP_Addr_Flg_DHCP = 1 // Use DHCP
The Flags member is a bit field that may be used for several different
purposes. Each bit is defined below:

Differing configuration parameters may be obtained, depending upon the con-


figuration of the network DHCP server. It is possible that the DHCP server will
provide the host name, IP address, subnet mask, gateway, and even DNS
information. In a minimal configuration, the DHCP server will only supply the IP
address and subnet mask.
IP_ADDRESS_STRUCT IPAddressResult =
GET_IP_ADDRESS(0:0:0,IPAddress)
Note: For NetLinx Central Controllers, the "Host Name" can only consist of
alphanumeric characters.
SET_LENGTH_ARRAY This function sets the effective length of a dimension of an array.
Set_Length_Array (<type> Array[ ], LONG Len)
Parameters:
• <type>: May be any intrinsic or user-defined data type.
• Array: Array of any type
• Len: Value to assign as the length
SET_LENGTH_ARRAY(NumArray,5)
SET_LENGTH_STRING This function sets the length of a CHAR or WIDECHAR string. This function is
retained for compatibility with previous versions of Axcess. It provides the
same functionality as SET_LENGTH_ARRAY.
SET_LENGTH_STRING (CHAR STRING[ ], LONG Len)
SET_LENGTH_STRING (WIDECHAR STRING[ ], LONG Len)
Parameters:
• STRING: The input character string.
• Len: The new string length.
SET_LENGTH_STRING(STRING, 10)
SET_OUTDOOR_ This function establishes the value for the outdoor temperature. This value is
TEMPERATURE broadcast to all devices periodically. At this time, only the PLK-DMS and PLK-
IMS take advantage of the outdoor temperature. A value of 32768 indicates
that no outdoor temperature is available.
SET_OUTDOOR_TEMPERATURE(INTEGER Temp)
Parameters:
• Temp: The outdoor temperature as it shall be displayed. It is up to the
programmer to provide the correct temperature scale whether it is Celsius or
Fahrenheit.
SET_OUTDOOR_TEMPERATURE (32) // show 32 degrees
SET_PULSE_TIME This function sets the PULSE time in 1/10th second units. The default PULSE
time is 5 (0.5 seconds).
SET_PULSE_TIME (TIME)

150 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


SET_SYSTEM_NUMBER Sets the system number of the NetLinx master. The new system number will
take effect after the system has been rebooted.
SLONG SET_SYSTEM_NUMBER (INTEGER newSystemNum)
Parameters:
• newSystemNum: Desired new system number
Result:
• 0: Operation was successful.
• -1: System number is invalid.
• -2: Assignment of system number causes conflict.
This function only affects the master's system number, not the system number
of any attached devices. Therefore, any devices with pre-programmed system
numbers will no longer communicate with this master.
SET_SYSTEM_NUMBER (3) // set new system number
SET_TIMER This keyword resets the system timer. The system timer counts up in 1/10th
second units. The value passed to this function (TIME) may be any unsigned
32-bit variable or constant. This provides a timer with a maximum range of over
13 years.
SET_TIMER (TIME)
Note: The system timer is reset to zero on power up.
SET_VIRTUAL_CHANNEL_ This function lets the programmer override the default number of channels that
COUNT a virtual device port maintains. By default every virtual device port maintains
the state of channels 1-255 inclusive.
SET_VIRTUAL_CHANNEL_COUNT(DEV Device, INTEGER Count)
Parameters:
• Device: The virtual device port to modify.
• Count: The number of channels that the specified virtual device port should
maintain.
SET_VIRTUAL_CHANNEL_COUNT (dvVirtual,1024) // 1024
channels
SET_VIRTUAL_LEVEL_ This function lets the programmer override the default number of levels that a
COUNT virtual device port maintains. By default, every virtual device port maintains the
state of levels 1-8 inclusive.
SET_VIRTUAL_LEVEL_COUNT (DEV Device,INTEGER Count)
Parameters:
• Device: The virtual device port to modify.
• Count: The number of levels that the specified virtual device port should
maintain.
SET_VIRTUAL_LEVEL_COUNT (dvVirtual,10) // make it have 10
levels
SET_VIRTUAL_PORT_ This function lets the programmer override the default number of ports that a
COUNT virtual device maintains. By default every virtual device maintains the state of a
single port (port 1).
SET_VIRTUAL_PORT_COUNT(DEV Device, INTEGER Count)
Parameters:
• Device: The virtual device to modify.
• Count: The number of ports that the specified virtual device should maintain.
SET_VIRTUAL_PORT_COUNT (dvVirtual,2) // 2 ports
SINTEGER This keyword defines an intrinsic data type representing a 16-bit signed
integer.
SLONG This keyword defines an intrinsic data type representing a 32-bit signed
integer.

NetLinx Programming Language Reference Guide 151


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


STACK_VAR This keyword specifies a non-static variable. A non-static variable's value is re-
initialized every time the statement block in which it is declared is executed.
References to STACK_VAR variables are not allowed within waits.
STACK_VARs are temporary variables that cease to exist when the block in
which they are declared is exited.
If neither the LOCAL_VAR nor the STACK_VAR keyword is specified,
STACK_VAR is assumed.
STRING This keyword defines a section in a DATA event handler for processing
SEND_STRING instructions.
STRING_TO_VARIABLE This routine takes the Encode data from buffer and loads the values into the
(VARIABLE DECODE) DECODE variable. The DECODE variable must match the type of the variables in
the encoded string. When the ENCODE variable is a structure, the decode vari-
able members must match in type and order. If the number of members of the
structures doesn't match then the routine will fill all it can or skip any unused
data members.
SINTEGER STRING_TO_VARIABLE (DECODE, CHAR BUFFER[ ], LONG
POSITION)
Parameters:
• DECODE: Any type of variable. This is the variable to be decoded into.
• BUFFER: Must be of char array type. This is where the encoded data is found.
• POSITION: This is where the first byte of the decode data. It is also modified
to point to the next location after the last decoded byte. That means that
successive calls to this function can be made without modifying position. The
position should be set to one on the first call.
Result:
• 2: Decode data too small, more members in structure
• 1: Structure too small, more members in decode string
• 0: Decoded OK
• -1: Decode variable type mismatch
• -2: Decode data too small, decoder ran out of data
STRUCTURE This keyword introduces the declaration of a STRUCTURE data type.
STRUCTURE <name>
{
[<type>] <data1>
[<type>] <data2>
.
.
}

152 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


SWITCH...CASE This keyword statement provides a programming construct for selective execu-
tion of code blocks based on the evaluation of a single condition.
SWITCH (var)
{
CASE 1:
{
IF(Var2=1)
{
BREAK // IF Var2=1 STOP EXECUTION
}
(statements go here if Var2 < > 1)
}
CASE 3:
{
(statements go here)
}
CASE 5:
{
(statements go here)
}
DEFAULT:
{
(statements go here)
}
}
SYSTEM_CALL This keyword is similar to CALL except that the subroutine invoked using the
SYSTEM_CALL keyword resides in a special file called a library file. When this
keyword is used, the compiler generates a call to the subroutine in the library
file and automatically includes the library file for compilation.
SYSTEM_NUMBER This keyword defines an unsigned 16-bit integer system constant that contains
the system number.
TIME This keyword holds the current time as a string in the form "hh:mm:ss". The
time is represented in 24-hour format.
IF (TIME = '23:59:59')
{
}
TIME_TO_HOUR This function returns an integer representing the hour portion of a time string.
SINTEGER TIME_TO_HOUR (CHAR TimeStr[ ])
Parameters:
• TimeStr: Input string containing the time in hh:mm:ss format.
If successful, this function returns an integer (0-23) representing the hour por-
tion of the time string. The specified time is invalid, this function returns -1.
CHAR TimeStr[ ] = '9:30:08'
SINTEGER nHour
nHour = TIME_TO_HOUR (TimeStr) // nHour = 9
TIME_TO_MINUTE This function returns an integer representing the minute portion of a time string.
SINTEGER TIME_TO_MINUTE (CHAR TimeStr[ ])
Parameters:
• TimeStr: Input string containing the time in hh:mm:ss format.
If successful, this function returns an integer (0-59) representing the minute
portion of the time string. If the specified time is invalid, this function returns -1.
CHAR TimeStr[ ] = '9:30:08'
SINTEGER nMinute
nMinute = TIME_TO_MINUTE (TimeStr) // nMinute = 30

NetLinx Programming Language Reference Guide 153


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


TIME_TO_SECOND This function returns an integer representing the second portion of a time
string.
SINTEGER TIME_TO_SECOND (CHAR TimeStr[ ])
Parameters:
• TimeStr: Input string containing the time in hh:mm:ss format.
If successful, this function returns an integer (0-59) representing the second
portion of the time string. If the specified time is invalid, this function returns -1.
CHAR TimeStr[ ] = '9:30:08'
SINTEGER nSecond
nSecond = TIME_TO_SECOND (TimeStr) // nSecond = 8
TIMED_WAIT_UNTIL This keyword delays execution of one or more statements until a particular
condition is met. It is similar to WAIT_UNTIL except that this instruction pro-
vides for a timeout parameter to be specified. The syntax is:
TIMED_WAIT_UNTIL <condition> timeout ['<name>']{(* wait
statements *)}
For more information, refer to the discussion in this document regarding
WAITs.
TIMELINE_ACTIVE This function is used to determine if a timeline has been created. If the timeline
does not exist (i.e. TIMELINE_CREATE has not been called) this function
returns zero.
INTEGER TIMELINE_ACTIVE(LONG Id)
Parameters:
• Id: A user defined value that uniquely identifies this timeline. Each timeline
must be assigned a unique identifier starting with number one.
Returns:
• 0: Not created.
• Non-zero: The timeline has been created.
IF(TIMELINE_ACTIVE(TL1)) // if timeline 1 is running
{
// do something
}
TIMELINE_CREATE Creates an initial timeline and specifies the attributes of the timeline.
INTEGER TIMELINE_CREATE(LONG Id, LONG Times[ ],LONG
Length, LONG Relative, LONG Repeat)
Parameters:
• Id: A user defined value that uniquely identifies this timeline. Each timeline
must be assigned a unique identifier starting with number one.
• Times: An array of times where each time specifies when a
TIMELINE_EVENT will be triggered. The times in the array may be relative to
each other or relative to the start of the timeline depending upon the
Relative parameter. For an absolute timeline, it is not necessary for the
times in the array to be sorted in any particular order (the NetLinx master
does this internally for you). The NetLinx master makes an internal copy of
the values in the array allowing the user to modify the passed in array as
desired without affecting the operation of the timeline.
• Length: The count of times in the Times array.
• Relative: Indicates whether the Times array contains relative times or
absolute times. Relative indicates the each time given is relative to the
last event time (i.e. the time delay in between the triggered events).
Absolute indicates that each time given is absolute with respect to the start
of the timeline.
• Repeat: Indicates whether the timeline should automatically start over again
when Length events have been triggered.

154 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


TIMELINE_EVENT These events are generated when a timeline's internal timer is equal to one of
the specified times in the times array. The TIMELINE_EVENT must be placed
in the DEFINE_EVENT section of the program.
TIMELINE_EVENT[timelineID]
See the TIMELINE_CREATE function (above) for a more detailed description.
TIMELINE_GET This function returns the value of the specified timeline's timer. The timer indi-
cates the number of milliseconds that have passed since the timeline started.
If the timeline is paused the timer is also paused and subsequent calls to
TIMELINE_GET will return the same value.
LONG TIMELINE_GET (LONG Id)
Parameters:
• Id: A user defined value that uniquely identifies this timeline. Each timeline
must be assigned a unique identifier starting with number one.
Result:
This function returns the specified timeline's internal timer. The timer value
represents the number of milliseconds that have passed since the timeline
started.
TIMELINE_SET (TL1,TIMELINE_GET (TL1)+1000)
// jump ahead 1 second
TIMELINE_KILL This function is used to terminate a timeline. Any further references to the
specified timeline ID are invalid.
INTEGER TIMELINE_KILL(LONG Id)
Parameters:
• Id: A user defined value that uniquely identifies this timeline. Each timeline
must be assigned a unique identifier starting with number one.
Result:
• 0: Successful
• 1: Specified timeline ID invalid
TIMELINE_KILL(TL1) // permanently destroy the timeline
TIMELINE_PAUSE This function is used to suspend the execution of a timeline. It may be
restarted from where it left off with the TIMELINE_RESTART function.
INTEGER TIMELINE_PAUSE(LONG Id)
Parameters:
• Id: A user defined value that uniquely identifies this timeline. Each timeline
must be assigned a unique identifier starting with number one.
Result:
• 0: Successful
• 1: Specified timeline ID invalid
TIMELINE_PAUSE(TL1) // momentarily suspend the timeline

NetLinx Programming Language Reference Guide 155


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


TIMELINE_RELOAD This function is used to change the array times of a timeline. The new array of
times takes affect immediately even if the timeline is currently executing. If the
timeline is executing when this function is called the timeline continues to exe-
cute and the next matching time from the new array triggers an event.
INTEGER TIMELINE_RELOAD(LONG Id, LONG Times[],LONG
Length)
Parameters:
• Id: A user defined value that uniquely identifies this timeline. Each timeline
must be assigned a unique identifier starting with number one.
• Times: An array of times where each time specifies when a
TIMELINE_EVENT will be triggered. The times in the array must utilize the
same time base (TIMELINE_RELATIVE or TIMELINE_ABSOLUTE) as
determined by the original call to TIMELINE_CREATE. The NetLinx master
makes an internal copy of the values in the array allowing the user to modify
the passed in array as desired without affecting the operation of the timeline.
• Length: The count of times in the Times array.
Result:
• 0: Successful
• 1: Timeline ID already in use
• 2: Specified array is not an array of LONGs.
• 3: Specified length is greater than the length of the passed array.
• 4: Out of memory
TimeArray[1] = 1000
TimeArray[2] = 1500
TimeArray[3] = 2000
TIMELINE_RELOAD(TL1,TimeArray,3) // Modify the timeline
TIMELINE_RESTART This function is used to continue execution of a timeline that was suspended
with TIMELINE_PAUSE.
INTEGER TIMELINE_RESTART(LONG Id)
Parameters:
• Id: A user defined value that uniquely identifies this timeline. Each timeline
must be assigned a unique identifier starting with number one.
Result:
• 0: Successful
• 1: Specified timeline ID invalid
TIMELINE_RESTART(TL1) // continue the timeline
TIMELINE_SET This function is used to modify the current timer value of a timeline. The time-
line's timer is immediately set to the new value regardless of whether the time-
line is executing or not.
INTEGER TIMELINE_SET (LONG Id, LONG Timer)
Parameters:
• Id: A user defined value that uniquely identifies this timeline. Each timeline
must be assigned a unique identifier starting with number one.
• Timer: The new value for the timeline's internal timer.
Result:
• 0: Successful
• 1: Specified timeline ID invalid
• 2: Specified timer value out of range
TIMELINE_SET (TL1,0) // start it over again

156 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


TO This keyword activates a channel or variable for as long as the corresponding
channel of its PUSH statement is activated. When the channel referenced by
the PUSH statement changes from off to on, the TO command starts activating
the associated channel or variable. When the channel is released, the TO com-
mand stops activating of the channel or variable. Therefore, a TO statement
must be found underneath a PUSH statement only. The syntax is shown below:
TO [DEVICE,CHANNEL]TO [(DEVCHAN[ ])]TO [Variable]
Several conditions apply to the use of the TO command:
• It must be used only below a PUSH statement.
• It cannot be used as part of a set of WAIT statements.
• It cannot be placed in the DEFINE_START section.
The channel or variable will act under the rules set by DEFINE_LATCHING,
DEFINE_MUTUALLY_EXCLUSIVE, and DEFINE_TOGGLING.
TOTAL_OFF This keyword turns a channel or variable off. Unlike OFF, TOTAL_OFF turns off
the status of a channel or variable that is in a mutually exclusive set.
TRUE This keyword is a CHAR constant contains the value 1.
While NetLinx does not support a BOOLEAN data type, an non-zero value is
consider true for conditional expressions.
TYPE_CAST This routine eliminates compiler type cast warnings by casting the passed
intrinsic variable type to the type assigned by the return value.
IntrinsicVariableNewType TYPE_CAST
(IntrinsicVariableType)
It is possible to eliminate the compiler warnings related to type casting. The
TYPE_CAST library function converts any non-array intrinsic type to any other
non-array intrinsic type. The type conversion still happens and follows the stan-
dard Type Conversion Rules, but any warnings related to the type cast are
eliminated. Type casting causes potential loss of data when a variable or con-
stant is assigned to a variable of smaller type.
UNCOMBINE_CHANNELS This keyword reverses the effect of COMBINE_CHANNELS. All combines related
to the specified virtual device-channel are disabled.
SLONG UNCOMBINE_CHANNELS VDC
Parameters:
• VDC: The virtual device-channel passed to COMBINE_CHANNELS.
UNCOMBINE_DEVICES This keyword reverses the effect of COMBINE_DEVICES. All combines related
to the specified virtual device are disabled.
SLONG UNCOMBINE_DEVICES VD
Parameters:
• VD: The virtual device passed to COMBINE_DEVICES.
Result:
• 0: Operation was successful.
• -1: Invalid virtual device.
Result = COMBINE_DEVICES VD, DEVSetResult =
UNCOMBINE_DEVICES VD

NetLinx Programming Language Reference Guide 157


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


UNCOMBINE_LEVELS This keyword reverses the effect of COMBINE_LEVELS. All combines related to
the specified virtual device-level are disabled.
SLONG UNCOMBINE_LEVELS VDL
Parameters:
VDL: The virtual device-channel passed to COMBINE_LEVELS.
Result:
0: Operation was successful
-1: Invalid virtual device-level
Result = COMBINE_LEVELS VDL, DLSetResult =
UNCOMBINE_LEVELS VDL
UPPER_STRING This function changes all alphabetic characters in the specified string to upper
case. The syntax:
CHAR[ ]UPPER_STRING (CHAR STRING[ ]) WIDECHAR[ ]
UPPER_STRING (WIDECHAR STRING[ ])
Parameters:
STRING: The character string to convert to upper case.
Result:
The converted character string.
UCString = UPPER_STRING(STRING)
VARIABLE_TO_STRING This routine takes the variable ENCODE and creates entries in the buffer to rep-
(VARIABLE ENCODE) resent that variable. The variable passed in can be of any type including
arrays, structures, and arrays of structures.
SINTEGER VARIABLE_TO_STRING(ENCODE, CHAR BUFFER[ ], LONG
POSITION)
Parameters:
• ENCODE: Any type of variable. This is the variable to be encoded.
• BUFFER: This is where the encode data is placed.
• POSITION: This is where the first byte of the encoding is placed. Is it also
modified to point to the next location after the last encoded byte. That means
that successive calls to this function can be made without modifying position.
Position should be set to one on the first call.
Result:
0: Encoded OK
-1: Encoded variable unrecognized type
-2: Encoded data would not fit into buffer; the buffer is too small.
Result = VARIABLE_TO_STRING (MyStruct, Buffer, Pos)

158 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


VARIABLE_TO_XML SINTEGER VARIABLE_TO_XML(CONSTANT VARIANTARRAY A,CHAR
B[], LONG C, LONG D)
Where:
• A is the variable (any type) to be encoded:
• B is the CHAR array to hold the resulting XML.
• C is the beginning encoding position. Encoding will start as B[C].
• D is the encoding flag. These can be used together.
Value $01 is "Encode with Types". If the bit is set, types will be included for
every variable being encoded. The default is to not include types. The
constant XML_ENCODE_TYPES can be used to specify this flag.
Value $10 is "Encoded CHAR arrays as using data list". The constant
XML_ENCODE_CHAR_AS_LIST can be used to specify this flag. See the
Encoding and Decoding: Binary and XML section on page 209.
Value $20 is "Array Encoding is Little-Ending". The constant
XML_ENCODE_LE can be used to specify this flag.
The return value is:
• 3 = XML decode data type mismatch
• 2 = XML decode data too small, more members in structure
• 1 = Structure too small, more members in XML decode string
• 0 = Decoded OK
• -1 = Decode variable type mismatch
• - 2 = Decode data too small, decoder ran out of data. Most likely poorly
formed XML.
• -3 = Output character buffer was too small.
Example:
DEFINE_TYPE

STRUCTURE _AlbumStruct
{
LONG lTitleID
CHAR sArtist[100]
CHAR sTitle[100]
}

DEFINE_VARIABLE

_AlbumStruct MyAlbumStruct[3]
LONG lPos
SLONG slReturn
SLONG slFile
SLONG slResult
CHAR sBinaryString[10000]
CHAR sXMLString[50000]

DEFINE_START

MyAlbumStruct[1].lTtleID = 11101000
MyAlbumStruct[1].sArtist = ‘Buffet, Jimmy’
MyAlbumStruct[1].sTitle = ‘Living & Dying in ¾ Time’
MyAlbumStruct[2].lTtleID = 11101012
MyAlbumStruct[2].sArtist = ‘Sinatra, Frank’
MyAlbumStruct[2].sTitle = ‘Come Fly With Me’

MyAlbumStruct[3].lTtleID = 33101000
MyAlbumStruct[3].sArtist = ‘Holiday, Billie’
MyAlbumStruct[3].sTitle = ‘Lady in satin’

NetLinx Programming Language Reference Guide 159


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


VARIABLE_TO_XML DEFINE_EVENT
(Cont.)
BUTTON_EVENT[TP,1] / /Convert And Save
{
PUSH:
{
// Convert To Binary
lPos = 1
slReturn = VARIABLE_TO_STRING(MyAlbumStruct, sBinaryString,
lPos)
SEND_STRING 0,"’POSITION=’,ITOA(lPos),’ – Result =
‘,ITOA(slReturn)"

// Convert To XML
lPos = 1
slReturn = VARIABLE_TO_XML(MyAlbumStruct, sXMLString, lPos,
0)
SEND_STRING 0,"’POSITION=’,ITOA(lPos),’ – Result =
‘,ITOA(slReturn)"

// Save Structure to Disk - Binary


slFile = FILE_OPEN(‘BinaryEncode.xml’, 2)
slReturn = FILE_WRITE(slFile, sBinaryString,
LENGTH_STRING(sBinaryString))
slReturn = FILE_CLOSE(slFile)

// Save Structure To Disk – XML


slFile = FILE_OPEN(‘xmlEncode.xml’, 2)
slReturn = FILE_WRITE(slFile, sXMLString,
LENGTH_STRING(sXMLString))
slReturn = FILE_CLOSE(slFile)
}
RELEASE:
{
}
}
BUTTON_EVENT[TP,2] // Read and Decode
{
PUSH:
{
// Read Binary File
slFile = FILE_OPEN(‘BinaryEncode.xml’,1)
slResult = FILE_READ(slFile, sBinaryString,
MAX_LENGTH_STRING(sBinaryString)
slResult = FILE_CLOSE (slFile)

// Read XML File


slFile = FILE_OPEN(‘XMLEncode.xml’,1)
slResult = FILE_READ(slFile, sXMLString,
MAX_LENGTH_STRING(sXMLString))
slResult = FILE_CLOSE (slFile)

160 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


VARIABLE_TO_XML RELEASE:
(Cont.)
{
}

}
// Convert To Binary
lPos = 1
slReturn = STRING_TO_VARIABLE(MyAlbumStruct, sBinaryString,
slPos)
// OR Convert To XML
slPos = 1
slReturn = XML_TO_VARIABLE (MyAlbumStruct, sXMLString, slPos,
0)
VOLATILE This keyword is used as part of a variable declaration to specify that storage
space for the variable be allocated in volatile memory. Variables stored in vola-
tile memory are not retained when the system is powered-down, as are vari-
ables stored in non-volatile memory. The trade-off is that volatile memory is
generally more plentiful and therefore a good choice for storing large data
arrays.
WAIT This keyword delays execution of one or more statements for a specified
period of time. The syntax is:
WAIT time ['<name>']
{
(* wait statements *)
}
For more information, refer to the Waits section on page 36.
WAIT_UNTIL This keyword is used to delay execution of one or more statements until a
specified condition is met. The syntax is:
WAIT_UNTIL <condition> ['<name>']
{
(* wait statements *)
}
For more information, refer to the Waits section on page 36.
WHILE This keyword executes its statement block as long as its associated condition
evaluates to true. The condition is evaluated before the first pass through the
statements. Therefore, if the conditional expression is never true the condi-
tional statements will never be executed.
WHILE (<conditional expression>)
{
(* conditional statements *)
}
Refer to the discussion on programming loop constructs under the Language
Elements section on page 31 for more information.
WIDECHAR This keyword is an intrinsic data type representing a 16-bit unsigned integer.
This data type is intended for use with Unicode character strings.

NetLinx Programming Language Reference Guide 161


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


XML_TO_VARIABLE SINTEGER XML_TO_VARIABLE(VARIANTARRAY A,CONSTANT CHAR
B[], LONG C, LONG D)
Where:
• A is the variable (any type) to be encoded.
• B is the CHAR array holding the source XML.
• C is the next beginning encoding position. Encoding ended at B[C-1].
• D are the decoding flags. They can be used together.
Value $01 is "Force Types When Decoding". If the type in the XML does not
match the variable typed being decoded to, the variable will not be written
and the variable will be skipped in the XML. The constant
XML_DECODE_TYPES can be used to specify this flag.
Value $10 is "Do Not preserve current value of A". If set, A will be cleared if
not explicitly set. The constant XML_DECODE_NO_PRESERVE can be used to
specify this flag.
The return value is:
• 3 = XML decode data type mismatch
• 2 = XML decode data too small, more members in structure
• 1 = Structure too small, more members in XML decode string
• 0 = Decoded OK
• -1 = Decode variable type mismatch
• - 2 = Decode data too small, decoder ran out of data. Most likely poorly
formed XML.
• -3 = Output character buffer was too small.
Example:
DEFINE_TYPE

STRUCTURE _AlbumStruct
{
LONG lTitleID
CHAR sArtist[100]
CHAR sTitle[100]
}

DEFINE_VARIABLE

_AlbumStruct MyAlbumStruct[3]
LONG lPos
SLONG slReturn
SLONG slFile
SLONG slResult
CHAR sBinaryString[10000]
CHAR sXMLString[50000]
DEFINE_START

MyAlbumStruct[1].lTtleID = 11101000
MyAlbumStruct[1].sArtist = ‘Buffet, Jimmy’
MyAlbumStruct[1].sTitle = ‘Living & Dying in ¾ Time’
MyAlbumStruct[2].lTtleID = 11101012
MyAlbumStruct[2].sArtist = ‘Sinatra, Frank’
MyAlbumStruct[2].sTitle = ‘Come Fly With Me’

MyAlbumStruct[3].lTtleID = 33101000
MyAlbumStruct[3].sArtist = ‘Holiday, Billie’
MyAlbumStruct[3].sTitle = ‘Lady in satin’
DEFINE_EVENT
BUTTON_EVENT[TP,1] / /Convert And Save
{

162 NetLinx Programming Language Reference Guide


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


XML_TO_VARIABLE PUSH:
(cont.) {
// Convert To Binary
lPos = 1
slReturn = VARIABLE_TO_STRING(MyAlbumStruct, sBinaryString,
lPos)
SEND_STRING 0,"’POSITION=’,ITOA(lPos),’ – Result =
‘,ITOA(slReturn)"

// Convert To XML
lPos = 1
slReturn = VARIABLE_TO_XML(MyAlbumStruct, sXMLString, lPos,
0)
SEND_STRING 0,"’POSITION=’,ITOA(lPos),’ – Result =
‘,ITOA(slReturn)"

// Save Structure to Disk - Binary


slFile = FILE_OPEN(‘BinaryEncode.xml’, 2)
slReturn = FILE_WRITE(slFile, sBinaryString,
LENGTH_STRING(sBinaryString))
slReturn = FILE_CLOSE(slFile)

// Save Structure To Disk – XML


slFile = FILE_OPEN(‘xmlEncode.xml’, 2)
slReturn = FILE_WRITE(slFile, sXMLString,
LENGTH_STRING(sXMLString))
slReturn = FILE_CLOSE(slFile)

}
RELEASE:
{
}

}
BUTTON_EVENT[TP,2] // Read and Decode
{
PUSH:
{
// Read Binary File
slFile = FILE_OPEN(‘BinaryEncode.xml’,1)
slResult = FILE_READ(slFile, sBinaryString,
MAX_LENGTH_STRING(sBinaryString)
slResult = FILE_CLOSE (slFile)

// Read XML File


slFile = FILE_OPEN(‘XMLEncode.xml’,1)
slResult = FILE_READ(slFile, sXMLString,
MAX_LENGTH_STRING(sXMLString))
slResult = FILE_CLOSE (slFile)

// Convert To Binary
lPos = 1
slReturn = STRING_TO_VARIABLE(MyAlbumStruct, sBinaryString,
slPos)

// OR Convert To XML
slPos = 1
slReturn = XML_TO_VARIABLE (MyAlbumStruct, sXMLString,
slPos, 0)
}
RELEASE:
{
}

NetLinx Programming Language Reference Guide 163


Reserved Identifiers

Keywords & Run-Time Library Functions (Cont.)


XOR (^^) This keyword evaluates two conditions. One and only one condition can be
true for the entire expression to be true.

Send_Commands
Two new Send_Commands have been added to the master. The new commands enable or disable a feature
that helps synchronize level values. By default, this feature is disabled for compatibility reasons.
The synchronization algorithm works by setting the level value of a level five seconds after receiving a
level value from a level. While it may not be apparent, this makes sure that level values remain in sync
with each other if they ever get out of sync. The only way levels could ever get out of sync is when the
situation of "dueling levels" arises. A typical example of "dueling levels" is when two touch panels with
active sliders are combined with a volume control. If one slider attempts to raise the volume level while
the other is attempting to lower the volume level the level value bounces back and forth somewhere
between the desired levels. If both sliders are released at the exact same time, it is possible that one of
level values displayed on the touch panel's slider is inaccurate. The level synchronization algorithm
corrects the incorrect level five seconds after activity ceases.
The commands are ~LEVSYNCON and ~LEVSYNCOFF are sent to the level that should have the
synchronization algorithm enabled or disabled. The command itself is never sent to the device because
the master intercepts the command and processes it internally. Both commands accept a single parameter
that specifies the level number.
Using the "dueling levels" example above, the following send commands will turn on the
synchronization algorithm for level #1 of Touch Panel 1, level #4 of touch panel #2, and level #2 of the
volume control.
SEND_COMMAND dvTouchPanel1,'~LEVSYNCON 1'
SEND_COMMAND dvTouchPanel2,'~LEVSYNCON 4'
SEND_COMMAND dvVolume,'~LEVSYNCON 2'
Note that for some devices, turning the level synchronization algorithm on can cause undesired results.
The undesired results will vary from device to device so it is difficult to indicate any specific failure
mode. Keep in mind that the algorithm should only be turned on when necessary.
Also note that the LEVSYNCON and LEVSYNCOFF Send_Commands may not be sent to remote devices
(devices that belong to other systems) and only the device's master may issue these commands.
DEFINE_MUTUALLY_EXCLUSIVE and Variables
Symptom: If you have a set of variables that are mutually exclusive and you set one of the variables to a
non-zero value by assignment, e.g. Var1 = 1 or the Studio Debug window, then the other variables in the
set stay "on" i.e. non-zero.
DEFINE_VARIABLE
INTEGER var[4]
INTEGER x
DEFINE_MUTUALLY_EXCLUSIVE
(var[1],var[2],var[3],var[4])
DEFINE_PROGRAM
WAIT 20
{
x++; IF (x > 4) x = 1;
var[x] = x // This will not invoke the mutually exclusive magic
}
In the NetLinx code example above, all elements of var will eventually be non-zero.

164 NetLinx Programming Language Reference Guide


Reserved Identifiers

Axcess does not support making elements of an INTEGER array mutually exclusive.

Cause: This has always worked this way, even in Axcess.


Resolution: Use ON to set variables if they are members of a mutually exclusive set:
DEFINE_VARIABLE
INTEGER var[4]
INTEGER x
DEFINE_MUTUALLY_EXCLUSIVE
(var[1],var[2],var[3],var[4])
DEFINE_PROGRAM
WAIT 20
{
x++; IF (x > 4) x = 1;
ON[var[x]] // This will work as expected - only one element of var will have a
value of 1 at any time
}
This issue does not occur with DEVCHAN's. Using ON or assigning them a non-zero value will work as
expected:
DEFINE_DEVICE
dvRelay = 305:1:0
DEFINE_VARIABLE
INTEGER x
DEFINE_MUTUALLY_EXCLUSIVE
([dvRelay,1]..[dvRelay,4])
([dvRelay,5]..[dvRelay,8])
DEFINE_PROGRAM
WAIT 20
{
x++; IF (x > 4) x = 1;
ON[dvRelay,x] // This works as expected: only 1 relay of relays 1 to 4 will be on
at a time
[dvRelay,x + 4] = x // This works as expected: only 1 relay of relays 5 to 8 will
be on at a time
}

NetLinx Programming Language Reference Guide 165


Reserved Identifiers

166 NetLinx Programming Language Reference Guide


Compiler Messages

Compiler Messages
Compiler Warnings
Sometimes the compiler generates a warning message instead of an error message; these warning
messages always start with w. A warning about a particular statement means that the statement is not
technically an error, but you should be careful doing it. Warnings, unlike errors, do not stop the program
from compiling.
(w) Cannot assign unlike types
This warning occurs when a variable or value of one type is assigned to a variable of a different type.
Here are some examples:
Assigning a string literal, string expression, or array to a non-array variable
Assigning a non-array variable to an entire array
Assigning an integer array to a non-integer array
Assigning a two-dimensional array to a one-dimensional array, or vice versa
Assigning the result of a function that returns an array type to a non-array variable or to a two-
dimensional array variable (for example, X = ITOA(12), where X is a non-array variable or
two-dimensional array variable)
Assigning the result of a function that returns a non-array type to a one- or two-dimensional
array variable (for example, X = ATOI('AMX'), where X is a one- or two-dimensional array
variable)
This message is a warning and not an error, because X = ITOA(12) works correctly when X is a simple
variable, since the result is a single value between Ø and 65,535.
(w) Define_Call is not used
This warning occurs at the end of program compilation for each DEFINE_CALL subroutine that was
declared but never used.
(w) Integer applies to arrays only
This warning appears when the keyword INTEGER is applied to a non-array type of variable.
Doing this is not an error, because non-array variables are already integers, but it is redundant.
(w) Long_While within While
This warning occurs if the compiler finds a LONG_WHILE or MEDIUM_WHILE inside a block of
code following a WHILE keyword.
This warning exists because the WHILE command has a 1/2 second timeout period, and the
LONG_WHILE and MEDIUM_WHILE keywords do not. This could create a hard-to-find logic error.
The solution is to change the WHILE to a LONG_WHILE.
(w) Possibly too many nested levels
This warning appears if there is a large amount of nesting in the program. This can happen with a long
chain of IF...ELSE IF statements.
The solution is to use the SELECT...ACTIVE set of statements.

NetLinx Programming Language Reference Guide 167


Compiler Messages

(w) Variable is not used


This warning occurs at the end of compilation for each variable that was declared but never used.

Compiler Errors
The compiler informs you when it finds an error during the compilation process. Most of the time these
errors occur due to a typographical error or incorrect syntax of a particular command. Unlike warnings,
errors must be corrected before your NetLinx program can be executed. The table below lists all of the
messages that can occur when there is an error during the compilation of your program.
A "<symbol>" was expected
The compiler is expecting a certain symbol at this particular place.
ACTIVE keyword expected
An ACTIVE keyword is not present after a SELECT keyword.
Allowed only in DEFINE_START
A keyword that is only allowed to appear in the DEFINE_START section of the program was
encountered elsewhere.
Attempted CALL to undefined subroutine
A CALL statement refers to a subroutine that has not been defined with a DEFINE_CALL statement.
Comment never ends, EOF encountered
A comment begins but never ends. Place a close comment, * ) at the end of the unfinished comment.
Conditional compile nesting too deep
There are too many nested #IF_DEFINED or #IF_NOT_DEFINED conditional compilation statements.
The limit is 20 nested conditional compilation statements.
Constant type not allowed
A constant value was declared as latching, toggling, or mutually exclusive, as shown below:
DEFINE_CONSTANT
PLAY = 1
DEFINE_LATCHING
PLAY (* Error: PLAY is a constant *)

DEFINE_CALL must have a name


DEFINE_CALL must have a name after it. For example, DEFINE_CALL 'VHS' .
DEFINE_CALL name already used
The name of the DEFINE_CALL has already been used. This name cannot be the same as an already
declared identifier of any type.
Device values must be equal
In a range specification, the devices (or their defined identifiers) must be equal. For example, ([1,1]..[1,5]
) is valid; ([1,1]..[2,5] ) is not.
Duplicate symbol
Duplicate definitions of variables or constants are found. All variables and constants must have unique
identifiers.

168 NetLinx Programming Language Reference Guide


Compiler Messages

Evaluation stack overflow


The expression is too complicated. Try breaking it up into smaller pieces.
Evaluation stack underflow
The expression is too complicated. Try breaking it up into smaller pieces.
Identifier expected
The compiler is expecting an identifier after a #DEFINE statement or after an integer declaration in the
DEFINE_VARIABLE section.
Identifier is not an array type
A non-array variable was treated as an array.
Include file not found
An INCLUDE statement was encountered, but the specified include file could not be found.
Invalid include file name
A string literal enclosed in single quotes must follow the INCLUDE keyword.
Library file not found
The library file containing the specified SYSTEM_CALL could not be found.
Maximum string length exceeded
String literals are limited in length to 132 characters, including spaces.
Must be char array reference
An array type variable was expected in CREATE_BUFFER , CREATE_MULTI_BUFFER , or
CLEAR_BUFFER .
Must be integer reference
The identifier in question must be an integer. This error occurs when the third parameter of
CREATE_LEVEL is an array or array element.
Out of memory
The compiler has run out of memory. Free up memory either by removing any pop-up programs or
drivers, by using extended memory, or by breaking your program into one or more Include files.
Parameter mismatch in CALL
A value or variable passed to a CALL as a parameter is of the wrong type as defined by the
DEFINE_CALL statement.
Program_Name must be on line 1
Move the PROGRAM_NAME= statement to the first line of the program.
Push/Release not allowed within Push/Release
A PUSH or RELEASE statement was found within a block of code headed by a PUSH or RELEASE
statement.
Push/Release not allowed within Wait
These keywords are not allowed in a section of code which will be executed due to a WAIT keyword.

NetLinx Programming Language Reference Guide 169


Compiler Messages

PUSH_CHANNEL not allowed within Wait


These keywords are not allowed in a section of code which will be executed due to a WAIT keyword.
RELEASE_CHANNEL not allowed within Wait
These keywords are not allowed in a section of code which will be executed due to a WAIT keyword.
PUSH_DEVICE not allowed within Wait
These keywords are not allowed in a section of code which will be executed due to a WAIT keyword.
RELEASE_DEVICE not allowed within Wait
These keywords are not allowed in a section of code which will be executed due to a WAIT keyword.
String constant expected
A string is required for the particular operation. This error occurs if a string literal enclosed in single
quotes does not follow the PROGRAM_NAME keyword.
String constant never ends, EOF encountered
A string literal is started but never ends. Add a closing single quotation mark ( ' ) to the end of the string.
String literal expected
A string is required for the particular operation. This error would occur if a string literal enclosed in
single quotes does not follow the #WARN keyword.
Subroutine may not call itself
A subroutine cannot call itself. It can, however, call a different subroutine.
Syntax error
A syntax error is found in an expression. In most cases, this error means that a character is out of place or
something is misspelled.
SYSTEM_CALL name not same as PROGRAM_NAME in <file>
This error occurs when a library file is compiled and the name of the subroutine in the library file does
not match the PROGRAM_NAME string on the first line of the file.
This variable type not allowed
This error occurs when an attempt is made to use an array variable with DEFINE_LATCHING ,
DEFINE_TOGGLING, or DEFINE_MUTUALLY_EXCLUSIVE.
TO statements that occur outside the data flow of PUSH events/statements may not
work
TO is valid:
Under a PUSH statement
Under a BUTTON_EVENT/PUSH handler
Under a BUTTON_EVENT/HOLD handler
In a DEFINE_FUNCTION or DEFINE_CALL that gets invoked in one of the areas above. In
this case, the function or call could be potentially be invoked anywhere in the program. It is
an intractable problem to check for misplacement of <any possible function name> and <any
possible call name>, so TO outside of PUSH'es will not generate an error, just a warning.

170 NetLinx Programming Language Reference Guide


Compiler Messages

This all applies to MIN_TO also.

Too few parameters in CALL


There are not enough parameters being passed to the subroutine.
Too many include files
In NetLinx, the number of Include files allowed is limited only by the amount of memory available on
the PC at compile time.
Too many parameters in CALL
There are too many parameters being passed to the subroutine.
Type mismatch in function CALL
A function was called with a parameter of the wrong type. For instance, attempting to use ITOA with an
array as a parameter will result in an error.
Undefined identifier
An attempt was made to reference an identifier that has not been defined previously in the program.
Unmatched #END_IF
An #END_IF keyword was found, but no #IF_DEFINED or #IF_NOT_DEFINED was previously
compiled.
Unrecognized character in input file
An invalid character was found during the build.
Use SYSTEM_CALL [instance] 'name'
This error occurs if a SYSTEM_CALL statement is written incorrectly as SYSTEM_CALL 'NAME'
[INSTANCE NUMBER].
Variable assignment not allowed here
Variables may not be assigned a value when they are defined in the DEFINE_VARIABLE section.
Wait not found
A statement references a WAIT by a name that does not exist. For example, CANCEL_WAIT 'CASS'
will produce this error if there is no WAIT named CASS.

Run-Time Errors
In many cases, a program is compiled and sent to the Central Controller error-free, but the system does
not act in the way it should. If the program code is correct, you should check for run-time errors. These
errors occur in the Central Controller, usually when it could not perform a particular operation in the
program.
Bad assign 2dim...
These errors occur if an attempt is made to assign a two-dimensional array to a different type (such as a
variable or one-dimensional array), and vice versa.

NetLinx Programming Language Reference Guide 171


Compiler Messages

Bad assign Call...


These errors occur if the Central Controller cannot assign a parameter in a CALL statement to the
parameter in the corresponding DEFINE_CALL statement.
Bad element assign...
These errors occur if an assignment is attempted past the end of an array, or to the Ø location of an array
(for example, ARRAY[Ø]).
Bad Off... Bad On... Bad To...
These errors indicate that the device-channel or variable that is being referenced by an OFF, ON, or TO
keyword is out of range.
Bad re-assign Call...
These errors occur when the Central Controller attempts to re-assign the parameter variables in a
DEFINE_CALL to the parameters in the corresponding CALL statement, and the assignment cannot be
made.
Bad run token
This error occurs when the Central Controller does not understand a piece of data in the program it is
executing.
Bad Set_Length...
These errors occur if the SET_LENGTH_STRING keyword tries to set the length value of an array to a
value greater than the array's storage capacity.
Bad While
This error occurs whenever a WHILE loop terminates due to the half-second timeout imposed on
WHILE loops.

172 NetLinx Programming Language Reference Guide


NetLinx UniCode Functions

NetLinx UniCode Functions


Overview
NetLinx UniCode Functions allow programmers to embed Unicode String literals in their NetLinx
programs, manipulate them using run-time functions and send them to touch panels and other user
interfaces.
NetLinx UniCode Functions
_WC This keyword is a macro for Unicode strings. All Unicode string literals must be
contained in single quotes and in the _WC macro.
WIDECHAR wcData[] = WC('Unicode String')
CH_TO_WC This keyword converts a CHAR array to a WIDECHAR array.
WIDECHAR[] CH_TO_WC(CHAR STRING[])
Parameters:
STRING - a character string to be converted.
Result:
Result is a WIDECHAR array containing the values from the CHAR array.
WIDECHAR wcData[] = CH_TO_WC('ASCII')
WC_COMPARE_STRING This keyword compares two Unicode strings.
If either string contains a '?' character, the matching character in the other
string is not compared.
The '?' is equivalent to a wildcard. For example:
INTEGER WC_COMPARE_STRING(WIDECHAR STR1[], WIDECHAR
STR2[])
Parameters:
• STR1 - the first widechar string to be compared.
• STR2 - the first widechar string to be compared.
Result:
The returned result can only be True (1) or False (0).
• 0 = the strings don't match
• 1 = the strings are the same
See COMPARE_STRING for a code example.
WC_CONCAT_STRING This keyword concatenates two WIDECHAR arrays.
WIDECHAR[] WD_CONCAT_STRING(WIDECHAR STR1[], WIDECHAR
STR2[])
Parameters:
• STR1 - the first widechar string to be concatenated.
• STR2 - the first widechar string to be concatenated.
Result:
A widechar string which concatenates STR1 and STR2
wcMyString = WC_CONCAT_STRING(wcString1,wcString2)

NetLinx Programming Language Reference Guide 173


NetLinx UniCode Functions

NetLinx UniCode Functions (Cont.)


WC_DECODE This function decodes Unicode string from a character string using one of 4
formats.
WIDECHAR[ ] WC_DECODE(CHAR cData[], INTEGER Format, LONG
Start)
Parameters:
• cData: String containing the encoded Unicode string
• Format:
1 Unicode: The data is encoded as a Unicode formatted stream. The
constant WC_FORMAT_UNICODE is defined as a value of 1 for specifying
this format.
2 Unicode BE: The data is encoded as a Unicode BE (Big Endian) formatted
stream. The constant WC_FORMAT_UNICODE_BE is defined as a value of
2 for specifying this format.
3 UTF-8: The data is encoded as a UTF-8 formatted stream. The constant
WC_FORMAT_UTF8 is defined as a value of 3 for specifying this format.
4 TP: The data is encoded for use with the UNI TP command. The constant
WC_FORMAT_TP is defined as a value of 4 for specifying this format.
• Stat: Position in Data from which to start reading
Result:
A WIDECHAR array containing the Unicode data.
wcMyString = WC_DECODE(cData, WC_FORMAT_UNICODE,1)
WC_ENCODE This function encodes a Unicode string to a character string using one of 4 for-
mats.
WIDECHAR[ ] WC_ENCODE(WIDECHAR STRING[], INTEGER Format,
LONG Start)
Parameters:
• STRING: String containing the Unicode string to encode
• Format:
1 Unicode: Encode the data as a Unicode formatted stream. The constant
WC_FORMAT_UNICODE is defined as a value of 1 for specifying this
format.
2 Unicode BE: Encode the data as a Unicode BE (Big Endian) formatted
stream. The constant WC_FORMAT_UNICODE_BE is defined as a value of
2 for specifying this format.
3 UTF-8: Encode the data as a UTF-8 formatted stream. The constant
WC_FORMAT_UTF8 is defined as a value of 3 for specifying this format.
4 TP: Encode the data for use with the UNI TP command. The constant
WC_FORMAT_TP is defined as a value of 4 for specifying this format.
• Stat: Position in STRING from which to start reading
Result:
Result is a CHAR array containing the encoded Unicode data.
cData = WC_ENCODE(wcMyString, WC_FORMAT_UNICODE,1)

174 NetLinx Programming Language Reference Guide


NetLinx UniCode Functions

NetLinx UniCode Functions (Cont.)


WC_FILE_CLOSE This function closes a file opened with WC_FILE_OPEN. This function should
be called when all reading or writing to the file is completed.
SLONG WC_FILE_CLOSE (LONG hFile)
Parameters:
• hFile: Handle to the file returned by WC_FILE_OPEN.
Result:
• 0: Operation was successful
• -1: Invalid file handle
• -5: Disk I/O error
• -7: File already closed
There is a limit to the number of file handles available from the system. If files
are not closed, it may not be possible to open a file.
Result = WC_FILE_CLOSE (hFile)

NetLinx Programming Language Reference Guide 175


NetLinx UniCode Functions

NetLinx UniCode Functions (Cont.)


WC_FILE_OPEN This function opens a file for reading or writing.
SLONG FILE_OPEN (CHAR FilePath[ ], LONG IOFlag, LONG
Format)
Parameters:
• FilePath: String containing the path to the file to be opened
• IOFlag:
1 Read: The file is opened with READ ONLY status. The constant
FILE_READ_ONLY is defined as a value of 1 for specifying this flag.
2 R/W New: The file is opened with READ WRITE status. If the file currently
exists, its contents are erased. The constant FILE_RW_NEW is defined as a
value of 2 for specifying this flag.
3 R/W Append: The file is opened with READ WRITE status. The current
contents of the file are preserved and the file pointer is set to point to the end
of the file. The constant FILE_RW_APPEND is defined as a value of 3 for
specifying this flag.
• Format:
1 Unicode The file is opened as a Unicode formatted file. If the file is opened
as Read or R/W Append and the file is a Unicode formatted file, this
parameter will be set to this value by the function. The constant
WC_FORMAT_UNICODE is defined as a value of 1 for specifying this
format.
2 Unicode BE The file is opened as a Unicode BE (big Endian) formatted
file. If the file is opened as Read or R/W Append and the file is a Unicode BE
formatted file, this parameter will be set to this value by the function. The
constant WC_FORMAT_UNICODE_BE is defined as a value of 2 for
specifying this format.
3 UTF-8 The file is opened as a UTF-8 formatted file. If the file is opened as
Read or R/W Append and the file is a UTF-8 formatted file, this parameter
will be set to this value by the function. The constant WC_FORMAT_UTF8 is
defined as a value of 3 for specifying this format.
If the open operation is successful, this function returns a non-zero integer
value representing the handle to the file. This handle must be used in
subsequent read, write, and close operations.
>0: Handle to file (open was successful)
-2: Invalid file path or name
-3: Invalid value supplied for IOFlag
-5: Disk I/O error
-14: Maximum number of files are already open
-15: Invalid file format
If the file is opened successfully, it must be closed after all reading or writing is
completed, by calling WC_FILE_CLOSE. If files are not closed, subsequent
file open operations may fail due to the limited number of file handles avail-
able.
// Open MYFILE.TXT for readingINTEGER nFormatSLONG
hFilehFile = WC_FILE_OPEN('MYFILE.TXT',
FILE_READ_ONLY,nFormat)
// nFormat will be set to detected file type

176 NetLinx Programming Language Reference Guide


NetLinx UniCode Functions

NetLinx UniCode Functions (Cont.)


WC_FILE_READ This function reads a block of widechar data from the specified file.
SLONG WC_FILE_READ (LONG hFile, WIDECHAR Buffer[ ], LONG
BufLen)
Parameters:
• hFile: Handle to the file returned by WC_FILE_OPEN
• Buffer: Buffer to hold the data to be read
• BufLen: Maximum number of characters to read
Result:
• >0: The number of bytes actually read
• -1: Invalid file handle
• -5: Disk I/O error
• -6: Invalid parameter
• -9: End-of-file reached
This function reads (from the current location of the file pointer) the number of
characters specified by BufLen (or fewer bytes if the end of file is reached).
The characters are read from the file identified by hFile and are stored in
Buffer. The file pointer will automatically be advanced the correct number of
bytes so the next read operation continues where the last operation left off.
WIDECHAR wcBuffer[1024]nBytes = WC_FILE_READ (hFile,
wcBuffer, 1024)
WC_FILE_READ_LINE This function reads a line of widechar data from the specified file.
SLONG WC_FILE_READ_LINE (LONG hFile, WIDECHAR Buffer[ ],
LONG BufLen)
Parameters:
• hFile: Handle to the file returned by WC_FILE_OPEN
• Buffer: Buffer to hold the data to be read
• BufLen: Maximum number of characters to read
Result:
• =0: The number of bytes actually read
• -1: Invalid file handle
• -5: Disk I/O error
• -6: Invalid parameter (buffer length must be greater than zero)
• -9: End-of-file reached
This function reads from the current location of the file pointer up to the next
carriage return or to the end-of-file (EOF), whichever comes first. A complete
line will not be read if the buffer length is exceeded before a carriage return (or
EOF) is encountered. The characters are read from the file identified by hFile
and are stored in Buffer. The <CR> or <CR><LF> pair will not be stored in
Buffer. If a complete line is read, the file pointer is advanced to the next char-
acter in the file after the <CR> or <CR><LF> pair or to the EOF if the last line
was read.
WIDECHAR wcBuffer[80]nBytes = WC_FILE_READ_LINE (hFile,
wcBuffer,80)

NetLinx Programming Language Reference Guide 177


NetLinx UniCode Functions

NetLinx UniCode Functions (Cont.)


WC_FILE_WRITE This function writes a block of widechar data to the specified file.
SLONG WC_FILE_WRITE (LONG hFile, WIDECHAR Buffer[ ], LONG
BufLen)
Parameters:
• hFile: Handle to the file returned by WC_FILE_OPEN.
• Buffer: Buffer containing the data to write.
• BufLen: Number of characters to write.
Result:
• >0: The number of bytes actually written
• -1: Invalid file handle
• -5: Disk I/O error
• -6: Invalid parameter (buffer length must be greater than zero)
• -11: Disk full. The data will overwrite or append to the current contents of the
file depending on the current position of the file pointer.
WIDECHAR wcBuffer[1024]Result = WC_FILE_WRITE (hFile,
wcBuffer,1024)
WC_FILE_WRITE_LINE This function writes a line of widechar data to the specified file.
SLONG FILE_WRITE_LINE (LONG hFile, WIDECHAR Line[ ], LONG
LineLen)
Parameters:
• hFile: Handle to the file returned by WC_FILE_OPEN.
• Line: Buffer containing the line of data to write.
• LineLen: Number of characters to write.
Result:
• >0: The number of bytes actually written
• -1: Invalid file handle
• -5: Disk I/O error
• -6: Invalid parameter (LineLen must be greater than zero)
• -11: Disk full. A <CR><LF> character pair is automatically appended to the
end of the line.
WIDECHAR wcLine[80]Result = FILE_WRITE_LINE (hFile,
wcLine, 80)
WC_FIND_STRING This function searches through a string for a specified sequence of characters.
INTEGER WC_FIND_STRING (WIDECHAR STRING[ ], WIDECHAR
Seq[ ], INTEGER Start)
Parameters:
• STRING: The string of character to search.
• Seq: The sequence of characters to search for.
• Start: The starting character position for the search.
Result:
A 16-bit unsigned integer representing the character location of Seq in
STRING. If the character string is found at the beginning of the string, this
function returns 1; any error condition returns 0.
POS = WC_FIND_STRING(STRING, _WC('ABC'), 1)

178 NetLinx Programming Language Reference Guide


NetLinx UniCode Functions

NetLinx UniCode Functions (Cont.)


WC_GET_BUFFER_CHAR This keyword removes a character from a buffer.
WIDECHAR WC_GET_BUFFER_CHAR (WIDECHAR A[])
The result is a WIDECHAR value.
WC_GET_BUFFER_CHAR has a two-part operation:
1. Retrieve the first character in the buffer.
2. Remove the retrieved character from the buffer and shift the remaining char-
acters by one to fill the gap.
wchChar = GET_BUFFER_STRING(wcString)
// wchChar contains first character of wcString
// wcString is now one character smaller in length and
// starts with what used to be the 2nd character
WC_GET_BUFFER_STRING This function removes characters from a buffer.
WIDECHAR WC_GET_BUFFER_STRING (WIDECHAR A[], Length)
Length is the number of characters to remove.
Result is a WIDECHAR value.
WC_GET_BUFFER_STRING has a two-part operation:
1. Retrieve <length> number of characters from the buffer.
2. Remove the retrieved character from the buffer and shift the remaining char-
acters up to fill the gap.
wcSubStr = GET_BUFFER_STRING(wcString,3)
// wcSubStr contains first 3 characters of wcString
// wcString is now three characters smaller in length and
// starts with what used to be the 4th character
WC_LEFT_STRING This function returns the specified number of characters from the beginning of
a string.
WIDECHAR[ ] WC_LEFT_STRING (WIDECHAR STRING[ ], LONG
Count)
Parameters:
• STRING: The string from which to extract the characters.
• Count: The number of character to copy from the beginning of the string.
Result:
A string containing a copy of the first Count characters from STRING.
wcSTRING = _WC('ABCDEFG')wcSubstr =
WC_LEFT_STRING(wcSTRING, 3) // wcSubstr = 'ABC'
WC_LENGTH_STRING This function returns the length of a WIDECHAR string. This function is pro-
vides the same information as LENGTH_ARRAY.
LONG WC_LENGTH_STRING (WIDECHAR STRING[ ])
Parameters:
• STRING: The input character string.
Result:
The result is the length of STRING. The string length can be set implicitly
through a literal or variable string assignment or explicitly by calling
SET_LENGTH_STRING.
For example:
IF (WC_LENGTH_STRING(wcSTRING) > 0){// process string}

NetLinx Programming Language Reference Guide 179


NetLinx UniCode Functions

NetLinx UniCode Functions (Cont.)


WC_LOWER_STRING This function changes all alphabetic characters in the specified string to lower
case using the case mapping defined by Unicode.org.
WIDECHAR[ ] WC_LOWER_STRING (WIDECHAR STRING[ ])
Parameters:
• STRING: The widechar string to convert to lower case.
Result:
The result is the converted widechar string.
wcLCString = WC_LOWER_STRING(wcSTRING)
WC_MAX_LENGTH_STRING This function returns the dimensioned length of a WIDECHAR string. This
function provides the same information as MAX_LENGTH_ARRAY.
LONG WC_MAX_LENGTH_STRING (WIDECHAR STRING[ ])
Parameters:
• STRING: The input widechar string.
Result:
The result is the dimensioned length of STRING.
MaxLen = WC_MAX_LENGTH_STRING(wcSTRING)Len =
WC_LENGTH_STRING(wcSTRING)IF (MaxLen > Len){// append
character to wcSTRING}
WC_MID_STRING This function returns the specified number of characters, starting at the speci-
fied location in the source string.
WIDECHAR[ ] WC_MID_STRING (WIDECHAR STRING[], LONG
Start, LONG Count)
Parameters:
• STRING: The input character string.
• Start: Starting location in the string.
• Count: Number of characters to extract.
Result:
The result is a widechar string containing the specified characters.
wcSTRING = _WC('ABCDEFGHIJK')wcSubstr =
WC_MID_STRING(wcSTRING, 5, 4)// wcSubstr = 'EFGH'
WC_REMOVE_STRING This function removes characters from the specified string. All characters up to
and including the first occurrence of the specified sequence are removed.
WIDECHAR[ ] WC_REMOVE_STRING (WIDECHAR STRING[],
WIDECHAR Seq[], LONG Start)
Parameters:
• STRING: String from which to find and remove characters.
• Seq: Sequence of characters to find.
• Start: Starting position in the string to begin search.
Result:
The result is a string containing the removed characters. If the character
sequence was not found, an empty string is returned.
wcSTRING = _WC('ABCDEF')wcSubstr =
WC_REMOVE_STRING(wcSTRING, _WC('BC'), 1)// wcSubstr =
'ABC'// wcSTRING = 'DEF'

180 NetLinx Programming Language Reference Guide


NetLinx UniCode Functions

NetLinx UniCode Functions (Cont.)


WC_RIGHT_STRING Returns the specified number of characters from the end of a string.
WIDECHAR[ ] WC_RIGHT_STRING (WIDECHAR STRING[ ], LONG
Count)
Parameters:
• STRING: The string from which to extract the characters.
• Count: The number of character to copy from the end of the string.
Result:
The return is a string containing a copy of the last Count characters from
STRING.
wcSTRING = _WC('ABCDEFG')wcSubstr =
WC_RIGHT_STRING(wcSTRING, 3) // wcSubstr = 'EFG'
WC_SET_LENGTH_STRING This function sets the length of a WIDECHAR string. This function provides the
same functionality as SET_LENGTH_ARRAY.
LONG WC_SET_LENGTH_STRING (WIDECHAR STRING[ ], LONG Len)
Parameters:
• STRING: The input widechar string.
• Len: The new string length.
WC_SET_LENGTH_STRING(wcSTRING, 10)
WC_TO_CH This keyword converts a WIDECHAR array to a CHAR array.
CHAR[ ] WC_TO_CH (WIDECHAR wcSTRING[ ])
Parameters:
• STRING: The widechar string to convert to a character string.
Result:
A character string version of the widechar string. All characters that require
more than 8 bits of storage are converted to the '?' character.
cData= WC_TO_CH (_WC('Unicode'))
WC_TP_ENCODE This function encodes a WIDECHAR array into a CHAR array formatted for the
UNI and BAU user interface commands.
CHAR[ ] WC_TP_ENCODE (WIDECHAR STRING[ ])
Parameters:
• STRING: The widechar string to send to a user interface.
Result:
The result is an encoded character string.
cString = WC_TP_ENCODE(wcSTRING)SEND_COMMAND
dvTY,"'^UNI-1,0,',cString"
WC_UPPER_STRING This function changes all alphabetic characters in the specified string to upper
case using the case mapping specified by Unicode.org.
WIDECHAR[ ] WC_UPPER_STRING (WIDECHAR wcSTRING[ ])
Parameters:
• STRING: The widechar string to convert to upper case.
Result:
The result is the converted widechar string.
wcUCString = WC_UPPER_STRING(wcSTRING)

NetLinx Programming Language Reference Guide 181


NetLinx UniCode Functions

Working With UniCode in NetLinx Studio v2.4


Starting with NetLinx Studio 2.4, NetLinx now supports 16-bit Unicode characters. You can type
Unicode character literals strings into you program, assigned them to variables, manipulate them using
string operations, read and write Unicode characters to the file system and send Unicode strings to user
interfaces for display.
Configuring NetLinx Studio
Before you begin to work with Unicode, you must enable the UTF-8 Unicode option and the Unicode
Compile option in NetLinx Studio. The UTF-8 Unicode option will tell Studio to store your file as UTF-
8, which will support Unicode characters. The Unicode Compile option will tell Studio to process the
_WC pre-processor statements to properly handle Unicode embedded in your source files at compile
time.
To enable UTF-8, in NetLinx Studio:
1. Choose Settings-> Preferences from the menu bar.
2. Select the Editor tab of the Preferences dialog (FIG. 1).

FIG. 1 Editor tab of the Preferences dialog

3. Under Display, check the Enable UTF-8 format checkbox.


4. Close the Preferences dialog.
To enable Unicode Compiling in NetLinx Studio:
1. Choose Settings > Preferences from the menu bar

182 NetLinx Programming Language Reference Guide


NetLinx UniCode Functions

2. Select the NetLinx Compiler tab (FIG. 2).

FIG. 2 NetLinx Compiler tab of the Preferences dialog

3. Under Options, check the Enable _WC Preprocessor checkbox.


4. Close the Preferences dialog.
Including the Unicode Library
The Unicode Library is implemented in a NetLinx Include file, UnicodeLib.axi, that must be included in
your program in order to access the Unicode functions. The Unicode Library is located in an Include file
located in the C:\Program Files\Common Files\AMXShare\AXIs directory. Because this location is the
default Include search path, you do not need to specify the directory in the include statement.
To include the Unicode Library to your program add these lines to your program:
(***********************************************************)
(* INCLUDE FILES GO BELOW *)
(***********************************************************)
#INCLUDE 'UnicodeLib.axi'

Defining a Unicode String Literal


To enter Unicode characters into your program, enclose the characters in single quotes, like you would
any other string, and wrap the string literal in the Unicode macro _WC. Here is an example:
_WC('Your string goes here')

NetLinx Programming Language Reference Guide 183


NetLinx UniCode Functions

All Unicode string literals must be wrapped in the _WC macro. Failing to wrap a Unicode string in the
_WC macro will result in a compiler error.
Storing a Unicode String
Unicode strings are stored in WIDECHAR arrays, similar to the way ASCII strings are stored in CHAR
arrays. To define a WIDECHAR constant or variable and initialize it using a Unicode string literal, use
the following syntax:
WIDECHAR wcMyString[] = _WC('My String')

The "wc" prefix is Hungarian notation for widechar. This is simply a programming
convention and is completely optional. Hungarian notation helps you better identify
your variables while you are programming and is a general recommended standard.
For more information, see Wikipedia's Hungarian Notation page.

Working with WIDECHAR arrays and Unicode Strings


Working with WIDECHAR arrays and Unicode strings is very similar to working with CHAR arrays and
ASCII strings. Most operation that can be performed on a CHAR array can be performed on a
WIDECHAR array. For instance, to assign a string to a variable use this syntax:
wcMyString = _WC('My String')

The string functions defined for CHAR arrays have been defined for WIDECHAR array for use in
Unicode programming. These functions allow you to operate on strings similar to the way you would
with CHAR array. For instance, to remove the first 3 characters from a WIDECHAR array and return
those characters as a WIDECHAR array, use WC_GET_BUFFER_STRING:
wcRemoved = WC_GET_BUFFER_STRING(wcMyString,3)

You will find that most other function work exactly as their CHAR counterpart do except they work on
and return WIDECHAR arrays. The list of Unicode compatible functions is:
WC_COMPARE_STRING
WC_GET_BUFFER_CHAR
WC_GET_BUFFER_STRING
WC_LEFT_STRING
WC_FIND_STRING
WC_LENGTH_STRING
WC_LOWER_STRING
WC_MAX_LENGTH_STRING
WC_MID_STRING
WC_REMOVE_STRING
WC_RIGHT_STRING
WC_SET_LENGTH_STRING
WC_UPPER_STRING

184 NetLinx Programming Language Reference Guide


NetLinx UniCode Functions

Character Case Mappings


Converting between upper and lower case is accomplished by using the Unicode.org character database
to determine the mapping between upper case and lower case characters. Not all Unicode characters have
an upper or lower case equivalent; these characters will not be affected by WC_UPPER_STRING and
WC_LOWER_STRING. Only the characters defined by Unicode.org as having an upper or lower case
mapping are affected by these functions. For more information on Unicode character conversion, see the
Unicode.org character conversion FAQ.
Concatenating String
Unicode strings and WIDECHAR array cannot be concatenated using the same syntax that ASCII
strings use. In NetLinx, string expressions are enclosed in double quotes and can only contain 8-bit
strings. To concatenate Unicode strings and WIDECHAR arrays, you must use the
WC_CONCAT_STRING function:
wcMyString = WC_CONCAT_STRING(_WC('First name'),_WC(' SurName'))

If you attempt to concatenate Unicode strings or WIDECHAR arrays using NetLinx string expressions,
expect data loss.
Converting between WIDECHAR and CHAR
On occasion, you may need to convert a CHAR array to a WIDECHAR array or a WIDECHAR array to
a CHAR array. The CH_TO_WC and WC_TO_CH functions can be used to accomplish these
conversions. For example:
wcMyString = CH_TO_WC('Any ASCII string')
wcMyString = CH_TO_WC(cMyString)

cMyString = WC_TO_CH(_WC('Any Unicode string'))


cMyString = WC_TO_CH (wcMyString)

When converting from WIDECHAR to CHAR, Unicode characters are converted to '?'. Any ASCII or
extended ASCII characters, i.e. 8-bit characters, contained in the WIDECHAR array will appear in the
CHAR array. Converting from CHAR to WIDECHAR never results in loss of data.
Using FORMAT
The NetLinx Unicode library does not include a Unicode compatible FORMAT function. In NetLinx, the
format function is used to convert numbers to text. To use FORMAT with Unicode string, use
FORMAT to convert the number to a CHAR array and then use CH_TO_WC and
WC_CONCAT_STRING to combine the result with an existing WIDECHAR array. The following two
syntaxes are functionality equivalent:
fTemperature = 98.652
cMyString = FORMAT('The current temperature is %3.2f',fTemperature)

fTemperature = 98.652
cTempString = FORMAT('%3.2f',fTemperature)
wcMyString = _WC('The current temperature is ')
wcMyString = WC_CONCAT_STRING(wcMyString,CH_TO_WC(cTempString))

NetLinx Programming Language Reference Guide 185


NetLinx UniCode Functions

Reading and Writing to Files


The NetLinx Unicode library supports reading and writing of WIDECHAR arrays. The WC_FILE
routines operate the same as the FILE routines with the exception of FILE_OPEN. WC_FILE_OPEN
takes an additional parameter; the file format.
The WC_FILE_OPEN returns a special file handle so it is important to only use the file handle returned
by WC_FILE_OPEN with other WC_FILE functions and the file handle used with WC_FILE functions
must have been obtained by calling WC_FILE_OPEN.
The NetLinx Unicode library supports three different file formats for compatibility with files created on
a computer. Windows Notepad supports the same three file formats so files created in Notepad can be
read using the WC_FILE routines and files created using the WC_FILE routines can be read with
Notepad.
When reading or appending to file, the file format is automatically determined when the file is opened.
You can pass in a variable to WC_FILE_OPEN and the function will set the variable to the file format
that was detected. When writing files, the file format parameter will determine how data is written to the
file. The following constants can be used for specifying or checking the file format:
WC_FORMAT_UNICODE, WC_FORMAT_UNICODE_BE,
WC_FORMAT_UTF8. The Unicode file format, specified by the constant WC_FORMAT_UNICODE,
is the fastest to encode and decode. You should use this format unless you have a particular application
that requires either UTF-8 or Unicode BE encoding.
The WC_FILE_READ/WRITE functions take the number of characters that will be read or written to
the file. However, the functions return the number of bytes read or written to the file, not the number of
characters. For Unicode and Unicode BE encoding, there are 2 bytes for every character. For UTF-8
encoding, the number of bytes for every character varies depending on the character.
Unicode filenames are not supported. The parameter for the file name is a CHAR array. Always use a
non-Unicode name for the file.
The following file functions support WIDECHAR arrays:
WC_FILE_OPEN
WC_FILE_CLOSE
WC_FILE_READ
WC_FILE_READ_LINE
WC_FILE_WRITE
WC_FILE_WRITE_LINE
Send strings to a User Interface
Sending a WIDECHAR array to a user interface is accomplished using WC_TP_ENCODE.
WC_TP_ENCODE takes a WIDECHAR array and returns a CHAR array formatted for a user interface
UNI or BAU command.
cMyString = WC_TP_ENCODE(wcMyString)
SEND_COMMAND dvTP,"'^UNI-1,0,',cMyString "

Right-to-Left Unicode Strings


Right-to-Left Unicode languages are stored in memory the same way left-to-right language are. The first
memory position of an array contains the first logical character. You can access the right-most character
of a Right-to-Left Unicode string using this notation:
wchChar = wcString[1]

186 NetLinx Programming Language Reference Guide


NetLinx UniCode Functions

Right-to-left languages are not stored differently than left-to-right languages, they are simply rendered
differently than right to left languages.
However, note that the functions WC_LEFT_STRING and WC_RIGHT_STRING remove a number of
characters from the start and end of a string respectively. Using WC_LEFT_STRING on a right-to-left
language will return the number of right-most, i.e. first, characters you requested, not the left-most, i.e.
end, characters.
WC_LEFT_STRING returns the number of characters request from the front of the string and
WC_RIGHT_STRING return the number of characters requested from the end of the string, regardless
of the language's orientation.
Compiler Errors
The most common type of compiler errors you will encounter while programming for Unicode are
caused by not wrapping Unicode string literals in _WC, passing a WIDECHAR to a function that take a
CHAR array or passing a CHAR array to a function that takes a WIDECHAR array.
If you forget to wrap a Unicode string in _WC, expect to see the following compiler error:
On the line where the string is defined:
C10571: Converting type [string] to [WIDECHAR]

On the line where the constant or variable is used:


C10585: Dimension mismatch: [1] vs. [0] and C10533: Illegal assignment statement

If you try to pass a CHAR array to a function that expects a WIDECHAR array, expect to see the
following compiler error:
On the line where the function call is made
C10585: Dimension mismatch: [1] vs. [0] and Type mismatch in call for parameter
[WCDATA]

If you try to pass a WIDECHAR array to a function that expects a CHAR array, expect to see the
following compiler error:
On the line where the function call is made
C10585: Dimension mismatch: [1] vs. [0] and Type mismatch in call for parameter [A]

Parameter names might not match those listed above.

NetLinx Programming Language Reference Guide 187


NetLinx UniCode Functions

188 NetLinx Programming Language Reference Guide


IP Communication

IP Communication
Clients and servers communicate via Internet Protocol (IP) using either a connection-oriented or
connection-less protocol.
Connection-oriented input/output (I/O) channels require a connection or virtual circuit to be established
between the client and server before data can be transmitted or received. Transmission Control Protocol
(TCP) is the transport protocol typically used for connection-oriented I/O. With TCP, delivery of the data
is guaranteed.
With connection-less I/O, a connection is not established between the client and server before data is
exchanged. Instead, the identity of the client and server is established each time data is sent or received.
This type of communication is usually recommended for applications that transfer only small amounts of
data. User Datagram Protocol (UDP) is the transport protocol used for connection-less I/O. With UDP,
delivery of the data is not guaranteed.
Both the client and server must be able to identify incoming and outgoing data for a particular
conversation. To achieve this, each application assigns a unique number to the conversation. This number
is the local port number. A local port is not a physical port but rather a virtual port that identifies the
source or destination for data exchanged during the conversation. Local ports are specific to either the
client or the server; they need not match across applications.
The application assigns the number for the local port - as opposed to letting the system assign it (for
instance, as the return value for IP_CLIENT_OPEN or IP_SERVER_OPEN) - to satisfy the static nature
of DEFINE_EVENT handlers. All event handlers must specify a device, port, and system to identify the
events' source. This device information must be constant; that is, it cannot change at run-time. A constant
IP device specification can be defined using a local port number. For example:
Device Number = 0 The master
Port = LocalPort The local port number
System = 0 This system (where the application is running)

A range of numbers is reserved for local port numbers to make sure that this IP device-naming
convention does not interfere with future naming schemes. The program can only assign local port
numbers at or above the value of the keyword, FIRST_LOCAL_PORT. All port numbers below
FIRST_LOCAL_PORT are reserved for future use. For example:
DEFINE_CONSTANT
PORT_REMOTE_MASTER1 = FIRST_LOCAL_PORT
PORT_REMOTE_MASTER2 = FIRST_LOCAL_PORT + 1
PORT_REMOTE_MASTER3 = FIRST_LOCAL_PORT + 2

Client Programming
Initiating a conversation
To initiate a conversation with a server, the client must use the IP_CLIENT_OPEN command and supply
either the IP address or domain name of the server and a port number for the requested service. The
client must also specify a local port number to use for sending and receiving data. This number
represents a virtual port on the client machine; it is not the actual port number used to create the client-
end socket. A local port number may not be used in another call to IP_CLIENT_OPEN until
IP_CLIENT_CLOSE is called for that port number. The syntax is shown below:
IP_Client_Open(LocalPort, ServerAddress, ServerPort, Protocol)
Parameters:

NetLinx Programming Language Reference Guide 189


IP Communication

LocalPort: A user-defined, non-zero integer value representing the virtual port on the client
machine that will be used for this conversation. This port number must be passed to
IP_CLIENT_CLOSE to close the conversation.
ServerAddress: A string containing either the IP address (in dotted-quad-notation) or the
domain name of the server to connect to.
ServerPort: The port number on the server that identifies the program or service the client is
requesting.
Protocol: The transport protocol to use (1 = TCP, 2 = UDP). If this parameter is not specified,
TCP (1) is assumed. The constants IP_TCP and IP_UDP can be used to specify this
parameter.
Terminating a conversation
To terminate a conversation, you must use the IP_CLIENT_CLOSE command and pass the number of
the local port used for the conversation. The syntax:
IP_Client_Close(LocalPort)

Parameters:
LocalPort: A user-defined, non-zero integer value representing the virtual port on the client
machine that will be used for this conversation.
Sending data
To send data to the server, use the SEND_STRING command.
SEND_STRING 0:LocalPort:0, '<string>'

The device specification (0:LocalPort:0) is interpreted as follows:


Device Number: 0: The master
Port: LocalPort: The local port number
System: 0: This system (the client)
Receiving data
To receive data from the server, use a DATA event handler or a buffer created with CREATE_BUFFER or
CREATE_MULTI_BUFFER. If an event handler is used, the data is located in the Text field of the DATA
object. The syntax is shown below:
Data_Event[Device]
{
STRING:
{
// process incoming string (Data.Text)
}
}

Parameters:
Device is (or contains as part of an array) the device representing the conversation
(0:LocalPort:0)
When using IP sockets in NetLinx, it is not uncommon to create a buffer using a CREATE_BUFFER
keyword and processing the buffer in the DATA_EVENT...OFFLINE event.
Netlinx has an important behavior than can affect the performance of IP socket code. This is not a bug
but a feature. If you are aware of it, you can write your code to take maximum advantage of the speed
NetLinx offers.

190 NetLinx Programming Language Reference Guide


IP Communication

When processing string data from a device, whether it is a regular device or an IP socket, the master will
attempt to copy this data to a buffer, if one has been created using the CREATE_BUFFER keyword, and
then try to run a DATA_EVENT…STRING handler for this device. If a DATA_EVENT…STRING handler
does not exists, Netlinx will run mainline to allow for any buffer processing that might occur in mainline.
At the end of a conversation with an IP device, there will usually be an incoming string event followed
by an offline event. The NetLinx master will copy the string to a buffer, if it exists, check for a string
event handler, run mainline if one does not exist, then process the offline event.
If you are processing that data in an offline event for an IP device, you will see a time delay between the
IP device or server closing the connection and the processing of the offline event. This delay will vary
with the size and complexity of mainline.
To eliminate this delay, simply include and empty string event handler in the DATA_EVENT section. This
will keep NetLinx from running mainline between the last incoming string and the offline event. See this
example:
DATA_EVENT[dvIP]
{
OFFLINE:
{
(* PROCESS THE DATA HERE*)
}
STRING:
{
(* DO NOT REMOVE ME! *)
}
}

Server Programming
Listening for client requests
A client gains access to a service by sending a request to the server specifying the port assigned to the
service. For the request to be acknowledged, the server must be listening on that port. To do this, the
server calls IP_SERVER_OPEN. This opens the port and allows the server to listen for requests from
client applications.
IP_SERVER_OPEN requires the caller to supply a local port number. This local port number is a virtual
port, as opposed to an actual physical port on the server. When TCP is the transport protocol, the local
port represents a single client connection on the server's physical port. When UDP is the transport
protocol, it represents a single point where all client requests on the associated port are routed.
The local port number is the key to identifying data sent to or received from a client application. A local
port number may not be used in another call to IP_SERVER_OPEN, until IP_SERVER_CLOSE is called
for that port number. The syntax:
IP_SERVER_OPEN(LocalPort, ServerPort, Protocol)

Parameters:
LocalPort: The local port number to open. This port number must be passed to
IP_CLIENT_CLOSE to close the conversation.
ServerPort: The port number on the server identifies the program or service the client is
requesting.

NetLinx Programming Language Reference Guide 191


IP Communication

Protocol: The transport protocol to use (1 = TCP, 2 = UDP). If this parameter is not specified,
TCP (1) is assumed. The constants IP_TCP and IP_UDP can be used to specify this
parameter.
Multiple client connections
With connection-oriented I/O (TCP), more than one client could request a connection with the server at
the same time. Support for multiple client connections applies only to connection-oriented I/O, that is,
TCP protocol. Opening multiple ports using UDP as the protocol serves no purpose. In that case, any
additional open commands will fail.
To support concurrent requests, the server must call IP_SERVER_OPEN once for each simultaneous
connection allowed. For example:
IP_SERVER_OPEN (First_Local_Port, 10510, IP_TCP)
IP_SERVER_OPEN (First_Local_Port, 10510, IP_TCP)
IP_SERVER_OPEN (First_Local_Port, 10510, IP_TCP)

This allows three simultaneous connections on port 10510. Note that each call to IP_SERVER_OPEN
uses a different local port number.
Closing a local port
To close a local port, the server application must call IP_SERVER_CLOSE. Once that is called, no
I/O can be handled using the specified local port. The syntax:
IP_SERVER_CLOSE(LocalPort)

Parameters:
LocalPort: The local port number to close.
Connection-oriented notifications
The server receives the following notifications when a client connects or disconnects. The protocol in
this case must be TCP.
DATA[0:LocalPort:0]
{
ONLINE:
{
// client has connected
}
OFFLINE:
{
// client has disconnected
}
}

Parameters:
Device is (or contains as part of an array) the device representing the conversation
(0:LocalPort:0).

192 NetLinx Programming Language Reference Guide


IP Communication

Receiving data
To receive data from a client, use a DATA event handler or a buffer created with CREATE_BUFFER or
CREATE_MULTI_BUFFER. If an event handler is used, the data is located in the Text field of the DATA
object. The syntax:
Data_Event[Device]
{
STRING:
{
// process incoming string (Data.Text)
}
}
Parameters:
Device is (or contains as part of an array) the device representing the conversation
(0:LocalPort:0).
Sending data
To send data to the client, use the SEND_STRING command.
SEND_STRING 0:LocalPort:0, '<string>'

The device specification (0:LocalPort:0) is interpreted as follows:


Device Number: 0: The master
Port: LocalPort: The local port number
System: 0: This system (the client)
Receiving Data with UDP
Since UDP is connection-less, no formal agreement has been made between the client and server to
exchange data. The client simply sends a UDP message and hopes the server is listening. In many
protocols that use UDP for communication, there is an implied agreement for the client to receive date
from the server.
When a UDP client socket in created, the socket is assigned a UDP/IP port number, not to be confused
with local port. This UDP/IP port will be used to send UDP messages. The server, if listening, will
receive this message along with the IP address and UDP/IP of the client who sent the message.
Some UDP protocols have an implied agreement that the server will be able to respond to the client by
sending a response back to the IP address and UDP/IP from where the message originated. Although the
UDP protocol does not specify that the client must expect to receive messages in this way, many UDP/IP
require the client to listening for response after sending a message.
Netlinx has two UDP client implementations. These are UDP (2) and UDP With Receive (3). The first
implementation only sends message and cannot receive messages. UDP with Receive will send and
receive messages on a single UDP/IP port.
It may seem like UDP (2) is not needed; however, it still serves and important purpose. Image you
wanted to send a UDP message and expect a response. The proper way to open this type of socket,
assuming you want to send a UDP message to 192.168.0.1 on UDP/IP port 6000, is:
IP_CLIENT_OPEN(dvUDPClient,'192.168.0.1',6000, IP_UDP_2WAY)

Now, if you were also writing the code for 192.168.0.1, you would need to have opened a UDP server
using the following:
IP_SERVER_OPEN(dvUDPServer,6000,IP_UDP)

NetLinx Programming Language Reference Guide 193


IP Communication

When the message is received at 192.168.0.1, the message will be delivered to the DATA_EVENT for
dvUDPServer and the IP address UDP/IP port of the sender of the message will be available in the
DATA.SOURCEIP and DATA.SOURCEPORT variables. A UDP (2) socket would be used in this case to
send a response to the client. Since we will no longer need to listen after sending the response, since
there would be no response to the response, we would open the socket using the following:
IP_CLIENT_OPEN(dvUDPClient,DATA.SOURCEIP,DATA.SOURCEPORT,IP_UDP)

Note that UDP with Receive (3) is only available when calling IP_CLIENT_OPEN.
Multicast
NetLinx can send and receive multi-cast UDP messages. To send a multi-cast UDP message, all you
need to do is specify a multi-cast address and port in the IP_CLIENT_OPEN function such as the
following:
IP_CLIENT_OPEN (dvIPClient.Port,'239.255.255.250',1900,IP_UDP)

To receive multi-cast UDP messages, you must call the IP_MC_SERVER_OPEN function:
IP_MC_SERVER_OPEN (dvIPServer,'239.255.255.250',1900)

The NetLinx master will join the multi-cast session and allow you to receive and transmit UDP multi-
cast messages.
Example IP Code
PROGRAM_NAME='IPExample'
(***********************************************************)
(* DEVICE NUMBER DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_DEVICE
dvIPServer = 0:2:0
dvIPClient = 0:3:0
(***********************************************************)
(* CONSTANT DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_CONSTANT

nIPPort = 8000
(***********************************************************)
(* VARIABLE DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_VARIABLE

IP_ADDRESS_STRUCT MyIPAddress (* .Flags *)


(* .HostName *)
(* .IPAddress *)
(* .SubnetMask *)
(* .Gateway *)
(***********************************************************)
(* STARTUP CODE GOES BELOW *)
(***********************************************************)

194 NetLinx Programming Language Reference Guide


IP Communication

DEFINE_START

(* Get My IP Address *)
GET_IP_ADDRESS(0:0:0,MyIPAddress)
(* Open The Server *)
IP_SERVER_OPEN(dvIPServer.Port,nIPPort,IP_TCP)
(* Open The Client *)
IP_CLIENT_OPEN(dvIPClient.Port,MyIPAddress.IPAddress,nIPPort,IP_TCP)
(***********************************************************)
(* THE EVENTS GO BELOW *)
(***********************************************************)

DEFINE_EVENT

(* Server Data Handler *)


DATA_EVENT[dvIPServer]
{
ONERROR:
{
SEND_STRING 0,"'error: server=',ITOA(Data.Number)"
}
ONLINE:
{
SEND_STRING 0,"'online: server'"
}
OFFLINE:
{
SEND_STRING 0,"'offline: server'"
}
STRING:
{
SEND_STRING 0,"'string: client=',Data.Text"
IF (FIND_STRING(Data.Text,'ping',1))
SEND_STRING 0:2:0,"'pong',13"
}
}
(* Client Data Handler *)
DATA_EVENT[dvIPClient]
{
ONERROR:
{
SEND_STRING 0,"'error: client=',ITOA(Data.Number)"
}
ONLINE:
{
SEND_STRING 0,"'online: client'"
}
OFFLINE:

NetLinx Programming Language Reference Guide 195


IP Communication

{
SEND_STRING 0,"'offline: client'"
}
STRING:

{
SEND_STRING 0,"'string: client=',Data.Text"
}
}
(***********************************************************)
(* THE ACTUAL PROGRAM GOES BELOW *)
(***********************************************************)
DEFINE_PROGRAM

(* Send Ping To Server *)


WAIT 50
SEND_STRING dvIPClient,"'ping',13"

(***********************************************************)
(* END OF PROGRAM *)
(* DO NOT PUT ANY CODE BELOW THIS COMMENT *)
(***********************************************************)

196 NetLinx Programming Language Reference Guide


NetLinx Modules

NetLinx Modules
The ability to reuse code is a desirable goal in software development; however, code reuse takes careful
planning and organization. As discussed earlier, NetLinx provides tools such as functions and modules
to promote reusability. Modules are NetLinx sub-programs designed to be "plugged into" a main
program.
Defining a module
The MODULE_NAME entry on the first line of the file defines the module. The syntax is:
MODULE_NAME = '<module name>' [(<parameter list>)]
The MODULE_NAME entry identifies the file as containing a NetLinx module, as opposed to a standard
NetLinx source code file. The module name is any valid string literal not to exceed 64 characters. A file
can contain only one module and the file name must be the same as the module name with the addition of
the ".AXS" extension.
Module parameters behave exactly like subroutine parameters; the parameter list is optional. The value
for each parameter is set either by the main program or another module. If the value of a parameter is
changed, both the main program and module see the change.

Constants and expressions cannot be used as arguments in the parameter list.

The example below defines a module named ModuleExample. Aside from the MODULE_NAME entry,
the code looks like any standard NetLinx source code file.
All parameters to a module must be one of the instrinsic types: CHAR, INTEGER, SINTEGER, LONG,
SLONG, FLOAT, DOUBLE, DEV, DEVCHAN or DEVLEV. Also, any of the above array types can be used.
MODULE_NAME='ModuleExample'(DEV dvDECK, DEVCHAN dcTRANPORTS[], INTEGER nFIRST)
(*{{PS_SOURCE_INFO(PROGRAM STATS) *)
(***********************************************************)
(* ORPHAN_FILE_PLATFORM: 1 *)
(***********************************************************)
(*}}PS_SOURCE_INFO *)
(***********************************************************)
(* DEVICE NUMBER DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_DEVICE

(***********************************************************)
(* CONSTANT DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_CONSTANT

NO_BUTTON = 0
NO_FUNCTION = 256

PLAY = 1
STOP = 2

NetLinx Programming Language Reference Guide 197


NetLinx Modules

PAUSE = 3
FFWD = 4
REW = 5
SFWD = 6
SREV = 7
REC = 8

PLAY_FB = 241
STOP_FB = 242
PAUSE_FB = 243
FFWD_FB = 244
REW_FB = 245
SFWD_FB = 246
SREV_FB = 247
REC_FB = 248

(* vcr will go into stop after rewinding for a certain time *)


VCR1_REW_TO_STOP = 1800 (* 3 min *)

(* vcr will go into stop after search rewinding for a certain time *)
VCR1_SREV_TO_STOP = 12000 (* 20 min *)

(* vcr will go into stop after being paused for a certain time *)
VCR1_PAUSE_TO_STOP = 6000 (* 10 min *)

(* button feedback flag *)


VCR1_DEFEAT_FEEDBACK = 0

(***********************************************************)
(* TYPE DEFINITIONS GO BELOW *)
(***********************************************************
DEFINE_TYPE*)

(***********************************************************)
(* VARIABLE DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_VARIABLE

VOLATILE INTEGER nOFFSET_FN (* FUNCTION OFFSET *)


VOLATILE INTEGER nOFFSET_FB (* FEEDBACK OFFSET *)
VOLATILE INTEGER nFUNC (* FUNCTION THAT WAS PRESSED *)

(***********************************************************)
(* SUBROUTINE DEFINITIONS GO BELOW *)
(***********************************************************)

DEFINE_CALL 'ALL OFF'


{

198 NetLinx Programming Language Reference Guide


NetLinx Modules

OFF [dvDECK,nOFFSET_FN+PLAY]
OFF [dvDECK,nOFFSET_FN+STOP]
OFF [dvDECK,nOFFSET_FN+PAUSE]
OFF [dvDECK,nOFFSET_FN+FFWD]
OFF [dvDECK,nOFFSET_FN+REW]
OFF [dvDECK,nOFFSET_FN+SFWD]
OFF [dvDECK,nOFFSET_FN+SREV]
OFF [dvDECK,nOFFSET_FN+REC]
}

DEFINE_CALL 'FEEDBACK' (INTEGER nFUNCTION)


{
[dvDECK,nOFFSET_FB+PLAY_FB] = (nFUNCTION=PLAY)
[dvDECK,nOFFSET_FB+STOP_FB] = (nFUNCTION=STOP)
[dvDECK,nOFFSET_FB+PAUSE_FB] = (nFUNCTION=PAUSE)
[dvDECK,nOFFSET_FB+FFWD_FB] = (nFUNCTION=FFWD)
[dvDECK,nOFFSET_FB+REW_FB] = (nFUNCTION=REW)
[dvDECK,nOFFSET_FB+SFWD_FB] = (nFUNCTION=SFWD)
[dvDECK,nOFFSET_FB+SREV_FB] = (nFUNCTION=SREV)
[dvDECK,nOFFSET_FB+REC_FB] = (nFUNCTION=REC)
}
(***********************************************************)
(* STARTUP CODE GOES BELOW *)
(***********************************************************)
DEFINE_START

(* SELECT OFFSETS IF ANY *)


IF (nFIRST BAND $00FF)
nOFFSET_FN=(nFIRST BAND $00FF)-PLAY
ELSE
nOFFSET_FN=0
IF (nFIRST BAND $FF00)
nOFFSET_FB=((nFIRST BAND $FF00)/$FF)-PLAY_FB
ELSE
nOFFSET_FB=0

(***********************************************************)
(* EVENT PROCESSING ROUTINES BELOW *)
(***********************************************************)
DEFINE_EVENT

(***********************************************************)
(* dcTRANPORTS - TRANSPORT CONTROLS *)
(***********************************************************)
BUTTON_EVENT[dcTRANPORTS]
{
PUSH:
{

NetLinx Programming Language Reference Guide 199


NetLinx Modules

#IF_DEFINED SYSCALL_NOTIFY
SEND_STRING 0,"'IN MODULE ',39,'ModuleExample',39"
#END_IF

(* RUN A FUNCTION *)
nFUNC = GET_LAST(dcTRANPORTS)
SWITCH (nFUNC)
{
CASE PLAY:
{
IF (![dvDECK,nOFFSET_FB+REC_FB])
{
CANCEL_WAIT 'VCR1 REW TO STOP'
CANCEL_WAIT 'VCR1 PAUSE TO STOP'
CANCEL_WAIT 'VCR1 SREV TO STOP'
CALL 'ALL OFF'
MIN_TO [dvDECK,nOFFSET_FN+PLAY]
CALL 'FEEDBACK' (PLAY)
}
}

CASE STOP:
{
CANCEL_WAIT 'VCR1 REW TO STOP'
CANCEL_WAIT 'VCR1 PAUSE TO STOP'
CANCEL_WAIT 'VCR1 SREV TO STOP'
CALL 'ALL OFF'
MIN_TO [dvDECK,nOFFSET_FN+STOP]
CALL 'FEEDBACK' (STOP)
}

CASE PAUSE:
{
SELECT
{
ACTIVE ([dvDECK,nOFFSET_FB+PAUSE_FB]
AND [dvDECK,nOFFSET_FB+REC_FB]
AND dcTRANPORTS[8].CHANNEL<NO_FUNCTION):
{
CANCEL_WAIT 'VCR1 REW TO STOP'
CANCEL_WAIT 'VCR1 PAUSE TO STOP'
CANCEL_WAIT 'VCR1 SREV TO STOP'
CALL 'ALL OFF'
MIN_TO [dvDECK,nOFFSET_FN+REC]
CALL 'FEEDBACK' (REC)
}
ACTIVE ([dvDECK,nOFFSET_FB+PAUSE_FB]
AND dcTRANPORTS[1].CHANNEL<NO_FUNCTION):

200 NetLinx Programming Language Reference Guide


NetLinx Modules

{
CANCEL_WAIT 'VCR1 REW TO STOP'
CANCEL_WAIT 'VCR1 PAUSE TO STOP'
CANCEL_WAIT 'VCR1 SREV TO STOP'
CALL 'ALL OFF'
MIN_TO [dvDECK,nOFFSET_FN+PLAY]
CALL 'FEEDBACK' (PLAY)
}
ACTIVE ([dvDECK,nOFFSET_FB+PLAY_FB]):
{
CANCEL_WAIT 'VCR1 REW TO STOP'
CANCEL_WAIT 'VCR1 PAUSE TO STOP'
CANCEL_WAIT 'VCR1 SREV TO STOP'
WAIT VCR1_PAUSE_TO_STOP 'VCR1 PAUSE TO STOP'
SYSTEM_CALL 'FUNCTION' (dvDECK,STOP,nFIRST)
CALL 'ALL OFF'
MIN_TO [dvDECK,nOFFSET_FN+PAUSE]
CALL 'FEEDBACK' (PAUSE)
}
ACTIVE ([dvDECK,nOFFSET_FB+REC_FB]):
{
CANCEL_WAIT 'VCR1 REW TO STOP'
CANCEL_WAIT 'VCR1 PAUSE TO STOP'
CANCEL_WAIT 'VCR1 SREV TO STOP'
WAIT VCR1_PAUSE_TO_STOP 'VCR1 PAUSE TO STOP'
SYSTEM_CALL 'FUNCTION' (dvDECK,STOP,nFIRST)
CALL 'ALL OFF'
MIN_TO [dvDECK,nOFFSET_FN+PAUSE]
CALL 'FEEDBACK' (PAUSE)
ON [dvDECK,nOFFSET_FB+REC_FB]
}
}
}

CASE FFWD:
{
SELECT
{
ACTIVE ([dvDECK,nOFFSET_FB+STOP_FB]
OR [dvDECK,nOFFSET_FB+FFWD_FB]
OR [dvDECK,nOFFSET_FB+REW_FB]
OR (dcTRANPORTS[6].CHANNEL
AND ([dvDECK,nOFFSET_FB+PLAY_FB]
OR [dvDECK,nOFFSET_FB+SREV_FB]
OR [dvDECK,nOFFSET_FB+SFWD_FB]))):
{
CANCEL_WAIT 'VCR1 REW TO STOP'
CANCEL_WAIT 'VCR1 PAUSE TO STOP'

NetLinx Programming Language Reference Guide 201


NetLinx Modules

CANCEL_WAIT 'VCR1 SREV TO STOP'


CALL 'ALL OFF'
MIN_TO [dvDECK,nOFFSET_FN+FFWD]
CALL 'FEEDBACK' (FFWD)
}
ACTIVE (dcTRANPORTS[6].CHANNEL=NO_BUTTON
AND ([dvDECK,nOFFSET_FB+PLAY_FB]
OR [dvDECK,nOFFSET_FB+SREV_FB]
OR [dvDECK,nOFFSET_FB+SFWD_FB])):
{
CANCEL_WAIT 'VCR1 REW TO STOP'
CANCEL_WAIT 'VCR1 PAUSE TO STOP'
CANCEL_WAIT 'VCR1 SREV TO STOP'
CALL 'ALL OFF'
MIN_TO [dvDECK,nOFFSET_FN+SFWD]
CALL 'FEEDBACK' (SFWD)
}
}
}

CASE SFWD:
{
IF ([dvDECK,nOFFSET_FB+PLAY_FB]
OR [dvDECK,nOFFSET_FB+STOP_FB]
OR [dvDECK,nOFFSET_FB+REW_FB]
OR [dvDECK,nOFFSET_FB+FFWD_FB]
OR [dvDECK,nOFFSET_FB+SREV_FB]
OR [dvDECK,nOFFSET_FB+SFWD_FB])
{
CANCEL_WAIT 'VCR1 REW TO STOP'
CANCEL_WAIT 'VCR1 PAUSE TO STOP'
CANCEL_WAIT 'VCR1 SREV TO STOP'
CALL 'ALL OFF'
MIN_TO [dvDECK,nOFFSET_FN+SFWD]
CALL 'FEEDBACK' (SFWD)
}
}

CASE REW:
{
SELECT
{
ACTIVE ([dvDECK,nOFFSET_FB+STOP_FB]
OR [dvDECK,nOFFSET_FB+FFWD_FB]
OR [dvDECK,nOFFSET_FB+REW_FB]
OR (dcTRANPORTS[7].CHANNEL
AND ([dvDECK,nOFFSET_FB+PLAY_FB]
OR [dvDECK,nOFFSET_FB+SREV_FB]

202 NetLinx Programming Language Reference Guide


NetLinx Modules

OR [dvDECK,nOFFSET_FB+SFWD_FB]))):
{
CANCEL_WAIT 'VCR1 REW TO STOP'
CANCEL_WAIT 'VCR1 PAUSE TO STOP'
CANCEL_WAIT 'VCR1 SREV TO STOP'
WAIT VCR1_REW_TO_STOP 'VCR1 REW TO STOP'
SYSTEM_CALL 'FUNCTION' (dvDECK,STOP,nFIRST)
CALL 'ALL OFF'
MIN_TO [dvDECK,nOFFSET_FN+REW]
CALL 'FEEDBACK' (REW)
}
ACTIVE (dcTRANPORTS[7].CHANNEL=NO_BUTTON
AND ([dvDECK,nOFFSET_FB+PLAY_FB]
OR [dvDECK,nOFFSET_FB+SREV_FB]
OR [dvDECK,nOFFSET_FB+SFWD_FB])):
{
CANCEL_WAIT 'VCR1 REW TO STOP'
CANCEL_WAIT 'VCR1 PAUSE TO STOP'
CANCEL_WAIT 'VCR1 SREV TO STOP'
WAIT VCR1_SREV_TO_STOP 'VCR1 SREV TO STOP'
SYSTEM_CALL 'FUNCTION' (dvDECK,STOP,nFIRST)
CALL 'ALL OFF'
MIN_TO [dvDECK,nOFFSET_FN+SREV]
CALL 'FEEDBACK' (SREV)
}
}
}

CASE SREV:
{
IF ([dvDECK,nOFFSET_FB+PLAY_FB]
OR [dvDECK,nOFFSET_FB+STOP_FB]
OR [dvDECK,nOFFSET_FB+REW_FB]
OR [dvDECK,nOFFSET_FB+FFWD_FB]
OR [dvDECK,nOFFSET_FB+SREV_FB]
OR [dvDECK,nOFFSET_FB+SFWD_FB])
{
CANCEL_WAIT 'VCR1 REW TO STOP'
CANCEL_WAIT 'VCR1 PAUSE TO STOP'
CANCEL_WAIT 'VCR1 SREV TO STOP'
WAIT VCR1_SREV_TO_STOP 'VCR1 SREV TO STOP'
SYSTEM_CALL 'FUNCTION' (dvDECK,STOP,nFIRST)
CALL 'ALL OFF'
MIN_TO [dvDECK,nOFFSET_FN+SREV]
CALL 'FEEDBACK' (SREV)
}
}
Continued

NetLinx Programming Language Reference Guide 203


NetLinx Modules

CASE REC:
{
IF ([dvDECK,nOFFSET_FB+STOP_FB]
OR [dvDECK,nOFFSET_FB+REC_FB])
{
CANCEL_WAIT 'VCR1 REW TO STOP'
CANCEL_WAIT 'VCR1 PAUSE TO STOP'
CANCEL_WAIT 'VCR1 SREV TO STOP'
CALL 'ALL OFF'
MIN_TO [dvDECK,nOFFSET_FN+REC]
CALL 'FEEDBACK' (REC)
}
}
}
}
}

(***********************************************************)
(* THE ACTUAL PROGRAM GOES BELOW *)
(***********************************************************)
DEFINE_PROGRAM

[dcTRANPORTS[1]] = [dvDECK,nOFFSET_FB+PLAY_FB]
[dcTRANPORTS[2]] = [dvDECK,nOFFSET_FB+STOP_FB]
[dcTRANPORTS[3]] = [dvDECK,nOFFSET_FB+PAUSE_FB]
[dcTRANPORTS[4]] = ([dvDECK,nOFFSET_FB+FFWD_FB] OR
(dcTRANPORTS[6].CHANNEL=NO_BUTTON AND [dvDECK,nOFFSET_FB+SFWD_FB]))
[dcTRANPORTS[5]] = ([dvDECK,nOFFSET_FB+REW_FB] OR
(dcTRANPORTS[7].CHANNEL=NO_BUTTON AND [dvDECK,nOFFSET_FB+SREV_FB]))
[dcTRANPORTS[6]] = [dvDECK,nOFFSET_FB+SFWD_FB]
[dcTRANPORTS[7]] = [dvDECK,nOFFSET_FB+SREV_FB]
[dcTRANPORTS[8]] = ([dvDECK,nOFFSET_FB+REC_FB] AND
(![dvDECK,nOFFSET_FB+PAUSE_FB]))

(***********************************************************)
(* END OF PROGRAM *)
(* DO NOT PUT ANY CODE BELOW THIS COMMENT *)
(***********************************************************)

Using a module in a program


To use a module in a program, you must declare it using the DEFINE_MODULE keyword. This tells the
NetLinx compiler to add the module to the program, effectively merging the module's event handling
and mainline code with the containing program (or module). In other words, the program will have one
event table and one mainline routine consisting of code from the main program and all modules declared
using the DEFINE_MODULE statement.

204 NetLinx Programming Language Reference Guide


NetLinx Modules

Technically, modules can contain declarations to other modules, provided that no circular references are
involved. However, because different instances of the same module must not be separated by instances of
a different module, it is highly recommended that you do not declare modules from within other modules
- if you have multiple declarations of the parent module they will then be separated by the declarations of
the child module.
FIG. 1 demonstrates how a NetLinx module is incorporated into a main program. In this example, the
main program has no event table or mainline code.

FIG. 1 Mainline and Event Table Organization

PROGRAM_NAME='ModuleExampleTest'
(*{{PS_SOURCE_INFO(PROGRAM STATS) *)
(***********************************************************)
(* ORPHAN_FILE_PLATFORM: 1 *)
(***********************************************************)
(*}}PS_SOURCE_INFO *)
(***********************************************************)
(* DEVICE NUMBER DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_DEVICE

dvVCR = 1:7:0
dvTP = 128:1:0

(***********************************************************)
(* VARIABLE DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_VARIABLE
VOLATILE
DEVCHAN dcTRANPORTS[] = {
{ dvTP,1 }, { dvTP,2 }, { dvTP,3 }, { dvTP,4 },
{ dvTP,5 }, { dvTP,6 }, { dvTP,7 }, { dvTP,8 }
}
VOLATILE
INTEGER nVCR_FIRST = 0

NetLinx Programming Language Reference Guide 205


NetLinx Modules

(***********************************************************)
(* MODULE CODE GOES BELOW *)
(***********************************************************)

DEFINE_MODULE 'ModuleExample' mdlVCR(dvVCR,dcTRANPORTS,nVCR_FIRST)

(***********************************************************)
(* END OF PROGRAM *)
(* DO NOT PUT ANY CODE BELOW THIS COMMENT *)
(***********************************************************)

206 NetLinx Programming Language Reference Guide


Internet Inside

Internet Inside
The Internet Inside™ feature of the NetLinx master allows a web browser to retrieve web pages directly
from the master. The web pages provide a user interface that mimics the look and feel of an AMX touch
panel. In fact, TPDesign generates the web pages.
The components of Internet Inside are as follows:
Java TPClasses – The Java client code that runs on the browser essentially emulating a touch
panel.
WDM – Web Device Manager. A software module that runs on the NetLinx masters that
proxies control information to the master on behalf of the Java client.
PNG files – Portable Network Graphics. Bitmap graphics that get displayed in the browser.
Both touch panel icons and touch panel bitmaps get converted to PNG files for the Java client
to display.
XML files - Extensible Markup Language. Page definition files that describe that layout of
each page. The Java client loads one of the XML files for every page flip that occurs (load on
demand) and, therefore, are not loaded into the browser when the client makes its initial
connection.
HTML file – There is a single HTML file called INDEX.HTM for each user interface. The
HTML file contains just enough information to get the Java client up and running.
WDM Configuration file – The WDM references a configuration file (WDM.CONF) to
determine its operational parameters.
When TPDesign generates the web pages for NetLinx it creates all of the files necessary and places them
into a local directory. The created files must be downloaded to the NetLinx master into a sub-directory of
the /USER directory. For example, a board room system that contains a NetLinx master might be placed
in a directory named /BoardRoom as a subdirectory of /USER.
If you decide to download the files to the NetLinx master, you’ll have to use an FTP client. The FTP user
name must be "NetLinx" (case sensitive) and the password is "password" (case sensitive). The default
directory returned by FTP is doc:/user. The user must create a subdirectory of /user and download all of
the files into that newly created directory.
Java TPClasses
The Java TPClasses client code runs in the users web browser and is loaded when the INDEX.HTM file
loaded. The Java TPClasses code performs several different functions, including providing the look and
feel of the user interface and providing the communication mechanism to the WDM. The
communication connection between TPClasses and WDM is a persistent TCP/IP connection using TCP
port 10510 by default. The TCP port number may be changed, if necessary, by editing the INDEX.HTM
and WDM.CONF files. The line in the INDEX.HTM file that needs to change is:
<param name="connectport" value="10500">

The INDEX.HTM file also contains the NetLinx device number that the web user interface will connect to
the NetLinx master. This device number must have NetLinx code written to support it. Typically, a
simple DEFINE_COMBINE between the "real" touch panel and the web user interface device number is
utilized that provides identical functionality to the web user interface that the "real" touch panel has.
TPDesign provides a facility for setting the device number and range of devices for the web user
interface. However, the device number and range may be changed by editing the following line in the
INDEX.HTM file:
<param name="devrange1" value="225,228,4">

NetLinx Programming Language Reference Guide 207


Internet Inside

The first parameter is the starting device number, the second parameter is the ending device number
inclusive, and the last parameter is the number of NetLinx devices the web user interface uses per
instance. The purpose of this format is to allow multiple instances of the same web user interface on
multiple browsers. For example, assume a conference room where the user desires the ability to connect
two simultaneous web user interfaces. Since duplicate device numbers are not allowed, the two user
interfaces must have distinctly different device numbers. The following might exist in the INDEX.HTM
file:
<param name="devrange1" value="225,232,4">

When the Java client code connects to the WDM it negotiates an unused device number or range with the
WDM based upon the devrange1 parameters. The example above would allow a web user interface to
have either the range of devices 225,226,227 and 228, or the range of 229,230,231, and 232. Note that
the NetLinx program would have to contain a DEFINE_COMBINE that included combining device 225
with 229, 226 with 230, etc.
WDM Configuration
The configuration of the WDM is optional because the WDMs default configuration options work for
most applications. The only WDM configuration option that might need to be modified is the TCP port
that the TPClasses Java code attempts to connect. By default, the WDM listens for the Java code to
connect on TCP port 10500.
The WDM reads the WDM.CONF file from the NetLinx master’s disk-on-chip /USER directory. Normally,
there is no WDM.CONF file in the /USER directory so the WDM uses its default values. To override the
defaults, a properly modified WDM.CONF file must be placed in the /USER directory. Conveniently,
TPDesign creates a WDM.CONF file that can be used as a template. Shown below is the WDM.CONF file
that TPDesign creates automatically:
DEBUG_PORT 10000
PERSIST_SRV_PORT 10500
MASTER 1 127.0.0.1 1319
LISTEN_BACKLOG 5

The only configuration setting that should be modified is the PERSIST_SRV_PORT parameter, and it
must be set to the same port number as the TPClasses Java code’s "connectport" parameter. The
"connectport" parameter exists in the INDEX.HTM file that is also created by TPDesign (see the Java
TPClasses section on page 207 for more information).

The WDM listens on a single TCP port; every web user interface and WDM MUST
have the same TCP port setting. If you manually change the TCP port configuration
of one, you must change the TCP port configuration on all of them (WDM and all
INDEX.HTM files).

208 NetLinx Programming Language Reference Guide


Encoding and Decoding: Binary and XML

Encoding and Decoding: Binary and XML


There are six special functions used to encode and decode variables in NetLinx. This encoding process
takes a NetLinx variable, no matter how complex, and converts it into a string. The decode process will
take this string and copy the contents back into a variable.
These functions can be used to take the contents of NetLinx variables and convert them to string. Once
the variable exists in string form, it can then be sent across an RS-232 connection, sent over and IP
socket or saved to the NetLinx master's file system (disc on chip). Once the string is retrieved, either
from a data event or by reading the information from the NetLinx master's file system, the data can be
converted back to a variable.
There are two version of this encoding and decoding: Binary and XML. The binary conversion routines
are: STRING_TO_VARIABLE, VARIABLE_TO_STRING and
LENGTH_ VARIABLE_TO_STRING.
The XML routines are XML_TO_VARIABLE, VARIABLE_TO_XML and
LENGTH_ VARIABLE_TO_XML. Both sets of routines accomplish the same function but the encoded
string differs in protocol. The binary conversion routines uses a compact binary representation of the
variable while the XML represents the variable as a ASCII text only XML document.
The binary routines are ideal when sending data from one NetLinx system to another NetLinx system
over RS-232 or IP since the variable will be as compact as possible. It is also ideal for saving a file to the
NetLinx master's file system if you do not intend to edit the file later. The binary routines encode and
decode a variable sequentially meaning that the order and type of the variables must match on both the
encoding and decoding side.
The XML routines are ideal when sending data from one NetLinx system to another type of system over
RS232 or IP, since XML is more universally accepted by other types of computer systems. XML is also
ideal for saving a file to the NetLinx master's file system if you intend to edit the file later since it is
entirely ASCII text. It should be noted that while the XML is more universal, is not very compact. The
XML routines encode and decode a variable non-sequentially, meaning that the order and type of
variables do not need to match on both the encoding and decoding side.
Below are some examples of how to use these encoding routines:
PROGRAM_NAME='ConversionExample'
(*{{PS_SOURCE_INFO(PROGRAM STATS) *)
(***********************************************************)
(* FILE CREATED ON: 05/22/2001 AT: 11:09:27 *)
(***********************************************************)
(* FILE_LAST_MODIFIED_ON: 05/22/2001 AT: 11:26:44 *)
(***********************************************************)
(* ORPHAN_FILE_PLATFORM: 1 *)
(***********************************************************)

(*!!FILE REVISION: *)
(* REVISION DATE: 05/22/2001 *)
(* *)
(* COMMENTS: *)
(* *)
(***********************************************************)
(*}}PS_SOURCE_INFO *)

NetLinx Programming Language Reference Guide 209


Encoding and Decoding: Binary and XML

(***********************************************************)
(***********************************************************)
(* System Type : NetLinx *)
(***********************************************************)
(* REV HISTORY: *)
(***********************************************************)
(***********************************************************)
(* DEVICE NUMBER DEFINITIONS GO BELOW *)
(***********************************************************)

DEFINE_DEVICE
dvTP = 128:1:0
(***********************************************************)
(* CONSTANT DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_CONSTANT

nFileRead = 1
nFileWrite = 2
(***********************************************************)
(* DATA TYPE DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_TYPE

STRUCTURE _AlbumStruct
{
LONG lTitleID
CHAR sArtist[100]
CHAR sTitle[100]
CHAR sCopyright[100]
CHAR sLabel[100]
CHAR sReleaseDate[100]
INTEGER nNumTracks
CHAR sCode[100]
INTEGER nDiscNumber
}

STRUCTURE _AlbumStruct2
{
CHAR sArtist[100]
CHAR sTitle[100]
INTEGER nNumTracks}
(***********************************************************)
(* VARIABLE DEFINITIONS GO BELOW *)
(***********************************************************)

210 NetLinx Programming Language Reference Guide


Encoding and Decoding: Binary and XML

DEFINE_VARIABLE
VOLATILE _AlbumStruct AlbumStruct[3]
VOLATILE _AlbumStruct2
AlbumStruct2[3]
VOLATILE CHAR sBinaryString[10000]
VOLATILE CHAR sXMLString[50000]
VOLATILE LONG lPos
VOLATILE SLONG slFile
VOLATILE SLONG slReturn

(***********************************************************)
(* STARTUP CODE GOES BELOW *)
(***********************************************************)
DEFINE_START

(* assign some values *)


AlbumStruct[1].lTitleID = 11101000
AlbumStruct[1].sArtist = 'Buffet, Jimmy'
AlbumStruct[1].sTitle = 'Living & Dying in 3/4 Time'
AlbumStruct[1].sCopyright = 'MCA'
AlbumStruct[1].sLabel = 'MCA'
AlbumStruct[1].sReleaseDate = '1974'
AlbumStruct[1].nNumTracks = 11
AlbumStruct[1].sCode = '3132333435'
AlbumStruct[1].nDiscNumber = 91
AlbumStruct[2].lTitleID = 17248229
AlbumStruct[2].sArtist = 'Buffet, Jimmy'
AlbumStruct[2].sTitle = 'Off to See the Lizard'
AlbumStruct[2].sCopyright = 'MCA'
AlbumStruct[2].sLabel = 'MCA'
AlbumStruct[2].sReleaseDate = '1989'
AlbumStruct[2].nNumTracks = 11
AlbumStruct[2].sCode = '3132333436'
AlbumStruct[2].nDiscNumber = 105
AlbumStruct[3].lTitleID = 12328612
AlbumStruct[3].sArtist = 'Buffet, Jimmy'
AlbumStruct[3].sTitle = 'A-1-A'
AlbumStruct[3].sCopyright = 'MCA'
AlbumStruct[3].sLabel = 'MCA'
AlbumStruct[3].sReleaseDate = '1974'
AlbumStruct[3].nNumTracks = 11
AlbumStruct[3].sCode = '3132333437'
AlbumStruct[3].nDiscNumber = 189

(***********************************************************)
(* THE EVENTS GO BELOW *)
(***********************************************************)

NetLinx Programming Language Reference Guide 211


Encoding and Decoding: Binary and XML

DEFINE_EVENT

(* CONVERT AND SAVE *)


BUTTON_EVENT[dvTP,1]
{
PUSH:
{
(* CONVERT TO BINARY *)
lPos = 1
slReturn = VARIABLE_TO_STRING (AlbumStruct,sBinaryString,lPos)
SEND_STRING 0,"'POSITION=',ITOA(lPos),'; RETURN=',ITOA(slReturn)"

(* CONVERT TO XML *)
lPos = 1
slReturn = VARIABLE_TO_XML (AlbumStruct,sXMLString,lPos,0)
SEND_STRING 0,"'POSITION=',ITOA(lPos),'; RETURN=',ITOA(slReturn)"

(* NOW WE CAN SAVE THESE BOTH TO DISCS *)


slFile = FILE_OPEN('BinaryEncode.xml',nFileWrite)
IF (slFile > 0)
{
slReturn =
FILE_WRITE(slFile,sBinaryString,LENGTH_STRING(sBinaryString))
IF (slReturn < 0) SEND_STRING 0,"'FILE WRITE FAIL
RETURN=',ITOA(slReturn)"
slReturn = FILE_CLOSE(slFile)
IF (slReturn < 0) SEND_STRING 0,"'FILE CLOSE FAIL
RETURN=',ITOA(slReturn)"
}
slFile = FILE_OPEN('XMLEncode.xml',nFileWrite)
IF (slFile > 0)
{
slReturn = FILE_WRITE(slFile,sXMLString,LENGTH_STRING(sXMLString))
IF (slReturn < 0) SEND_STRING 0,"'FILE WRITE FAIL
RETURN=',ITOA(slReturn)"
slReturn = FILE_CLOSE(slFile)
IF (slReturn < 0) SEND_STRING 0,"'FILE CLOSE FAIL
RETURN=',ITOA(slReturn)"
}

(* Clear string *)
sBinaryString = ""
sXMLString = ""
}
}

(* READ AND DECODE *)


BUTTON_EVENT[dvTP,2]

212 NetLinx Programming Language Reference Guide


Encoding and Decoding: Binary and XML

{
PUSH:
{
(* NOW WE CAN SAVE THESE BOTH TO DISCS *)
slFile = FILE_OPEN('BinaryEncode.xml',nFileRead)
IF (slFile > 0)

{
slReturn =
FILE_READ(slFile,sBinaryString,MAX_LENGTH_STRING(sBinaryString))
IF (slReturn < 0) SEND_STRING 0,"'FILE WRITE FAIL RETURN=',ITOA(slReturn)"
slReturn = FILE_CLOSE(slFile)
IF (slReturn < 0) SEND_STRING 0,"'FILE CLOSE FAIL RETURN=',ITOA(slReturn)"
}

slFile = FILE_OPEN('XMLEncode.xml',nFileRead)
IF (slFile > 0)
{
slReturn = FILE_READ(slFile,sXMLString,MAX_LENGTH_STRING(sXMLString))
IF (slReturn < 0) SEND_STRING 0,"'FILE WRITE FAIL RETURN=',ITOA(slReturn)"
slReturn = FILE_CLOSE(slFile)
IF (slReturn < 0) SEND_STRING 0,"'FILE CLOSE FAIL RETURN=',ITOA(slReturn)"
}
(* CONVERT TO BINARY *)
lPos = 1
slReturn = STRING_TO_VARIABLE (AlbumStruct,sBinaryString,lPos)
SEND_STRING 0,"'POSITION=',ITOA(lPos),'; RETURN=',ITOA(slReturn)"

(* CONVERT TO XML *)
lPos = 1
slReturn = XML_TO_VARIABLE (AlbumStruct,sXMLString,lPos,0)
SEND_STRING 0,"'POSITION=',ITOA(lPos),'; RETURN=',ITOA(slReturn)"
}
}
(* READ AND DECODE *)
(* THE BINARY WILL FAIL SINCE THE DECODE TYPE DOES NOT MATCH THE ENCODE TYPE *)
(* THE XML WILL NOT FAIL SINCE IT DOES NOT REQUIRE DATA TO BE THE SEQUENTIAL *)
BUTTON_EVENT[dvTP,3]
{

PUSH:
{
(* NOW WE CAN SAVE THESE BOTH TO DISCS *)
slFile = FILE_OPEN('BinaryEncode.xml',nFileRead)
IF (slFile > 0)
{

NetLinx Programming Language Reference Guide 213


Encoding and Decoding: Binary and XML

slReturn =
FILE_READ(slFile,sBinaryString,MAX_LENGTH_STRING(sBinaryString))
IF (slReturn < 0) SEND_STRING 0,"'FILE WRITE FAIL RETURN=',ITOA(slReturn)"
slReturn = FILE_CLOSE(slFile)
IF (slReturn < 0) SEND_STRING 0,"'FILE CLOSE FAIL RETURN=',ITOA(slReturn)"
}
slFile = FILE_OPEN('XMLEncode.xml',nFileRead)
IF (slFile > 0)
{
slReturn = FILE_READ(slFile,sXMLString,MAX_LENGTH_STRING(sXMLString))
IF (slReturn < 0) SEND_STRING 0,"'FILE WRITE FAIL RETURN=',ITOA(slReturn)"
slReturn = FILE_CLOSE(slFile)
IF (slReturn < 0) SEND_STRING 0,"'FILE CLOSE FAIL RETURN=',ITOA(slReturn)"
}

(* CONVERT TO BINARY *)
lPos = 1
slReturn = STRING_TO_VARIABLE (AlbumStruct2,sBinaryString,lPos)
SEND_STRING 0,"'POSITION=',ITOA(lPos),'; RETURN=',ITOA(slReturn)"

(* CONVERT TO XML *)
lPos = 1
slReturn = XML_TO_VARIABLE (AlbumStruct2,sXMLString,lPos,0)
SEND_STRING 0,"'POSITION=',ITOA(lPos),'; RETURN=',ITOA(slReturn)"
}
}
(***********************************************************)
(* THE ACTUAL PROGRAM GOES BELOW *)
(***********************************************************)

DEFINE_PROGRAM

(***********************************************************)
(* END OF PROGRAM *)
(* DO NOT PUT ANY CODE BELOW THIS COMMENT *)
(***********************************************************)

214 NetLinx Programming Language Reference Guide


Appendix A: Marshalling Protocol

Appendix A: Marshalling Protocol


Marshalling Protocol (Group of Bytes)
The protocol assumes that every logical field (group of bytes) is prefixed with type/size information. For
example, if there is a 4 byte long integer field within a structure, the byte stream representing that field
consists of 5 bytes. The first byte (0xE3) specifies that a long integer follows and then the 4 remaining
bytes contain the value of the long integer.
This concept is extended to all primitive, structure and array types. The type of a field is always stored as
a single byte. The size of a field may or may not be stored depending upon the field type (fields with
know lengths do not have a size prefix). The specific formats of all the supported types are described in
the table below.
Marshalled Stream Format
The following table describes the byte format of the various types supported in the marshaller (fields
within <>'s indicate actual data bytes):
Byte Formats Supported in the Marshaller
Type Description Stream Format
BYTE Unsigned char/byte value. 0xE1
<BYTE>
WORD Unsigned short value. 0xE2
<WORD Hi>
<WORD Lo>
DWORD 4-byte value (could be an unsigned long integer or a float). 0xE3
<DWORD MSB>
.
.
<DWORD LSB>
QWORD 8-byte value (could be an unsigned Quad-word or a double). 0xE4
<QWORD MSB>
.
.
.
.
.
.
<QWORD LSB>
BYTESTR Sequence of BYTE's whose element count is <= 64K. 0xE5
Length Hi
Length Lo
<BYTE Sequence>
.
.

NetLinx Programming Language Reference Guide 215


Appendix A: Marshalling Protocol

Byte Formats Supported in the Marshaller (Cont.)


WORDSTR Sequence of WORD's whose element count is <= 64K. 0xE6
Length Hi
Length Lo
<WORD Sequence>
.
.
DWORDSTR Sequence of DWORD's whose element count is <= 64K. 0xE7
Length Hi
Length Lo
<DWORD Sequence>
.
.
QWORDSTR Sequence of QWORD's whose element count is <= 64K. 0xE8
Length Hi
Length Lo
<QWORD Sequence>
.
.
LBYTESTR Large sequence of BYTE's whose element count can be > 0xE9
64K (larger version of BYTESTR). Length MSB
.
.
Length LSB
< BYTE Sequence>
.
.
STRUCT A structure containing one or more fields. Each element 0xEA
within a structure is self-descriptive and can be any of the <First Struct Element 1>
types in this table.
.
.

END- Byte indicator for end of structure - not really a data type pre- 0xEB
STRUCT fix.
ARRAY Array of any one of the types in this table whose element- 0xEC
count can be > 64K. Each element in an array is selfdescrip- Length MSB
tive.The type of the first element (byte after LengthLSB) is
.
the type of the entire array.
.
Length LSB
<Array Element 1>
.
.
SKIP Byte indicator for space to be skipped in the input and 0xED
NULL'ed in the marshalled output. This can be viewed as a
NULL data type prefix.

216 NetLinx Programming Language Reference Guide


Appendix A: Marshalling Protocol

Marshalling Protocol (Variables)


The protocol assumes that every logical field (variable) is identified with a name or index, type/size
information and the actual data. For example, if there is a 4 byte long integer field within a structure, the
XML stream representing that field would consist of 3 tags: A name tag specifying the name of the
variable, a type tag specifying a 4 byte unsigned value, and the data. This concept is extended to all
primitive, structure and array types. The type of a field is always stored using W3C standard type
declarations. The type of the field is optional, as the data will be "stuffed" into whatever type matches the
name of the parameter. The specific formats of all the supported types are described below.
Marshalled Stream format
The following table describes the byte format of the various types supported in the XML marshaller.
Types Supported in the XML Marshaller
Type Description Stream Format
BYTE Unsigned char/byte value. If var is an element of an <var>
array, name is replaced with <index></index>. The <name>MyName</name>
index value, and the type are optional. Typically, only
<type>ui1</type>
<var><data>Data</data></var> is needed.
<data>255</data>
</var>
UWORD Unsigned short value. If var is an element of an array, <var>
name is replaced with <index></index>. The index <name>MyName</name>
value, and the type are optional. Typically, only
<var><data>Data</data></var> is needed. <type>ui2</type>
<data>65535</data>
</var>
WORD Signed short value. If var is an element of an array, <var>
name is replaced with <index></index>. The index <name>MyName</name>
value, and the type are optional. Typically, only
<var><data>Data</data></var> is needed. <type>i2</type>
<data>-32767</data>
</var>
ULONG 4-byte unsigned value. If var is an element of an array, <var>
name is replaced with <index></index>. The index <name>MyName</name>
value, and the type are optional. Typically, only
<var><data>Data</data></var> is needed. <type>ui4</type>
<data>4294967295 </data>
</var>
LONG 4-byte signed value. If var is an element of an array, <var>
name is replaced with <index></index>. The index <name>MyName</name>
value, and the type are optional. Typically, only
<var><data>Data</data></var> is needed. <type>ui4</type>
<data>-2147483647 </data>
</var>
FLOAT 4-byte IEEE 754 float value. If var is an element of an <var>
array, name is replaced with <index></index>. The <name>MyName</name>
index value, and the type are optional. Typically, only
<var><data>Data</data></var> is needed. <type>float.IEEE.754.32</type>
<data>1.23</data>
</var>

NetLinx Programming Language Reference Guide 217


Appendix A: Marshalling Protocol

Types Supported in the XML Marshaller (Cont.)


DOUBLE 8-byte IEEE 754 float value. If var is an element of an <var>
array, name is replaced with <index></index>. The <name>MyName</name>
index value, and the type are optional. Typically, only
<type>float.IEEE.754.64</type>
<var><data>Data</data></var> is needed.
<data>4.56</data>
</var>
STRUCT A structure containing one or more fields. Each ele- <struct> <name><MyName></name>
ment within a structure is self-descriptive and can be <var>…
any of the types in this table. If the struct is the outer-
</var>
most parent, then name is optional. If struct is an ele-
ment of an array, name is replaced with </struct>
<index></index> and the index value.
ARRAY Array of any one of the types in this table. Each ele- <array>
ment in an array is self-descriptive. The type of the <name><MyName></name>
parent is the type of the entire array. Type is optional
and generally not included when the array is an array <type>Type</type>
of structures. Current Length is optional. Array can <curLength>100</curLength>
contain a series of items, a series of structures or a <var>
series of array. Elements of an array should define an
<index>1</index>…
index instead of a name. This is the commonly used
format for structures but all types are allowed. </var></array>
...or...
<array>
<name><MyName></name>
<type>Type</type>
<curLength>100</curLength>
<struct>
<index>1</index>…
</struct>
</array>
... or...
<array>
<name><MyName></name>
<type>Type</type>
<curLength>100</curLength>
<array> <index>1</index>…
</array>
</array>
Array - Array of unsigned characters. Data is encoded using <array>
String String encoding. Type and length are optional. <name><MyName></name>
encoding
(Strings) <type>Type</type>
<curLength>100</curLength>
<string>MyString</string>
</array>

218 NetLinx Programming Language Reference Guide


Appendix A: Marshalling Protocol

Types Supported in the XML Marshaller (Cont.)


ARRAY - Array of any one of the types in this table except struc- <array>
Binary tures. This is the default for all non-CHAR arrays but <name><MyName></name>
Encoded CHAR arrays can use this encoding as well. The type
<type>Type</type>
of the parent is the type of the entire array. Type is
optional and generally not included. Current Length is <curLength>100</curLength>
optional. Style is LE for little endian or BE for big <encoded>
endian. BE is the default. Size indicates the byte size
<style>LE or BE</ style >
but not the type. ByteSize=4 is used for LONG,
SLONG, and FLOAT and means that 8 nibbles will be <size>1,2,4,8</size>
present for each element being encoded/decoded. <data>01020304</data>
</encoded>
</array>

Encoding notes:
The encoding XML will not contain any white space. This includes CR,LF pairs.
The decoding XML may contain white spaces. They will be ignored according to standard
XML rules (i.e. Spaces as between tags are read.)
Array may be encoded or decoded as binary encoded data
XML comments, <!-- -->, will be ignored in decode.
String encoding
NetLinx has no native string type, but since it is a common type the encoding/decoding of the string data
will be logically handled so the XML remains concise. CHAR arrays will be encoded/decoded as a string
type, printable ASCII characters appear as ASCII, and non-printable characters appear as escaped
decimal or hex code, &#<decimal code>; or &#x<hex code>;. An example string would be:
<data>My Name is Jimmy Buffet&#x0D;</data>

- or -
<data>My Name is Jimmy Buffet &#13;</data>

Additionally, some characters have a more readable syntax. These characters are invalid in XML; so, the
following characters can be encoded in the above format or the following format:

Character Escape Version


< &lt;
> &gt;
& &amp;
' &apos;
" &quot;

Binary array encoding


Arrays can optionally be encoded/decoded as pairs of ASCII-encoded HEX. The pairs of ASCII-
encoded HEX needs to be padded to the size of the data so a 4-byte data value needs to have 4 bytes that
represent it. There are no spaces between pairs, and the default is Big-Endian. Little Endian can be
encoded or decoded as an option. The HEX letters may appear as upper or lower case and are by default
upper case. Any example of a 2-byte (signed or unsigned) array containing the value 1,2,3,4,1,12,13,14
is:

NetLinx Programming Language Reference Guide 219


Appendix A: Marshalling Protocol

<encoded>
<style>BE</ style >
<size>2</size>
<data>010203040B0C0D0E</data>
</encoded>

This is the default type of encoding for non-CHAR arrays but can be used to encode/decode char arrays
as well. The data section must contain BytesSize*Elements nibbles.

220 NetLinx Programming Language Reference Guide


Appendix A: Marshalling Protocol

Binary Encoding Result


Binary Encoding Result
Byte In Encoded String Description
$EC Start of Array Encoding
$00 $00 $00 $03 Number of Elements in the Array
$EA Start of Structure
$E3 DWORD: LONG or SLONG
$00 $A9 $63 $48 Data: 11101000
$E5 Start of CHAR Array (String)
$00 $0D Length of Array: 13
$42 $75 $66 $66 $65 $74 $2C $20 $4A $69 $6D $6D $79 Data: 'Buffet, Jimmy'
$E5 Start of CHAR Array (String)
$00 $1A Length of Array: 26
$4C $69 $76 $69 $6E $67 $20 $26 $20 $44 $79 $69 $6E $67 $20 $69 $6E Data: 'Living & Dying in 3/4 Time'
$20 $33 $2F $34 $20 $54 $69 $6D $65
$E5 Start of CHAR Array (String)
$00 $03 Length of Array: 3
$4D $43 $41 Data: 'MCA'
$E5 Start of CHAR Array (String)
$00 $03 Length of Array: 3
$4D $43 $41 Data: 'MCA'
$E5 Start of CHAR Array (String)
$00 $04 Length of Array: 4
$31 $39 $37 $34 Data: '1974'
$E2 WORD: INTEGER or SINTEGER
$00 $0B Data: 11
$E5 Start of CHAR Array (String)
$00 $0A Length of Array: 10
$33 $31 $33 $32 $33 $33 $33 $34 $33 $35 Data: '3132333435'
$E2 WORD: INTEGER or SINTEGER
$00 $5B Data: 91
$EB End of Structure
$EA Start of Structure
$E3 DWORD: LONG or SLONG
$01 $07 $2F $E5 Data: 17248229
$E5 Start of CHAR Array (String)
$00 $0D Length of Array: 13
$42 $75 $66 $66 $65 $74 $2C $20 $4A $69 $6D $6D $79 Data: 'Buffet, Jimmy'
$E5 Start of CHAR Array (String)
$00 $15 Length of Array: 21
$4F $66 $66 $20 $74 $6F $20 $53 $65 $65 $20 $74 $68 $65 $20 $4C $69 Data: 'Off to See the Lizard'
$7A $61 $72 $64
$E5 Start of CHAR Array (String)
$00 $03 Length of Array: 3
$4D $43 $41 Data: 'MCA'
$E5 Start of CHAR Array (String)

NetLinx Programming Language Reference Guide 221


Appendix A: Marshalling Protocol

Binary Encoding Result (Cont.)


$00 $03 Length of Array: 3
$4D $43 $41 Data: 'MCA'
$E5 Start of CHAR Array (String)
$00 $04 Length of Array: 4
$31 $39 $38 $39 Data: '1989'
$E2 WORD: INTEGER or SINTEGER
$00 $0B Data: 11
$E5 Start of CHAR Array (String)
$00 $0A Length of Array: 10
$33 $31 $33 $32 $33 $33 $33 $34 $33 $36 Data: '3132333436'
$E2 WORD: INTEGER or SINTEGER
$00 $69 Data: 105
$EB End of Structure
$EA Start of Structure
$E3 DWORD: LONG or SLONG
$00 $BC $1E $A4 Data: 12328612
$E5 Start of CHAR Array (String)
$00 $0D Length of Array: 13
$42 $75 $66 $66 $65 $74 $2C $20 $4A $69 $6D $6D $79 Data: 'Buffet, Jimmy'
$E5 Start of CHAR Array (String)
$00 $05 Length of Array: 5
$41 $2D $31 $2D $41 Data: 'A-1-A'
$E5 Start of CHAR Array (String)
$00 $03 Length of Array: 3
$4D $43 $41 Data: 'MCA'
$E5 Start of CHAR Array (String)
$00 $03 Length of Array: 3
$4D $43 $41 Data: 'MCA'
$E5 Start of CHAR Array (String)
$00 $04 Length of Array: 4
$31 $39 $37 $34 Data: '1974'
$E2 WORD: INTEGER or SINTEGER
$00 $0B Data: 11
$E5 Start of CHAR Array (String)
$00 $0A Length of Array: 10
$33 $31 $33 $32 $33 $33 $33 $34 $33 $37 Data: '3132333437'
$E2 WORD: INTEGER or SINTEGER
$00 $BD Data: 189
$EB End of Structure

222 NetLinx Programming Language Reference Guide


Appendix A: Marshalling Protocol

XML Encoding Result


<array>
<curLength>0</curLength>
<struct>
<index>1</index>
<var>
<name>LTITLEID</name>
<data>11101000</data>
</var>
<array>
<name>SARTIST</name>
<curLength>13</curLength>
<string>Buffet, Jimmy</string>
</array>
<array>
<name>STITLE</name>
<curLength>26</curLength>
<string>Living &amp; Dying in 3/4 Time</string>
</array>
<array>
<name>SCOPYRIGHT</name>
<curLength>3</curLength>
<string>MCA</string>
</array>
<array>
<name>SLABEL</name>
<curLength>3</curLength>
<string>MCA</string>
</array>
<array>
<name>SRELEASEDATE</name>
<curLength>4</curLength>
<string>1974</string>
</array>
<var>
<name>NNUMTRACKS</name>
<data>11</data>
</var>
<array>
<name>SCODE</name>
<curLength>10</curLength>
<string>3132333435</string>
</array>
<var>

NetLinx Programming Language Reference Guide 223


Appendix A: Marshalling Protocol

<name>NDISCNUMBER</name>
<data>91</data>
</var>
</struct>
<struct>
<index>2</index>
<var>
<name>LTITLEID</name>
<data>17248229</data>
</var>
....
<var>
<name>NDISCNUMBER</name>
<data>105</data>
</var>
</struct>
<struct>
<index>3</index>
<var>
<name>LTITLEID</name>
<data>12328612</data>
</var>
...
<var>
<name>NDISCNUMBER</name>
<data>189</data>
</var>
</struct>
</array>

224 NetLinx Programming Language Reference Guide


Appendix B: Glossary

Appendix B: Glossary
Array: A single variable that has more than one storage location.
Buffer: An array variable that is associated with a particular device for the purpose of storing
information sent by the device.
Button Event: Include pushes, releases, and holds associated with a push or release on a particular
device-channel.
Calling Parameters: Variables or constants that originate from the caller and are received by the
function or subroutine being invoked
Central Controller: The NetLinx controller (processor) that controls the activities of the NetLinx
system.
Channel: The basic I/O unit in a NetLinx system. It corresponds to single unit of control such as a relay
or an IR signal. The Axcess system supports up to 255 channels per device; the new NetLinx system
will support up to 65,535.
Channel Event: Generated when PULSE, TO, MIN_TO, ON or OFF is called. The CHANNEL object is
available to the channel event handler as a local variable.
Constant: An identifier whose value cannot be changed throughout the entire program.
Data Event: Events associated with a device only; includes commands, strings, status, and error
messages.
Device: A component that has an address and can communicate on the NetLinx bus.
Device array: Specifies a group of DEVs (devices) for a command or event handler.
Device-channel: A reference to a specific device-channel (DEVCHAN) in the NetLinx system.
Device-channel array: Specifies a group of DEVCHANs.
Device-level: A reference to a specific level in the NetLinx system (DEVLEV).
Device-level array: Specifies a group of DEVLEVs.
Device number: A unique number from 1 to 32767 designating each device connected to the NetLinx
bus. The compiler replaces the device number with an internally generated DEV structure. This DEV
structure contains the specified device Number, a value of one (1) for Port indicating the first port, and a
value of zero (0) for System indicating this system (the system that is executing the code).
Device:Port:System (D:P:S): Notation used to explicitly represent a device number, port, and system.
For example, 128:1:0 represents the first port of the device number 128 on this system. The syntax is
NUMBER:PORT:SYSTEM, where the parameters are: NUMBER is a 16-bit integer representing the Device
number, PORT is a 16-bit integer representing the Port number on the device, and SYSTEM is a 16-bit
integer representing the System number.
Event: An activity such as a button push, relay closure, or device status change. Events are received by
NetLinx in the form of messages that are generally acted upon by blocks of code called event handlers.
An event is always associated with a particular device on the bus.
Event Handlers: Blocks of code defined in DEFINE_EVENT for incoming events/notifications. There
are handlers to support five types of events: Button Events, Channel events, Data Events, Level Events,
and Timeline Events.
Expression: Sub-component of a programming statement, such as the conditional portion of an IF
statement or the right-hand side of an arithmetic assignment statement.

NetLinx Programming Language Reference Guide 225


Appendix B: Glossary

Identifier: A combination of letters, numbers, or underscores that represents a device, constant, or


variable.
Index value: Number that tells NetLinx which location in an array to retrieve. This value must be non-
zero and not greater than the maximum length of the declared array.
Input change: A signal sent by the input function of a channel that alerts NetLinx to scan mainline for a
reference to that signal.
Integer: In NetLinx, the range of whole numbers from Ø to 65,535, inclusive.
Integer array: An array where each location can hold a value ranging from Ø to 65,535. Note that an
integer array will take up twice as much NetLinx memory than would a character array of the same
storage capacity.
Keyword: A word or series of words that signifies the operation for NetLinx to execute.
Latching: A defined behavior of status that causes its output channel to stay on or off until activated
once more.
Level: A value that is related to an analog input or output on a NetLinx device.
Level Event: Triggered by a level change on a particular device.
Local variable: A variable declared in a subroutine or function, and whose scope is limited to that
subroutine or function and is static.
Mainline: The portion of a NetLinx program (DEFINE_PROGRAM) that is executed continuously to
service input events and provide feedback to NetLinx devices.
Mutually exclusive set: Only one channel or variable in this set can be on at a time.
Output change: A message to the output function of a channel.
Reserved identifier: An identifier reserved for use by the NetLinx compiler.
Statements: Complete programming instruction such as a calculation, variable assignment, or
subroutine call.
String: A set of values grouped together with single quotes.
String expression: This expression is is enclosed by double quotes and combines several types of data
into a single string.
String literal: A set of ASCII characters (values ranging from 32 to 127) enclosed in single quotes.
Structure: Provides the ability to create a new data type composed of other data types arranged in a
specified order.
Subroutine: A section of code that stands alone and can be called from anywhere else in the program.
System variable: A value kept in the Central Controller that can be referenced by certain keywords.
Timed Wait: A wait request with an associated parameter that indicates that amount of time that must
elapse before the associated wait instruction(s) are to be executed.
Timeout: A defined amount of time during which a device waits for user input until performing a default
action.
Variable: A place to store data that will change as the program is executed.
Volatile Memory: Memory that does not preserve its state when the operating system is rebooted. This
type of memory is typically more plentiful than non-volatile memory. Data variables are stored in non-
volatile memory by default.
Wait list: A list containing unexpired WAIT statements. After each pass through mainline, the Central
Controller scans this list to see if any have come due.

226 NetLinx Programming Language Reference Guide


Appendix B: Glossary

Wildcard character: In NetLinx, the question mark (?) can only be used in a COMPARE_STRING
operation (unlike Axcess, which uses the question mark to compare dates and times).

NetLinx Programming Language Reference Guide 227


Appendix B: Glossary

228 NetLinx Programming Language Reference Guide


Appendix B: Glossary

NetLinx Programming Language Reference Guide 229


It’s Your World - Take Control™

3000 RESEARCH DRIVE, RICHARDSON, TX 75082 USA • 800.222.0193 • 469.624.8000 • 469-624-7153 fax • 800.932.6993 technical support • www.amx.com
033-004-2255 10/06 ©2006 AMX. All rights reserved. AMX and the AMX logo are registered trademarks of AMX. AMX reserves the right to alter specifications without notice at any time.

You might also like