Appendix A SapV2
SapV2 stands for Software Authority Protocol Version 2. It is the glue that provides all the communication between the services insider Pathfinder Core PRO. It is also available for control and troubleshooting purposes on port 9600 for those who wish to take the seriously deep tech dive into Pathfinder Core PRO.
Important Note: Since SapV2 makes up the guts of inter-process communication within Pathfinder Core PRO, it is both incredibly powerful but also incredibly dangerous in the wrong hands. Backups are highly recommended before working with this protocol as it can be used not only to monitor objects but to create and destroy them. For instance, all of the web page user interfaces manipulate the Pathfinder Core PRO configuration using this API; therefore, you can do anything the configuration web pages can do using this protocol. BE CAREFUL!
In order to interact with SapV2, open a telnet session to port 9600 on the Pathfinder Core PRO.
In order to work with the system in any way using the protocol, you first must log in:
Replace the bracketed username and password with a valid user and password.
For example:
Message Overview
SapV2 syntax is based on Axia’s Lwcp specification for syntax, but with some additional features that allow for object and property discovery and listing. As such, the Lwcp documentation can be a useful precursor to reading this appendix.
All messages in SapV2 are case insensitive and end with a carriage return and line feed. Each SapV2 message may consist of an operator, object path, list of properties, and list of system items. The operator and object path are required. For example:
In the message above:
Operator = get
ObjectPath = Devices#0.AnalogNode#[tcp://172.16.1.81:93]
Properties = Name, Description
System Items = $TXID=555
The list of possible operators is listed and described later in this document.
The object path represents branches of a tree like a file system path where the separator between each branch is a period. Each branch consists of the branch type followed by the pound sign and the unique identifier for the branch. In the example above, there are two branches:
Devices#0
AnalogNode#[tcp://172.16.1.81:93]
The branch type of the first branch is Devices and the identifier is 0. The second branch type is AnalogNode and the identifier is [tcp://172.16.1.81:93]. The identifier for the second branch is wrapped in square brackets because the identifier includes symbols that are reserved for object path segregation – namely the period. If a branch identifier includes periods or the pound sign, the identifier must be wrapped in square brackets. Spaces are not allowed within branch identifiers and therefore are not allowed within the object path.
Commas between properties are optional. Commas should not be used between system items.
System items always come at the end of a message and system items all begin with the dollar sign. Therefore, when parsing a SapV2 message, the system item section begins when you encounter an un-escaped space followed by a dollar sign. Since any property value that includes a space must be enclosed in quotes, dollar signs after a space may exist in a property value if they are enclosed in quotes. If a double quote needs to be embedded within a property value, it needs to be escaped with the backslash - \”. If a carriage return and linefeed is to be embedded in the value of a property use the %BeginEncap% %EndEncap% as defined in the Lwcp specification.
For example:
In the example above the property value of Name is:
AAND-001-081 $Hello
The parser does not start parsing the system items when it reaches the space and dollar sign because it is enclosed in quotes as part of the property value. Instead, the system item list begins at $TXID.
In the following example, we needed to include a carriage return and linefeed as part of the value of a property, so we use encapsulation:
In this example, the value of the memory slot will be set to “My Name is Freddy” with a carriage return and linefeed between Is and Freddy. Some properties in the system also accept escape values to represent carriage return and line feed. For example, the generic protocol translator accepts \cr\lf for its ToSend property.
Discovery
Unlike the current version of Lwcp, SapV2 has been designed to extend Lwcp to allow for the discovery for all objects and properties in the system. As in Lwcp, by using the get operator, you can specify an object path and a property and retrieve the property’s value:
However, in SapV2 if you do not specify a property, that means you are requesting a list of all the properties and values that the object has.
Additionally, if you place the object path separator at the end of the object path (the period), it means you are requesting the list of sub objects of the requested object.
In this way, it is possible to walk the tree and discover all objects and properties in the system.
If you wish to know when a list has been completely returned, you can add the $DONE system item.
By using the $DONE system item, the last item in the list carries the $DONE item.
If you only specify the period as the object path then you will get all of the root level objects.
$MAX_DEPTH System item examples
Rather than walking the tree to discover all of the objects, it is also possible to use the $MAX_DEPTH system item to define multiple layers of returned branches at once.
Every branch that is up to two levels beyond the specified object path is returned in this case. If you leave off the ending period, it will return all of the same object paths above but it will also include all of the properties for each object path.
Using the $DONE in addition will return $DONE on the last message item in the list.
The value -1 is special to the Max_Depth system item as it represents infinite. Therefore, using a Max_Depth value of -1 returns everything below the current branch. For example, the following command would return all of the objects at any branch level underneath Devices#0:
This command would return all of the objects and their properties at any branch level underneath Devices#0:
Use the $MAX_DEPTH with some caution as it can take a bit of CPU power to generate some of these large lists. It is better to subscribe to changes of a certain branch and then cache the results of MAX_DEPTH rather than polling large lists.
It is also possible to use a property name with the MAX_DEPTH system item. For example:
Would list every instance of the PinState property that exists below Devices#0.WinDriver#[tcp://172.16.1.254:93] with the $DONE at the end. The response (abbreviated) below might look like:
Note: The example above is abbreviated. This would actually return 120 INDIs (24*5 pins).
Multiple properties may also be returned in which case only objects that contain both properties will be returned. For example:
You can also specify a value in a property and then only items where the property matches that value will be returned.
Subscription Examples
All of the examples above also work with subscriptions. For example:
This will not return anything immediately. Any time any property beneath Devices#0 changes, it will get returned.
If you wanted to subscribe to all GPIO changes you could send:
Init Examples
Most object may also be created and destroyed using the INIT and DEL operators. The arguments required to create an object can be obtained by sending a get command to the object path of an existing object with the special hidden property called Constructor. See Hidden Properties for details.
In this case, the final object in the path does not have an ID associated with it because the constructing parameters will define the ID as part of the construction process. If we were subscribed to MemorySlot changes, we should see the results of this creation returned as a NEW message.
Delete Examples
Objects may be deleted from the system using the DEL operator and an object path. Properties are not valid in a Delete message.
If the connection has subscribed to changes that match this deletion, there will be a response:
The LED operator is the response for a DEL operation but will only be returned if a subscription has been made that matches the deletion object path.
Request for syntax
The RFS operator stands for Request For Syntax and the server will respond with SFR which stands for Syntax For Request. The RFS operator allows you to discover what a specific property expects for its value.
We get a variety of information about the property from this command. We know that the property is read/write, that it expects an option and the valid options are l or h. We know that it is a stable property which means that its syntax should not be expected to change in future versions of PFCore unless carefully noted and/or with backward compatibility handling. We also know that the l or h may be displayed in a more user-friendly fashion in a UI as Low or High. And we know that this property is one that should be displayed in the simple tree of logic flows (IsSimpleUi).
The list of syntax types that will be returned is documented in the RFS/SFR notes later in this document.
Routing Paths
It should be noted that in some places in the system (specifically underneath the Routers#0 root object), object identifiers use a URI type syntax. For example:
Routers#0.AxiaAudioRouter#1.AxiaAudioSource#[tcp://172.16.1.71:93?l=SRC&d=src&i=66&t=aaudio]
This identifier (tcp://172.16.1.71:93?l=SRC&d=src&i=66&t=aaudio) is called a PathIo and uniquely identifies an IO in the system. It may be broken up into its relative pieces as follows:
tcp://172.16.1.71:93: This is the uri of the ip address and port of the device on which the IO was discovered.
l=SRC: This stands for Level and could contain SRC, DST, GPI, GPO
d=src: This stands for Direction. This seems redundant to level but it is not. This defines whether the IO is a source or destination irrespective of whether it is a GPIO
i=66: This is the IO port identifier as reported by the equipment
t=aaudio: This is the type of IO which could include
aaudio: AxiaAudio
agpio: AxiaGpio
virt: Virtual
Operators
Each operator is comprised of up to 8 characters and are always terminated by a trailing whitespace.
SET: Request to update information on the system.
GET: Request for information from the system.
INDI: Indication that information on the system has changed.
SUB: Request to receive indications from an object path on the system when changes occur.
UNSUB: Request to stop receiving indications from an object path on the system.
RFS: Request for property formats of an object on the system.
SFR: Response to property format requests.
INIT: Request to create a new object.
NEW: Response message for a successful init if subscribed.
DEL: Deletes an object from the system.
LED: Response message operator for a delete message if subscribed.
NOP: No operation.
SYNC: Used to pass a message for cluster synchronization purposes.
LOGIN: Login to the system.
ACK: Acknowledgement from the system to a request tagged with the $ACK system item.
PUB*: Request to anchor the object path or paths.
UNPUB*: Request to un-anchor the object path, or paths.
ATCH*: Attaches to an object (macro for SUB then PUB on the object).
ATTACH*: Weak alias for ATCH.
HELP*: Request for helpful information about an object or property.
LINK*: Request to create a link between an object and a host object.
UNLINK*: Request to remove a link between an object and a host object.
* For Future use. Not currently implemented.
Untargetted Operators
There are a couple of operators that break the rules about requiring an object path. These operators stand on their own as complete commands:
LOGOUT: Logout of the system.
EXIT: Request that the system breaks the current connection.
QUIT: Alias for Exit.
Operator Examples
LOGIN
LOGIN {username} {password}
Example:
Returns:
GET
GET {Object}.{Object} {Property}
Example:
Object may be a specific object. Object may be terminated with a full stop (.), which indicates that a listing of all descendent Objects is being requested.
Object may be terminated with a pound sign (#), which indicates that a listing of all objects matching that type is being requested. * * For Future use. Not currently implemented.
Property may not be specified, in which case it is a request for all of the properties for that object.
Important Note: Objects are often returned in alphabetical order to make them easier to read and/or use in a user interface. However, it takes extra CPU power to organize the return list alphabetically. For faster response times and lower CPU impact, the $UNSORTED system item may be used.
SET
SET {Object}.{Object} {Property}={Value},{Property}={Value}
Sets a property value in the system. Use RFS to determine what the property expects and whether it is writable.
Example:
Note: A SET will only respond with a change message if there is a subscription active that meets the bounds of the change.
INDI
INDI {Object}.{Object} {Property}={Value}
This is a response from the server for a get command or for a change that is within the bounds of a subscription request.
Example:
SUB
SUB {Object}.{Object} {Property}
Subscriptions can be to an Object Path, an Object, or a Property. $MAX_DEPTH may also be used to subscribe to property changes at different depths.
Example:
INIT
INIT {Object}.{Object} {ConstructorProperty}={Value} {ConstructorProperty}={Value} ...
Creates an object which is defined as initable within the system.
Example:
DEL
DEL {Object}.{Object}
Deletes an object which may be removed from the system.
Example:
NOP
NOP {Object}.{Object}
This operator stands for No Operation. The rest of this message should be ignored, but it should still be structured as a valid SAPv2 Message. This can be used in configuration files that store SapMessages and essentially will act like remarking out the message. This allows you to leave the message in the file for future use. The system will read and parse the message, but will not act upon it.
Example:
SYNC
Sync {Object}.{Object} Property
This operator stands for Synchronize. It is used exclusively for internal clustering synchronization messages.
Example:
RFS and SFR
RFS {Object}.{Object} {Property}
SFR {Object}.{Object} {Property}=[{Read/Write},{Syntax},{DirectSubscriptionOnly},{IsStable},{SyntaxUsage}],{Property}=[...]
RFS is a request for syntax request and SFR is the server’s response.
Example:
The SFR response may carry multiple pieces of information about the property including:
Read/Write Values
RO: Read Only
WO: Write Only
RW: Read and Write
Syntax Values
BOL[[true,TRUE,t,1],[false,FALSE,f,0]]: Boolean value with True and False specifics
ENU[Value,Value,Value(Display)]: Enumeration
LST[Separator,Syntax Type]: List
TBL[Header,Header,Header,Header,Header]: Table
NUM[Minimum,Maximum,Increments]: Numeric value
TXT[Restrictions]: Text value with Restrictions on what type of text
BIN: Binary value
HEX: Hexadecimal value
BMP: Bitmap value
PNG: Portable Network Graphics value
URI: Uniform Resource Indicator value
IsSimpleUi: True or False
IsStable: True or False
Notes on RFS implementation.
Plain Text: SyntaxType=TXT
Boolean: SyntaxType=BOL
Number: SyntaxType=NUM
Number range
SyntaxType=NUM[<Miniumum>,<Maximum>,<increment>]
SyntaxType=NUM(1,10,1)
Enum
SyntaxType=ENU[value(display),value(display),value(display)] *
IP Address: SyntaxType=TXT[Ip]
Netmask: SyntaxType=TXT[IpNetmask]
Mulicast IP: SyntaxType=TXT[IpMcast]
StaticOptionList
SyntaxType=OPT[Single:optvalue(display),optvalue(display)] *
MultiSelectStaticOptionList
SyntaxType=OPT[Multi:optvalue(display),optvalue(display)] *
StaticSapOptionList SyntaxType=OPT[SapSingle:(sapPathForList),valueProperty,displayproperty] *
StaticSapOptionList
SyntaxType=OPT[SapMulti:(sapPathForList),valueProperty,displayproperty] *
DateTime: SyntaxType=TIM
Color: SyntaxType=COL
Vb6 OLE Style Color: SyntaxType=OLE
URL: SyntaxType=URI
*display is optional - if not present uses the optvalue
Note1: Syntax types with options have the option data (shown in the outer []) expressed in the syntaxUsage field of SapProperty Attribute. Note2: ENU and StaticOptionList are really the same except the values in ENU must be numbers. Note3: If the SapSingle is used with an object path of .. , the .. refers to the object path 1 level up from the current object level (example if the property is on an object and the path to that object is devices#0.powerstation#0.lwcpinterpreter#0, .. means devices#0.powerstation#0. Note4: If the SapSingle is used with an object path of @ , the @ refers to the property object’s current object path.
Object Path
{ObjectType}#{ObjectId}.{ObjectType}#{ObjectId}.{ObjectType}#{ObjectId} . . .
An Object path is comprised of a list of branches similar to a folder structure where the period is used as the separator. Each Branch is comprised of a type and an Id separated by the pound sign.
Example:
Devices#0.WinDriver#[tcp://172.16.1.254:93].LwrpInterpreter#0.LwrpRoot#0.Gpo#6.GpioPinState#4
If the id contains any characters that are reserved for the path architecture (. or #), the id must be enclosed in square brackets. Spaces are not allowed in object paths.
Properties
Property Names may not include spaces and must not begin with the dollar sign. The equals sign with no spaces is used between the property and its value where a value is relevant to the command usage.
Lwrp STAT Properties
This version includes data obtained from the STAT command in Lwrp for devices that support it. These read-only properties may be found in the API tree in logic flows under the device branch that supports it.
There are four types of STAT objects described below:
Important Note: Stat Sync data collection is not enabled by default as this process generates a lot of data, especially in systems with large numbers of xNodes. To enable stat sync data collection for a given device, use the API on port 9600 and send the command:
Also note that while turning the SubscribeToSync option on for a device will be saved between restarts, the state is not currently cluster synchronized.
Because the API matches the object layout of the device’s Lwrp protocol some of the new settings can be found in a variety of places. The new paths include:
LwrpInterpreter#0.LwrpRoot#0.Decoder# LwrpInterpreter#0.LwrpRoot#0.Encoder#
LwrpInterpreter#0.LwrpRoot#0.Cfg#0.Enc# LwrpInterpreter#0.LwrpRoot#0.Cfg#0.Dec#
For example, the destination properties for a decoder or encoder are available via the LwrpRoot#0.Cfg#0.Enc and LwrpRoot#0.Cfg#0.Dec paths whereas the encoder algorithm and bitrate settings are available via the LwrpRoot#0.Encoder and LwrpRoot#0.Decoder paths.
IPort Control
The LwrpRoot#0.Cfg#0.GPIO path controls whether the GPIO ports are enabled or disabled in the system. The actual GPIO port may or may not be present depending on whether the encoder or decoder are active. All of these paths are available for use in Logic Flows via the API tree, however, some are read-only and so will only appear when using a start point.
To figure out which properties match config options in the Iport UI, open a TCP connection to PathfinderCore PRO using Putty to port 9600 and subscribe to changes on the device in question.
Then you can make changes in the IPort’s UI and see the changed properties in Pathfinder Core PRO. This can be useful to see where certain properties are located in the API tree.
Hidden Properties
The Constructor property will return Init messages required to recreate an object that supports that property. However, it will not show up in the general list of properties for an object. It must be queried directly.
Property Values
If the property value is to include a space, it must be surrounded by quotes.
If the property value is to include a carriage return and/or line feed, it must be encapsulated using %BeginEncap%%EndEncap%.
If a double quote needs to be included in the value, it needs to be escaped using the backslash.
System Items
$ACK: Request Acknowledgement to Operation.
$TRXID/$TRXI/$TXID: Transaction ID to track response to Operation.
$IND/$INDI: Request Indication from SET without needing a subscription.
$DONE: Requests that the DONE system item be applied to the last message returned from a request.
$PROPATTR: Specifies that the properties in the GET/RFS messages are Syntax Format properties - such as getting all properties that are Readwrite=RO.
$OP: Operation. Used in ACK Operation responses to denote the Operation that was sent with the $ACK System Item. Also used in Subscription operations where you want to specify only messages with a specific operator. For example DEL or LED messages. (eg. sub MemorySlots#0 $MAX_DEPTH=-1 $OP=LED).
$MAX_DEPTH: Used to specify the Depth of the subscription or return. -1 equals all object paths below the request.
$UNSORTED: Return messages do not need to be sorted for easier readability. Used when querying large lists where order does not matter.
$CONTAINS_PROP: Indicates a request for objects that contain the specific property. If the message ends with an object separator (.) then it will just return objects. Otherwise, it will return all properties of the objects that include the requested property. This is not valid for subscription messages. It is only valid for Get. Please note that this can cause heavy CPU load as it requires walking the object tree and iterating all properties in each object. Use sparingly and cautiously.
$EXCLUDE_PROPS: Exclude certain properties from the return.
$SHOW_CLUSTER: Certain objects related to clustering are hidden and not returned in subscription and get responses unless this system item is included
$CLUSTER_CHANGES: Subscribe to only changes that are related to cluster synchronization. Returns will carry this as well.
$CLUSTER_QUIET: This has special meaning to Set and Init messages. It means the message is the result of a Change on another server and is being set to keep in sync. And therefore the change should not be broadcast to other servers that have subscribed to cluster changes to prevent numerous duplicate messages.
$LAST_UPDATE: Used in conjunction with $CLUSTER_CHANGES to show the date/time stamp of the most recent update.
$INCLUDE_MOUNTS: This will also follow and include mount points from an object to a mounted object. For example, from a route point to the mounted device IO. It applies to Get, Set, and Sub operator. Mount points are currently used sparingly within PathfinderCore PRO so this option is only useful in some situations.
$STATUS*: Response status code
$COUNT*: Request for number of objects below the current object path
$DEPTH*: Request for an operation to be iterated to a specified depth. Default is 1, and a non-positive integer depth will result in infinite depth.
$TSTAMP: Timestamp. Timestamp returns only for subscribed (SUB) objects. It is not returned by the "GET" operator and is not saved as a property of an object. Currently implemented for the Audio Alarm AlarmState= property. Other use of this is limited and not widely used.
* For Future use. Not currently implemented.
Additional System Item Notes
$PROPATTR is the system item for Property Attribute. It can equal AND or OR.
$PROPATTR=AND <Default> $PROPATTR=OR
If this attribute is set it means that the properties defined in the property list of the Get/RFS message are not literal properties. Rather, they are requesting objects that have properties that have formats described in the property list.
For example:
The pipe allows listing multiple options for a format value. The And/OR in the PropAttr defines whether a match is made if either of them matches or only if all match when multiple properties exist in the message.
Last updated