Syruslang

Language to quickly interface with the device and generate events/messages to your server

Intro)

Syrus IoT Telematics Gateway can be programmed with a proprietary language called Syruslang.

With Syruslang you can create custom definitions to quickly interface with the device and its internal components (network, inputs/outputs, accelerometer, gnss, etc) in order to customize the Syrus' reporting behavior.

The custom definitions are part of a Smart Event Engine which constantly evaluate conditions.

For example configurations checkout our Github Repo.

Quick 5 minute introduction presentation that goes over the main points of this documentation.

What is SyrusJS?

Syruslang runs on an embedded application inside the Syrus 4 called SyrusJS which manages a syruslang configuration file and all of its definitions.

Within SyrusJS there's a directory that holds the device's configuration and important files, the location of this directory is also referred to as the application data directory: /data/app_data/<INSTANCE_NAME>/.

The important files to consider within this directory are:

FilenameDescription
appends.syrus.confAny remote command definition sent to the device (automatically generated).
configuration.syrus.confDevice's main configuration file.
destinations.syrus.confDevice's destination definitions.

Comments within any of the filenames above can be written with # in front of the line with the comment.

# comment
define command
# >!@#% this is another comment

The Syrus Cloud Applications can be used to manage the files within SyrusJS and create your own script.

Configuration access

Via shell you can edit the configuration using an editor like vi or tail logs.

  • Logs directory: /data/logs
  • Application data: /data/app_data/<INSTANCE_NAME>

Please note that the logs file rotates every hour and if the size is greater than 30KB then it will be compressed. Maximum of 8 log files are created.

The system tool syrus-apps-manager can be used to interact with the application itself (start, stop, restart).

syrus-apps-manager restart syrusjs

Definitions

There are 3 main definitions that control what we call the Smart Event Engine of the device.

  1. Signals
  2. Actions
  3. Events

With these 3 definitions you can create thresholds, and trigger messages to be sent to a destination, or actions to be executed locally on the device.
It all starts by creating the definitions.

Create

In order to create a definition you have to start a new line with define followed by the name of the definition you want to create:

define *definition* custom_name

As you create the definitions you assign a unique custom_name to each one. Be aware that the naming must follow these rules:

  • are case-sensitive
  • 3 to 25 characters
  • only underscore is allowed as a special character _
  • cannot be special keywords like: and, or, not, exec, apx, group
  • [a-zA-Z_][a-zA-Z0-9_]{2,24}

There is no limit as to how many definitions you can create, but keep in mind that no two definitions can share the same custom_name.

🚧

Warning

Using the same definition and custom_name will overwrite the original definition

❌ define signal my_signal ... <- original
βœ… define signal my_signal ... <- this will overwrite the original my_signal definition

πŸ‘

Tip

Giving definitions similar names can lead to confusion, it's a good practice to use prefix when creating definitions.

βœ… define signal sg_nameofsignal
βœ… define event ev_nameofevent
βœ… define action ac_nameofaction

Definitions can span multiple lines

define signal sg_my_signal
    min_duration=10sec $io.ign == true

define event ev_my_event
    label=custom code=10
    ack=seq group=tracking
    trigger=sg_my_signal

Evaluation

The event engine is evaluated in the order mentioned above, first with signals, then the actions and finally the events.
This is important because you may have a signal that fires an action that triggers an event, and you need to keep in mind which one is going to trigger first.

Manipulation

Definitions can be deleted with the delete keyword, followed by the definition and its name:

delete *definition* custom_name

❗️

Definition deletion

Deleting a definition affects what's associated to that definition, for example, if you delete a signal it means any events or actions that depend on that signal will not fire.

Event Engine

The unit's reporting is controlled by an Event Engine which constantly evaluates user definitions.
The 3 main definitions are signals, actions, and events.

  • Signals: used to evaluate when you want something to happen (i.e. when the input is pressed, or when the speed is above a certain value)
  • Actions: used to fire a specific task once a signal is met (i.e. activate an output or make a call)
  • Events: used to notify an endpoint once a signal is met (i.e. generate a message to send to the server to indicate that the panic was pressed)

Signals

The main component of Syruslang is the definition of signals.
There are two types of signals:

  1. fixed signals - built-in device signals, start with @ symbol (momentarily true)
  2. custom signals - custom created signals that require an operator and value (persistently true)

These two types of signals are evaluated constantly for changes and when they are 'true' they'll trigger the signal thereby triggering an action or event as we'll see later.

Signal states

Fixed signals are also known as transitory signals because they are true momentarily, while custom user defined signals are true indefinitely until another signal or action changes its state.

To create a signal you have to use the following format (values with [] mean they're optional):

define signal signal_name
	[min_duration] $device_component [operator] [value]

Signal definition example:

# signal for persistent Ignition Is ON
define signal sg_ignitionIsOn $io.ign == true

We can add a persistence and rewrite the == true part, as this is the default evaluation. So the signal definition above can also be rewritten to:

define signal sg_ignitionIsOn 
	  min_duration=10sec $io.ign

# signal sg_ignitionIsOn will be true after 10 seconds of $io.ign detection

Once defined, a signal can be used to trigger actions, events, or both.

The state of the signal, whether it's true or not can be accessed with a get signal_value command.

get signal_value SIGNAL

If we were to look at the signal earlier defined we would notice it return true.

However if we were to do this with a fixed-signal it will always be false because it's only true momentarily.

get signal_value sg_ignitionIsOn
true 

# we can send this command using syrus-apps-manager

$ syrus-apps-manager send-message __cloud_syrusjs "get signal_value sg_ignitionIsOn"
true

# if we were try this with a fixed signal, like a timer signal, it will return false because it's only true momentarily
$ syrus-apps-manager send-message __cloud_syrusjs "get signal_value @timers.my_timer"
false

πŸ“˜

Units

Unless otherwise specified, Syruslang will follow the basic units of the metric system for time, distance, and speed (seconds, meters, and km/h, respectively).

Breakdown of the signal definition:

min_duration

The minimum duration that the condition (made up of the $device_component, operator, and value) must be met in order for the signal to transition to true. It has the following format, #A where # is any number and A represents the time unit:

  • sec - seconds
  • min - minutes
  • hr - hours

a min_duration=10sec for example, means that the condition must be met for 10 consecutive seconds, before the signal transitions to true.

$device_component

Device components refer to the internal modules and interfaces that the device is capable of interacting with. The device components section has a list of the available signals that can be constructed with each internal module/interface.

$gnss.speed
$net_wifi.ip_address
$net_cell.connected
$accelerometer.motion

operators

The operators supported are:

==  >  <  >=  <=  !=

value

The value varies depending on the field selected, can be bool, string, or a number.

Example of Signal Definitions

define signal ignitionON min_duration=5sec $io.ign
define signal ignitionOFF min_duration=5sec $io.ign == false
define signal speeding min_duration=2sec $gnss.mph > 70
define signal parked min_duration=10sec $accelerometer.motion == false
define signal buzzer $io.out2
define signal siren $io.out3
define signal usa_country_code $net_cell.mcc == 310
define signal att_network_code $net_cell.mnc == 410 
define signal slow
	min_duration=10sec $gnss.kph < 10
define signal work_wifi
	$net_wifi.ip_address == 123.123.123.123

Trigger (Signal Combination)

Various signals can be combined to form a combination of several situations that can trigger an event or an action.

The parameter trigger is used to create an equation using signals and logical operators: and, or, not, in a post fixed notation syntax.
Post-fixed notation means that the signals are placed first, and the operator is at the end of the signals to be evaluated, the signals and the operators are separated by a comma.

Examples

A or B β†’ A,B,or

A and B β†’ A,B,and

A and B and C β†’ A,B,and,C,and
same as..
A and B and C β†’ A,B,C,and,and

(A and B) or C β†’ A,B,and,C,or

A and (!B or C) β†’ A,B,not,C,or,and

(A and B) or (C and D) β†’ A,B,and,C,D,and,or

thus you can combine the signals defined previously like this:

# idling
ignitionON,parked,and

# attached to AT&T in US
usa_country_code,att_network_code,and

# not moving
ignitionON,parked,slow,or,and,ignitionOFF,or

# parked at the office
ignitionOFF,work_wifi,and

As mentioned above, the signals can be combined in actions and events.

Keep in mind that when you define a trigger for the first time, if all the signals within the trigger are true, the trigger will evaluate and fire.

Next we will look at how to define an action.


Actions

Actions can be defined to tell the device what to do when a trigger goes off. They have the following format:

define action action_name [rate] trigger=signal1[,signal2,operator,...] command

πŸ‘

Multiple actions

Multiple actions can be fired from a single trigger by separating each action with a new line and tab

define action action_name trigger=signal1[,signal2,operator,...]
	command1
	command2

define action ac_my_action trigger=signal1
	set out1 on
	set out2 on
	start recording

rate

Similar to the rates of an event, actions can have their own rates in order to avoid executing excess number of actions.
The format for rates is A/Bunit where A is the amount of fires to allow, and Bunit is the time frame to allow it for. The possible units are sec, min, hr.

For example a rate of 1/2hr allows only 1 fire every 2 hours. After the 2 hours complete the rate is reset back to 0 and the unit can fire once more in the span of 2 hours.

πŸ‘

Recommendation to use rates

Rates are very useful for actions that have to do with voice alerts, as these can get annoying really quick, unless of course that's your goal

command

The command that can be executed can be found in the device components section, as action use

Action definition example:

define action speedingBuzzer trigger=speeding set out2 on

πŸ‘

Substitue true & false for on & off

You can substitute == true and == false for the words on & off respectively

define action enable_hotspot 
    trigger=work_wifi,ignitionOFF,and set out2 on

πŸ‘

Execute system tool commands

You can execute any system tool command with the exec keyword.

standalone:

exec apx-wifi add --ssid=mynet --pass=mypass --priority=5

or as part of an action

define action ac_restart_gps trigger=no_gps exec apx-gps warm-start

Events

Events can be triggered by the same signals as an action and they can be used to notify an endpoint when a condition is met.
When an event is triggered it follows this sequence of steps:

  1. Creates a message according to the protocol on the events destination definition
  2. Appends any additional fields to the payload via the fieldsets
  3. Queues the payload on a data buffer (FIFO) per endpoint defined
  4. Attempts to communicate with the endpoints in order to remove the payload from its queue
  5. Depending on the Acknowldgement configured it either waits for a confirmation from the endpoint or moves on to the next event in queue.
  6. If no response from the endpoint is received the messages are retried in increasing timeouts, after 5sec, 10sec, 30sec, 60sec, etc. til it reaches 1min and keeps retrying every 1min.

The event definition format is as follow:

define event event_name group 
    [fieldset] [rate] [ack] 
    [label] [code] [photo] 
    trigger=signal1[,signal2,and,...]
paramdescriptiondefault value
groupis a way to group several events for destination handlingdefault
fieldsetrefers to the additional information that can be attached to an event besides the location information, we'll look at this in more detail later
raterefers to a firing limit for this event
ackrefers to the acknowledgement message that's used by an endpoint to handle the correct reception of the event, for mqtt endpoints this is the equivalent of QoSseq
retainset to false to disable the retain message flag for mqtt destinationstrue
labelrefers to a short string, up to 10 characters (alphanumeric, period [.] accepted), that's used to identify the event generated on an endpoint using syrus3g protocoltrckpnt
codeis a numeric code for the event generated (range: 0, 9999), useful for syrus3g protocol messages0
photowhether the event will have a photo associated to itfalse
videovariable with a video id attached to ithe event
triggerare the signals that we defined earlier that can be combined with logical operators.

Event definition examples:

define event movement group=default 
	fieldset=minimum rate=5/1min ack=disabled 
	label=trckpnt code=1 trigger=moving

define event ignition_on group=tracking 
	fieldset=default ack=seq 
	label=ignon code=2 
	trigger=ignitionON

define event speeding_70 group=alerts 
	fieldset=important ack=seq 
	label=spd code=3 
	trigger=speeding

define event parked group=default 
	fieldset=minimum rate=2/1hr ack=disabled 
	label=park code=4 
	trigger=isON,slow,and,nomov,and

Event Grouping (group)

Groups can be defined in order to get multiple events reporting to the same destination.

The first step is to define a group:

define group group_name

Once defined you can append this group_name to any event and later on apply fieldsets or destinations to that group of events.

To relate the group to a destination use the following command:

set destinations group=group_name destination_name1[,destination_name2]

Example, if we have the following events defined:

define event ignition_is_on group=important ack=seq label=ignon trigger=ignitionON
define event ignition_is_off group=important ack=seq label=ignoff trigger=ignitionOFF
define event panic_and_parked group=important ack=seq label=panic trigger=panic,parked,and
define event speeding_70 group=important ack=seq label=spd trigger=speeding

the first 3 events we can direct towards the main_server and the backup server with:

set destinations group=important main_server,backup

the 4th event falls in the default group so those can be directed to just the main_server for example:

set destinations group=default main_server

Thus, the destination file will depend on the groups of events defined in your configuration.syrus.conf.
Note, if an event has no destination set it will simply be discarded.

Fieldset

Fieldsets are data fields that can be appended to the payload of an event.

Start by defining a fieldset

# fieldset definition my_fields
define fieldset my_fields fields=field1,field2,etc..

Then you can use it on any event

# appends my_fields to my_event
define event my_event fieldset=my_fields ...

The fields come from the device components section, look for fieldset use.

To define or transform fieldset values & sets:

VALUES

fields=$battery.voltage

{
	"$battery": {
		"voltage": 4.1
	}
}

fields="foo":$battery.voltage or fields=foo:$battery.voltage

{
	"foo": 4.095
}

fields=foo.bar:$battery.voltage

{
	"foo": {
		"bar": 4.098
	}
}

SETS

fields=$battery

{
	"$battery": {
		"connected": true,
		"voltage": 4.098,
		"mv": 4098,
		"level": 100
	}
}

fields="foo":$battery

{
	"foo.connected": true,
	"foo.voltage": 4.098,
	"foo.mv": 4098,
	"foo.level": 100
}

fields=bar:$battery

{
	"bar": {
		"connected": true,
		"voltage": 4.098,
		"mv": 4098,
		"level": 100
	}
}

fields=foo.bar:$battery

{
	"foo": {
		"bar": {
			"connected": true,
			"voltage": 4.098,
			"mv": 4098,
			"level": 100
		}
	}
}

Example:

fields=position.context.lat:$gnss.latitude,position.context.lng:$gnss.longitude,position.value:$gnss.fix

{
	"position": {
		"context": {
			"lat": 25.783618,
			"lng": -80.293516
		}
	},
	"value": 3
}

For TAIP protocol, you just need to define a csv of all the compatible sets from device components.

Example:

define fieldset taip_pegasus fields=$gnss,$io,$net_cell,$ecu,$accelerometer

SyrusJS will automatically fill those fields with the appropriate subfields for TAIP messages.

🚧

One fieldset per destination

Make sure to define one fieldset per destination you create.

# group definitions
define group tracking
define group bluetooth

# fieldset definitions
define fieldset default fields=$gnss,$io
define fieldset btdata fields=$ecu,$net_eth

# event definitions
define event braking group=tracking ack=seq fieldset=default [email protected]_braking.signal
define event movement group=bluetooth ack=seq fieldset=btdata [email protected]

# groups destinations
set destinations group=tracking destination_peg1
set destinations group=bluetooth bt_event_destination
# multiple destinations

define destination destination_peg1 taip tcp://pegasus1.peginstances.com:5001

define destination bt_event_destination json bluetooth://_:_ ack=disabled

Rate

The rates are used to avoid firing an event in excess by limiting the amount of fires an event can have within a period of time.
The format for rates is A/Bunit where A is the amount of fires to allow, and Bunit is the time frame to allow it for. The possible units are sec, min, hr.

For example a rate of 5/1min allows only 5 fires of the event in the span of 1 minute. After the minute completes the rates are reset to 0 and the unit can fire 5 times again in the span of 1 min.

πŸ’‘Tip: This is very useful for events that have to do with physical connections like inputs, analog values, ignition, because these are proned to installation failures which can lead to multiple false fires

Label

Labels are important for TAIP protocol, when sending the data to Pegasus for example. They are used to identify an event. Labels must follow these guidelines:

  • 1 to 10 characters
  • letters can only be lowercased
  • only period . is allowed as a special character
  • cannot have consecutive periods
  • [a-z0-9.]{1,10}
  • can have the same name as a definition

Photo

The photo parameter is used to associate a photo to an event. When a compatible accessory is connected, like a fatigue_sensor, you can associate any photo captured or a specific photo captured with this.

Destinations

Destinations are the the endpoints where the data generated by the device will be reported, they are saved in a separate file called: destinations.syrus.conf within the app directory /data/app_data/syrusjs/

To define a destination:

define destination name protocol transport:endpoint[?args] [allowed_] [ack] [disabled]

name

Name is the custom name given to the destination, can be up to 50 alphanumeric characters.

protocol

The protocol refers to the data format that the payload is transmitted in:

  • json
  • taip (Syrus 3 format used for Pegasus platform)
  • csv used for file type destinations

transport

Transport refers to the method of transportation of the data, the following methods are supported:

  • mqtt
  • tcp
  • http/https
  • file
  • serial
  • satcom
  • bluetooth

MQTT Protocol Support on Syruslang

MQTT 3.1.1MQTT 5.0SSL/TLSTCPWS/WSSQoS
YesYesYesYesYes0,1,2

More information about MQTT

endpoint

The endpoint refers to the destination of the data, it can be various formats depending on the transport, for now given the transports defined earlier, the following are supported:

mqtt, tcp, http[s]:

://url[:port]

://ip_address[:port]

file

:///path/to/file.log

satcom, serial

://_:_

bluetooth

://_:_ - endpoint for S4GBT Destination Point (used for broadcasting)
://apps:_ - endpoint for S4GBT User Application Console (allows acknowledgement of messages)

Note that you can use variables in the endpoint from the components section by adding it inside two curly brackets {{}}:

Examples:

://url.com/syrus/{{$modem.imei}}

Protocol, Transport, Endpoint Support Matrix

The following table shows a relationship between the supported protocols for each transport method and their destination

transportsupported protocol(s)endpoint
mqttjson, taipmqtt://test.mosquitto.org:1883
tcptaiptcp://iot.yoursite.com:1234
http/httpjson, taip<https://yoursite.com/device/listener>
filejson, taip, csvfile:///media/mmcblk0p1/logs.csv
serialtaipserial://_:_
satcomtaipsatcom://_:_
bluetoothjsonbluetooth://_:_
bluetoothtaipbluetooth://apps:_

?args

The optional ?args refers to params that can be appended to the endpoint.

  • ?ssid=value&pass=pass1

allowed_

The connection to this destination will only be available when the specified network is within range/connectable. Outside of the allowed interfaces the destination will queue all messages until it's available again.

valuedescription
allowed_ssidwhen connected to a specific wireless network ssid
allowed_ipwhen connected to a specific ip_address
allowed_interfacewhen connected to one or many of these network interfaces wifi, eth, cell

Example:

# This connection will only allow messages sent via wifi inteface once it's connected/in range.  Any other interface that's used will queue the messages.
define destination mqtt_broker json mqtt://test.mosquitto.org:1883 protocol="mqtt" subscribe="dev/messagestx" publish="dev/messagestx" allowed_interface=wifi
# This example will only send messages when it's connected via ethernet, cellular network or a specific ssid
define destination server json tcp://test.server.com allowed_interface="eth,cell" ssid="Linksys Home Router"

ack

Configure the message acknowledgement to be used by a destination:

transportack supporteddetails
mqttβœ…ack supported using QoS
tcpβœ…ack supported via taip protocol
http🚫no ack support
https🚫no ack support
file🚫no ack support
serial🚫no ack support
satcom🚫no ack support
bluetoothβœ…seq/imei ack supported via bluetooth://apps:_ destination endpoint

See the Message Acknowledgement and Queues section for more information on the specific ack configurations.

disabled

Disables the endpoint, this is useful if you want to control it via an action, for Satcom/Sigfox destinations for example.

define destination satcom_destination taip satcom://_:_ ack=disabled disabled=true

The commands to enable and disable the destination are:

enable destination name
or
disable destination name

and some sample actions:

define action enable_satcom trigger=disconnected enable destination satcom_destination

define action disable_satcom trigger=disconnected,not disable destination satcom_destination

Useful for the satcom destination

MQTT

MQTT can be used as a destination transport method, for a full tutorial that incorporates mqtt checkout this walkthrough.
The following parameters are available when creating a destination definition for an MQTT endpoint:

paramdescriptionexample
cleanindicate whether or not a persistent session is required (set to false to keep a persistent session)false
clientIdclient identifier"client-1"
keepalivekeep alive period to maintain a connection open with broker60
lastWillPayloadmessage to send when client disconnects ungracefully"unexpected exit"
lastWillQoSlast will quality of service1
lastWillRetainwhether or not to retain the last will messagetrue
lastWillTopiclast will topic"dev/imei/connect/status"
usernameusername for client authentication"user"
passwordpassword for client authentication"pass"
protocolused to define the transport method and security, see below for protocol list"mqtts"
publishtopic to publish event messages"dev/imei/events"
commands_pubtopic to publish command responses"dev/imei/commands/resp"
subscribe or commands_subtopic that handles syruslang commands"dev/imei/commands"

Note that only one topic to publish event messages can be set per definition, but you can have multiple definitions with different topics.

Other parameters like the QoS & retain of each message are handled in the events definition.

methodportprotocolsecure
mqtt over tcp1883mqttno
mqtt over tls8883mqttsyes
mqtt websockets80wsno
mqtt websockets over tls443wssyes

Example MQTT endpoints

define destination mqtt_over_tcp json mqtt://mqtt.pegasusgateway.com:1883 protocol="mqtt" publish="dev/{{$modem.imei}}/pub" subscribe="dev/{{$modem.imei}}/sub" commands_pub="dev/{{$modem.imei}}/commands"
define destination mqtt_over_tcp_ssl json mqtt://mqtt.pegasusgateway.com:8883 protocol="mqtts" publish="dev/{{$modem.imei}}/pub" subscribe="dev/{{$modem.imei}}/sub" commands_pub="dev/{{$modem.imei}}/commands"
define destination mqtt_over_ws json mqtt://mqtt.pegasusgateway.com:80 protocol="ws" publish="dev/{{$modem.imei}}/pub" subscribe="dev/{{$modem.imei}}/sub" commands_pub="dev/{{$modem.imei}}/commands"
define destination mqtt_over_wss json mqtt://mqtt.pegasusgateway.com:443 protocol="wss" publish="dev/{{$modem.imei}}/pub" subscribe="dev/{{$modem.imei}}/sub" commands_pub="dev/{{$modem.imei}}/commands"

MQTT to conect with AWS IoT Core

Parameters to add in the destinations.syrus.conf file :

paramdescriptionexample
hostAWS endpoint in the format *-iot.region.amazonaws.com"aws://abc123-unique.iot.us-east-1.amazonaws.com:8883"
client_idThe id of the created device"syrus-867698041103352"
key_namePrivate key file name (usually ends with private.key)"nodejs_demo_thing.private.key"
cert_nameCertification file name (usually ends with .pem)"nodejs_demo_thing.cert.pem"
ca_nameRoot Certificate Authority file name (usually ends with .pem) - Can be Downloaded from AWS as RootCA.pem"AWSRootCA1.pem"
publishOutput topic, events will be sent to this topic"events/pub"
subscribesubscribe"events/sub"
commands_sub (optional)Input topic, this recieves from aws (used for commands)"commands/sub"
commands_pub (optional)Output topic, this send the command response"commands/pub"
Example
define destination awsmqtt json aws://abc123-unique.iot.us-east-1.amazonaws.com:8883 client_id="syrus-867698041103352" publish="events/pub" subscribe="events/sub" commands_pub="commands/pub" commands_sub="commands/sub" key_name="nodejs_demo_thing.private.key" cert_name="nodejs_demo_thing.cert.pem" ca_name="AWSRootCA1.pem"

HTTP(S)

When creating an http endpoint you can use the following notation to append headers: headers.HEADER_NAME=VALUE

# endpoint with application/json content-type
define destination my_endpoint json http://api.mysite.com/devices headers.content-type="application/json"

# endpoint with authorization and content-type
define destination other_endpoint json https://api.mysite.io/devices headers.authorization="Bearer XXXXXXXXX" headers.content-type="application/json"

Message acknowledgement and queues

Once an event is generated the device stores it in a queue per endpoint that the event is sent to.
Any event in queue is transmitted to the endpoint every second as long as a connection is established.

If the endpoint requires internet connection, there's 3 possibilities to reach it:

  1. Ethernet
  2. Wi-Fi
  3. Cellular (4G/LTE)

The data traffic by default is sent in that order of priority, with Ethernet being the preferred method.

By default SyrusJS uses the TCP stack to guarantee message delivery, however under special circumstances it's recommended to implement an application level ACK, this is where the ack param comes in.

The ack param of the event verifies if Syrus is expecting any sort of response from the endpoint indicating that it received the event.

protocol & transportackformat of ACK Syrus expectsexample
taip over tcpdisablednone
taip over tcpimei15 digit modem's IMEI867698040023056
taip over tcpseq>SAK;1,#,0,0< where # is the sequential ACK number generated by Syrus>SAK;1,1234,0,0

for MQTT the ack controls the QoS and retain flags of the MQTT specification

protocol & transportackQoSretain
json over mqttdisabled0false
json over mqttseq2true

# event messages and server responses depending on ACK

# ack=disabled
>>> (device sends) >REV012235381799-3345819-0706246800034232;...;ID=123457050627122<
<<< (server responds)
>>> (device sends) >REV022235381800-3345819-0706246800034232;...;ID=123457050627122<
<<< (server responds)

# ack = imei
>>> (device sends) >REV012235381799-3345819-0706246800034232;...;SA=0,0;ID=123457050627122<
<<< (server responds) 123457050627122
>>> (device sends) >REV022235381800-3345819-0706246800034232;...;SA=0,0;ID=123457050627122<

# ack = seq
>>> (device sends) >REV012235381799-3345819-0706246800034232;...;SA=1,0;ID=123457050627122<
<<< (server responds) >SAK;1,0,0,0<
>>> (device sends) >REV022235381800-3345819-0706246800034232;...;SA=1,1;ID=123457050627122<
<<< (server responds) >SAK;1,1,0,0<  

ack considerations

When seq ack is enabled, Syrus expects the same ID that the Syrus sent in the server's response in order to send the next message, otherwise the events are added to a queue. This is the general functionality of the ACK, however there are a couple of exceptions of messages that are not pushed to the events queue and instead respond immediately:

  1. Handshake - the connection message that Syrus sends to the server
    1. (device sends) >RXART;23.13.1;EG25S;model=Syrus 4 LTE,...;ID=123457050627122<
    2. (server responds) 123457050627122
    3. These messages need to be acknowledged with an IMEI
  2. Commands - any command that is sent to the device does not require an ACK and is responded immediately
    1. (device receives) >QPV<
    2. (device responds) >RPV68440+2099027-0897187900000432;ID=867698041103352<
    3. an optional send id (SI) in the format ;SI=1-#### (where #### can be an alphanumeric identifier) can be sent with the command to identify the command sent
    4. (device receives) >QPV;SI=1-0<
    5. (device responds) >RPV68440+2099027-0897187900000432;SI=1-0;ID=867698041103352<

Note that the sequential ID restarts after 32,000 so it should be treated as an ID for confirmation purposes since this number can also reset if the device has an app re-installed.

Maximum queue size

SyrusJS uses Redis and the device's filesystem to store event messages that have not been transmitted to an endpoint.
The maximum number of possible messages stored is equivalent to the amount of memory available in the user's storage partition, this partition is roughly 2.2GB and can be monitored in the Syrus 4 UI system page, divided by the size of the messages. Typical message sizes for TAIP can vary between 50 bytes to 500 bytes depending on the accessory, while MQTT can vary from a few bytes up to 5KB.

Clearing destination queues with TAIP ack

To clear a taip destination queue you can send the command >SRT;SFBUFF< using the send-message command.

$ syrus-apps-manager send-message __cloud_syrusjs '>SRT;SFBUFF<'

🚧

HTTP Errors

In the output/error logs you may get a message: ECONNABORTED. This is a disconnection message that means that the Syrus abruptly cut the communication with the remote server. It could be due to several reasons, for example:

  • Exceeded maximum timeout
  • Network congestion / loss of coverage

Logging to a file

A destination can also be a path to a file, this can be used to log data in any of the protocols defined above. By default, file destinations use the log rotation tool to automatically rotate the file that's being logged according by size and/or amount of days.

The format to create the file destination is:

define destination NAME PROTOCOL file:///PATH ACK ROTATE SIZE COMPRESS

The possible parameters to configure when defining a file destination are:

paramdescription
NAMEName of the destination
PROTOCOLjson, taip, or csv protocols
PATHpath to where the logs will be saved; specify the name of the file with an optional extension name, also note that this can be a path on the local file system or an external SD card that's mounted on the Syrus. Be sure to format the SD card before using it to log data
ACKleave as disabled for file type destinations
ROTATErotation duration, format NT - where N is a number, and T is a duration (D - days, W - weeks, M - months)
SIZEmax file size before the file is rotated (optional)
COMPRESSset to true to enable compression of the files once they are rotated (optional)
HEADERSFile headers, ex: 'timestamp, date_time, event_label, event_code,gnss_timestamp, speed, latitude, etc. Requires apx-logrotate v1.1.0 or the latest apex release (23.51.1). The order must be as in the fieldset definition. The headers can be defined explicitly in the destination file or can be added automatically (auto_headers = true).

*Note: if the file destination does not exist a new one is created, but if the file does exist already it will be overwritten!*

Example destination definition:

define destination logger csv file:///data/app_data/syrusjs/output.csv ack=disabled rotate=5D size=10MB compress=true headers=timestamp,date_time

Once the log starts you can use a command like zip to download the file to make sure it's capturing the correct data.

# zip the output file into the /data/logs folder
# format: zip DESTINATION_PATH SOURCE_FILE
$ zip /data/logs/output.zip /data/logs/output.csv

# then download the file using Syrus Cloud
download-file /data/logs/output.zip

For more information on the signals and fieldsets possible when logging data check out the blackbox section.

Interaction with serial port

You can use the serial port as a destination for the events you generate.

# define a group for sending events over the serial port
define group serial_msg

# define an event that triggers when the input is activated
define event input_active group=serial_destination fieldset=default code=90 [email protected]

# set the group to a destination
set destinations group=serial_msg serial_destination

# Set the destination to the serial port
define destination serial_destination taip serial://_._ ack=disabled
  
# The serial port will then receive the >REV event message
# See Syrus 3 Protocol section for more information

You can send commands over the serial port while in console mode.

# Enable the serial console mode
apx-serial set --mode=console

# Then you can send taip commands and get responses
>QPV<

You can send a command/message from a remote destination such as Pegasus over the serial port

>STXsomedata<
  
# the serial port will receive 
"somedata"

Remote interaction

Depending on the protocol and transport of the destination you defined, you can interact with the device remotely.

If you are using JSON over MQTT you can publish commands to a topic from your remote message broker on your destination definition.

By default SyrusJS will be connected to the topic defined by the params subscribe or commands_sub using QoS = 1.

Once a message (command) is received SyrusJS will publish to the topic commands_pub using QoS = 1 and retain = true.

Thus, to send commands remotely to the Syrus over MQTT you can publish messages to the commands_sub topic.

You can send an action, define something, or retrieve data remotely.

# activate output 2
set out2 on
OK

# define a new definition
define signal signal_name ...
OK

# get a list of all signals
get signals
define signal ignOn $io.ign == true, define signal isIdle ...

πŸ“˜

Remote definitions

Note that any definition that you configure remotely to the device will be appended to a file called appends.syrus.conf on the application's data folder

Commands to retrieve data, definitions, or values

definitionsdescription
get action custom_namereturns action definition of custom_name
get actionsreturns all action definitions
get counter custom_namereturns counter definition of custom_name
get countersreturns all counters definitions
get destination_state custom_namereturns enable if destination is used
get destination custom_namereturns destination definition of custom_name
get destinationsreturns all destinations definitions
get event custom_namereturns event definition of custom_name
get eventsreturns all events definitions
get fieldset custom_namereturns fieldset definition of custom_name
get fieldsetsreturns all fieldsets definitions
get geofence custom_namereturns geofence definition of custom_name
get geofencesreturns all geofences definitions
get group custom_namereturns group definition of custom_name
get groupsreturns all groups definitions
get signal custom_namereturns signal definition of custom_name
get signalsreturns all signals definitions
get signalvalue _signal_namereturns the value of the signal
get value $device.componentreturns the value of the device component

Note that if you're using the TAIP protocol, you'll need to encapsulate the message within the SL (SyrusLang) command: >SSLmessage<, the response will have the following format: >RSLresponse<

And if you want to send a system tool command you need to send a keyword exec: >SSLexec APX_COMMAND<

Examples:

# Get fieldset definition
>SSLget fieldset default<
>RSLdefine fieldset default fields="device_id":$modem.imei,"latitude":$gnss.latitude,"longitude":$gnss.longitude,"direction":$gnss.heading,"hdop":$gnss.hdop,"pdop":$gnss.pdop,"vdop":$gnss.vdop,"mph":$gnss.mph,"io_in1":$io.in1,"io_in2":$io.in2,"io_in3":$io.in3,"io_out1":$io.out1,"io_out2":$io.out2,"io_ign":$io.ign,"io_pwr":$io.pwr<

# Get signal value
>SSLget value $net_wifi.ip_address<
>RSL192.168.1.205<

# Define signal
>SSLdefine signal sg_custom $io.in1<
>RSLOK<

# Action enable hotspot
>SSLenable hotspot<
>RSLOK<

# Send output activation
>SSSXP21<

# Execute apx system tools
>SSLexec apx-geofences add places parks circular country_village_park 100 -80.305340,25.943784<

πŸ“˜

Keep track of commands sent

You can use a Send ID to keep track of the commands sent, just append ;SI=1-XXX after the command you want to send and the Syrus will reply with that message appended. XXX can be any alphanumeric value.

(device receives) >SSLexec apx-io set OUT2 true;SI=1-0;ID=123698041103352<
(device responds) >RSLOK;SI=1-0;ID=123698041103352<

(device receives) >SSLget value $net_wifi.ip_address;SI=1-1;ID=123698041103352<
(device responds) >RSL192.168.1.89;SI=1-1;ID=123698041103352<

Features

Accelerometer

Actions and Signals List

The accelerometer allows you to configure the signals related to driving including collision and aggressive driving behavior.
To get accurate results you must first calibrate the accelerometer once the device is properly installed in a vehicle, you can visit the CONNECT page for more info.

Set

You can calibrate the accelerometer with the following command

set accelerometer self_alignment

and set individual thresholds with

set accelerometer CFG_FORWARD_COLLISION -2500
set accelerometer CFG_BACKWARD_COLLISION 2150
set accelerometer CFG_LAT_COLLISION_FROM_RIGHT -1930
set accelerometer CFG_LAT_COLLISION_FROM_LEFT 1930
set accelerometer CFG_HARSH_FWD_ACCELERATION 300
set accelerometer CFG_HARD_BRAKING -250
set accelerometer CFG_CORNERING_RIGHT -590
set accelerometer CFG_CORNERING_LEFT 430

Get

Get the values of a single parameter or all accelerometer parameters

get accelerometer forward_collision
get accelerometer all

Signal

The available signals for the accelerometer are:

SignalDescription
@accelerometer.forward_collision.signalTrue when a forward collision is detected
@accelerometer.backward_collision.signalTrue when a backward collision is detected
@accelerometer.lat_collision_from_right.signalTrue when a collision from the right was detected
@accelerometer.lat_collision_from_left.signalTrue when a collision from the left was detected
@accelerometer.harsh_fwd_acceleration.signalTrue when a harsh acceleration was detected
@accelerometer.hard_braking.signalTrue when a sudden braking was detected
@accelerometer.cornering_right.signalTrue when hard cornering to the right was detected
@accelerometer.cornering_left.signalTrue when hard cornering to the left was detected

Fieldset

You can append the actual g-force value and the exact time that the accelerometer signal was triggered with

$accelerometer.ACCELEROMETER_EVENT.value - appends the force in milli-g when the accelerometer event was triggered

$accelerometer.ACCELEROMETER_EVENT.time - appends the timestamp of when the accelerometer event was triggered (YYYY-MM-DDTHH:mm:ss.sssZ)

define fieldset default fields=$accelerometer.hard_braking.value,"time_of_hardbraking":$accelerometer.hard_braking.time
{
  ...
  "accelerometer.hard_braking.value": -340,
  "time_of_hardbraking": "2020-07-03T19:59:43.140Z"
}

IMU

Actions and Signals List

Define backlogs of accelerations with different signals. The acceleration backlog can be downloaded and analyzed.

# Generate an accel backlog using signals from adas

define action ac_accel_backlog 
[email protected]_collision_warning
exec apx-imu backlog create --name=FCW_{{$gnss.timestamp}}

ADAS

Actions and Signals List

ADAS is an accessory that allows you to obtain advanced information about the behavior of drivers on the road.
It communicates via the ECU monitor or serial port.

Signals

The following table describes the list of signals and states available with the specific ADAS accessory you connect:

Comparison of Signals and Accessory

DescriptionStatesMovon MDAS-9 SignalMobileye Signal
Brakes detecting$ecu.brakes_enabledβœ…βœ…
FailSafe (Error state) detection$ecu.failsafeβœ…βœ…
Forward collision warning detection$ecu.forward_collision_warningβœ…βœ…
Headway measurement (in meters)$ecu.distance_from_front_vehicleβœ…πŸš«
Headway measurement (in seconds)$ecu.headway_measurementβœ…βœ…
Headway valid (boolean)$ecu.headway_validβœ…βœ…
Left and right signals$ecu.left_signal & $ecu.right_signalβœ…βœ…
Left lane departure warning$ecu.left_lane_departure_warningβœ…βœ…
Low and high beams detection$ecu.low_beam_signal & $ecu.high_beam_signalπŸš«βœ…
Parked (zero speed) detection$ecu.zero_speedβœ…βœ…
Pedestrian forward collision warning$ecu.pedestrian_forward_collision_warningβœ…βœ…
Pedestrian in danger zone$ecu.pedestrian_danger_zoneβœ…βœ…
Relative speed from the edefront of vehicle$ecu.relative_speed_from_front_vehicleβœ…πŸš«
Right lane departure warning$ecu.right_lane_departure_warningβœ…βœ…
Speed limit recognition$ecu.speed_availableβœ…βœ…
Tamper detection$ecu.tamper_alertβœ…πŸš«
Time indicator$ecu.time_indicatorπŸš«βœ…
Wipers detection$ecu.wipers_signalπŸš«βœ…
Connected state boolean$adas.connectedβœ…πŸš«
Connected state string [connected, disconnected]$adas.stateβœ…πŸš«
The event arrived as shown in the signals$adas.eventβœ…πŸš«
Event state [ready, recognized]$adas.event_stateβœ…πŸš«
Triggered when the vehicle passes the left lane@adas.left_lane_departure_warningβœ…πŸš«
Triggered when the vehicle passes the right lane@adas.right_lane_departure_warningβœ…πŸš«
Speed [km/h]$adas.speedβœ…πŸš«
Motor revolutions per minute [rpm]$adas.rpmβœ…πŸš«
Distance to objects on the left [cm]$adas.left_distanceβœ…πŸš«
Distance to objects on the right [cm]$adas.right_distanceβœ…πŸš«
Time to front collision [s]$adas.time_to_collisionβœ…πŸš«
Recording state$adas.recordβœ…πŸš«
Triggered when any adas event arrives@adas.eventβœ…πŸš«
Triggered when brakes are pressed@adas.brakeβœ…πŸš«
Triggered when the vehicle passes the left lane@adas.left_lane_departure_warningβœ…πŸš«
Triggered when the vehicle passes the right lane@adas.right_lane_departure_warningβœ…πŸš«
Triggered when the vehicle breaks the safety distance@adas.safety_distance_alertβœ…πŸš«
Triggered when the front vehicle starts to move@adas.front_vehicle_start_alarmβœ…πŸš«
Triggered when the vehicle slowly approaches to front car@adas.front_proximity_warningβœ…πŸš«
Triggered when a pedestrian is detected@adas.pedestrian_collision_warningβœ…πŸš«
Triggered on left turn@adas.left_turnβœ…πŸš«
Triggered on the right turn@adas.right_turnβœ…πŸš«
Triggered when the camera is blocked@adas.camera_blockedβœ…πŸš«
Triggered when low visibility is detected@adas.low_visibilityβœ…πŸš«

For a complete list of signals head to the Device Components Library. This section goes into details on specific signals.

$ecu.failsafe

True if the adas accessory triggers any of the following failsafe modes: blurred image, saturated image, low sun, partial blockage, or partial transparent.

$ecu.headway_warning_levelDescription
0When no CIPV (Close in path vehicle) is present
1When a CIPV is present with Headway Warning > Headway Warning configured
2When a CIPV is present with Headway Warning <= Headway Warning configured
3When a CIPV is present with Headway Warning < 0.6
$ecu.time_indicatorDescription
0Day
1Dusk
2Night
$ecu.traffic_signs_recognition_warning_levelDescription
0Speed <= road speed
1Speed > road speed + [0 - 5 km/h]
2Speed > road speed + [5 - 10 km/h]
3Speed > road speed + [10 - 15 km/h]
4Speed > road speed + [15 - 20 km/h]
5Speed > road speed + [20 - 25 km/h]
6Speed > road speed + [25 - 30 km/h]
7Speed > road speed + [30 - 35 km/h]
8Speed > road speed + 35 km/h
$ecu.sound_typeDescription
0Silent
1Lane departure warning Left
2Lane departure warning Right
3Headway warning 1
4Traffic sign recognition
5Urban forward collision warning
6Forward collision warning + Pedestrian collision warning
# Forward collision warning detected 
define signal fcw $ecu.forward_collision_warning

# Night signal
define signal night_time $ecu.time_indicator == 2

# FCW at night event
define event fcw_at_night group=tracking fieldset=default ack=seq label=fcwnight trigger=fcw,night_time,and
Examples of movon9 adas signals definitions

define signal sg_adas_connected $adas.connected == true

define signal sg_adas_disconnected $adas.connected == false

define event ev_adas_any group=tracking fieldset=default ack=seq label=any code=10 [email protected]

define event ev_left_lane group=tracking fieldset=default ack=seq label=left_lane code=11 [email protected]_lane_departure_warning

define event ev_right_lane group=tracking fieldset=default ack=seq label=right_lane code=12 [email protected]_lane_departure_warning

define event ev_distance_alert group=tracking fieldset=default ack=seq label=safety_distance code=13 [email protected]_distance_alert

define event ev_front_vehicle group=tracking fieldset=default ack=seq label=front_vehicle code=14 [email protected]_vehicle_start_alarm

define event ev_front_proximity group=tracking fieldset=default ack=seq label=proximity code=15 [email protected]_proximity_warning

define event ev_forward_warning group=tracking fieldset=default ack=seq label=collision code=16 [email protected]_collision_warning

define event ev_pedestrian_warning group=tracking fieldset=default ack=seq label=pedestrian code=17 [email protected]_collision_warning

define event ev_left_turn group=tracking fieldset=default ack=seq label=left_turn code=18 [email protected]_turn

define event ev_right_turn group=tracking fieldset=default ack=seq label=right_turn code=19 [email protected]_turn

define event ev_brake group=tracking fieldset=default ack=seq label=brake code=20 [email protected]

Blackbox

Actions and Signals List

The blackbox feature allows you to save data to a file periodically. It is enabled automatically for any destination file definition. For information on how to configure the destination file see Logging to a file.

Once you create the definition in your destinations file you're ready to start saving data to it.

πŸ“˜

$MEDIA_PATH and USER_PATH

Note that you can use $MEDIA_PATH or $USER_PATH to indicate /media/mmcblk0p1 or /data/users/syrus4g

For example, if you want to log data second by second to a file on an SD card and have that file automatically compress and rotate after 1 week you can use a destination like:

define destination gps_data csv file://$MEDIA_PATH/gps_data.csv ack=disabled rotate=1D

and a configuration file with:

# create a group for logging
define group blackbox

# create a fieldset to append data to the csv
define fieldset csvfields fields=gnss_timestamp:$gnss.timestamp,
	speed:$speed,
	acceleration:$gnss.acceleration.value,
	latitude:$gnss.latitude,
	longitude:$gnss.longitude,
	heading:$gnss.heading,
	bearing:$gnss.bearing,
	altitude:$gnss.altitude,
	fix:$gnss.fix,
	sats_active:$gnss.satsActive,
	accuracy:$gnss.accuracy,
	hdop:$gnss.hdop,
	vdop:$gnss.vdop,
	pdop:$gnss.pdop,
	power:$io.pwr,
	ignition:$io.ign,
	input1:$io.in1,
	$ecu.fef4,

# signals for detection of ignition
define signal sg_ignON $io.ign 
define signal sg_ignOFF $io.ign == false

# create a timer every second
define timer tm_csv duration=1sec enabled=true repeat=true

# timer conditions to start and stop based on ignition state
define action ev_startlog trigger=sg_ignON start timer tm_csv
define action ev_stoplog trigger=sg_ignOFF stop timer tm_csv

# event that's generated and saved to the file
define event ev_writelog group=blackbox fieldset=csvfields rate=1/1sec label=blackbox code=88 [email protected]_csv,sg_ignON,and

# log the events from group logs to the destination
set destinations group=blackbox gps_data

This will create files with the following format: NAME-YYYYMMDD.gz where NAME is the destination file name, so in this case gps_data.csv and YYYYMMDD is year, month, and date, example: 20220621. Note that the first file is created at midnight for the previous day.

In the previous example, logs will be created for up to 5 days and then the oldest file is rotated out.

syrus4g@syrus-867698040023056 /media/sd_card
-rwxrwxrwx    1 root     plugdev   228.9K Jun 18 00:00 gps_data.csv-20220617.gz
-rwxrwxrwx    1 root     plugdev   164.7K Jun 19 00:00 gps_data.csv-20220618.gz
-rwxrwxrwx    1 root     plugdev   175.2K Jun 20 00:00 gps_data.csv-20220619.gz
-rwxrwxrwx    1 root     plugdev   175.3K Jun 21 00:00 gps_data.csv-20220620.gz
-rwxrwxrwx    1 root     plugdev   175.4K Jun 22 00:00 gps_data.csv-20220621.gz
-rwxrwxrwx    1 root     plugdev     7.9M Jun 22 19:04 gps_data.csv

Once the files are generated you can use the download file feature in SyrusCloud to download the logs remotely at any time.

Blackbox Database

This feature creates an SQL database to backup relevant information second by second. Lets the user retrieve 10-minute segments of that information and send it to the requested destination point. Offers additional backup for crash scenarios where the physical evidence may be extracted as an SD Card. Gives an easy way to access and copy the black-box data.

Instructions

  1. Define a new database destination indicating the path to the database and the desired protocol. In this example, the database will be created in the root of the SD. If you want to save the database inside a folder, you need to create the folder manually.
define destination database_taip taip apx-db:///media/mmcblk0p1/blackbox.db
  1. Define any number of fieldsets to be stored in the database and set a timer to write every second.
# -- Group and fieldsets
define group blackbox
define fieldset default fields=$io,$gnss,$net,$ecu

# -- Signals
define signal sg_ign_on $io.ign 

# -- Timer
define timer tm_bbox duration=1sec enabled=true repeat=true

# -- Events
define event ev_write_db group=blackbox fieldset=default label=bbox code=90 [email protected]_bbox,sg_ign_on,and

# -- Destinations
set destinations group=blackbox database_taip

To retrieve a range of the stored information use one of the following methods:

Use the Pegasus QDB command in the following format.

# -- Format >QDB{protocol},{destination},{from_epoch},{to_epoch}<
>QDBjson,pegasus,1708700962,1708701562<

Send the following command from cloud, selecting the protocol and destination to send.

syrus-apps-manager send-message __cloud_syrusjs_instance "upload blackbox protocol=taip destination=my_server from=1708963644 to=1708963654"

Use the apx-db tool to read the interval or send it to a file for download, make sure to enter the path of the database and use the desired protocol as the table argument.

# -- To send the result to a file add the ' > filename.txt' to the end of the following script 
sudo apx-db read --database=/media/mmcblk0p1/storage/blackbox.db --table=taip --from=1708700962 --to=1708701562

Restrictions

  • Due to memory size only use an external SDcard to store the database.
  • Limited to one month 24h second by second recording or 2.5 Million registers per protocol.
  • The retrieval range is limited to 10 minutes.
  • Make sure to upgrade to Apex v24.08.1 or superior.

Bluetooth

Actions and Signals List

Bluetooth allows you to pair and connect to a bluetooth speakerphone that support HFP bluetooth profiles only. Other bluetooth profile variations like JL-HFP, or HSP.HFP are not supported at the moment.

Scan and pair a bluetooth speakerphone with the apx-bt system tool.
You can also use the Pegasus command console if you have access to it, simply write: >SSL followed by the bluetooth command

commanddescription
bluetooth scan secondsScans for this amount of seconds
bluetooth pair 'AABBCCDDEEFF'Pair to a bluetooth device
bluetooth pairforced '_AABBCCDDEEFF'Force pairing
bluetooth unpair 'AABBCCDDEEFF'Unpair from bluetooth device
bluetooth connect 'AABBCCDDEEFF'Connect to bluetooth device
bluetooth disconnect 'AABBCCDDEEFF'Disconnect from bluetooth device
bluetooth switchaudio '_AABBCCDDEEFF'Switch main audio
bluetooth restart 'AABBCCDDEEFF'Restart bluetooth
bluetooth reset 'AABBCCDDEEFF'πŸ›‘ Resets bluetooth paired devices
>SSLbluetooth scan 15<
>SSLbluetooth connect 'AABBCCDDEEFF'<
command resultsdescription
bluetooth info 'AABBCCDDEEFF'Shows bluetooth info
bluetooth infoall '_AABBCCDDEEFF'Shows all info
bluetooth listdiscovered '_AABBCCDDEEFF'Shows list of discovered
bluetooth listpaired '_AABBCCDDEEFF'Shows list of paired
bluetooth listconnected '_AABBCCDDEEFF'Shows list of connected
>SSLbluetooth list_discovered<
>RSL{"FC65DE2040E1":"Echo Show-1SN","7C6456A13E51":"[TV] Samsung Frame (43)","A0E6F8D3A66E":"Syrus 3GBT 05949"}<

Note that not all bluetooth devices that are discovered can be connected to for audio purposes, some bluetooth devices are connectable, but would not reproduce audio, check the bluetooth profile.

Actions

A possible action may be to connect to a separate speaker when you reach home

define action switch_bluetooth trigger=inside_home bluetooth connect '7C6456A13E51'

or force switch audio whenever the ignition turns on

define action force_audio trigger=ignition_on bluetooth switch_audio 'FC65DE2040E1'

Bluetooth Destinations

Bluetooth destinations can be defined to either broadcast messages to the S4GBT Destination Point characteristic or communicate with the user application console S4GBT User Application Console.

The main difference between the two is that the Destination Point characteristic only allows for messages to be notified, while the User application console allows you to write and read to that characteristic giving you the possibility of acknowledging messages.

Destination Point Characteristic

A sample configuration file (configuration.syrus.conf) may look like the following:

# create a group for bluetooth 
define group bluetooth

# fieldset for json message
define fieldset default fields=$gnss,$io

# create event definition
define event movement group=bluetooth ack=disabled fieldset=default [email protected]

# set destination to bluetooth endpoint
set destinations group=bluetooth bt_event_destination

A sample destinations file (destinations.syrus.conf) may look like the following:

# bluetooth destination
define destination bt_event_destination json bluetooth://_:_ ack=disabled

In the above scenario the movement event will be generated and sent to the S4GBT Destination Point characteristic.

User Application Characteristic

This configuration allows you to enable acknowledgement for event messages allowing you to queue and de-queue once your application receives an event notification.

Note that only taip protocol can be used for message acknowledgement.
A sample configuration file (configuration.syrus.conf) may look like the following:

# create a group for bluetooth 
define group bluetooth

# create fieldset for taip messages
define fieldset default fields=$gnss,$io

# create event definition
define event movement group=bluetooth ack=seq fieldset=default [email protected]

# set destination to bluetooth endpoint
set destinations group=bluetooth bt_apps_destination

A sample destinations file (destinations.syrus.conf) may look like the following:

# bluetooth destination
define destination bt_apps_destination taip bluetooth://apps:_ ack=seq

In the above scenario the movement event will be generated and sent to the S4GBT User Application characteristic, the message will continue to be resent until it's ACK, see acknowledgement section for more info.

Bluetooth sensors

Actions and Signals List

Once you have configured a bluetooth BLE sensor, you can trigger signals and detect states in the following way:

Signals

FieldsDescription
@ble.eventTriggered at any ble event
@ble.(MAC or ALIAS).temperature.changeTriggered when a change in temperature is detected

States

FieldsDescription
$ble.(MAC_ADDRESS or ALIAS).macDevice mac address
$ble.(MAC_ADDRESS or ALIAS).nameAdvertised name
$ble.(MAC_ADDRESS or ALIAS).aliasAssigned alias
$ble.(MAC_ADDRESS or ALIAS).timestampScanned time
$ble.(MAC_ADDRESS or ALIAS).temperatureReported temperature value in degrees celsius
$ble.(MAC_ADDRESS or ALIAS).humidityReported humidity value in percentage
$ble.(MAC_ADDRESS or ALIAS).movementReported number of movements detected
$ble.(MAC_ADDRESS or ALIAS).rpmReported rpm value [revolutions per minute]
$ble.(MAC_ADDRESS or ALIAS).batteryReported battery value [%]

The next script send events when detect a change in the temperature

# -- Variables definitions
define variable movement
set variable movement 0

define variable temperature
set variable temperature 0

# -- Fieldsets - add $ble to enable taip  or json fieldset
define fieldset default fields=$io,$ble

# -- Signals - Used prevously defined alias "Kitchen"
define signal sg_hightemp $ble.Kitchen.temperature > 20
define signal sg_lowtemp  $ble.Kitchen.temperature <= 20
define signal sg_movement $ble.E7973F682A94.movement > {{$variables.movement}}

# -- Events - trigger only used on the action
define event ev_hightemp group=tracking ack=seq label=hitemp code=70 fieldset=tracking
define event ev_lowtemp group=tracking ack=seq label=lotemp code=71 fieldset=tracking
define event ev_tmpchg group=tracking ack=seq label=tmpchng code=73 fieldset=tracking
define event ev_movement group=tracking ack=seq label=mvnt code=74 fieldset=tracking

# -- Actions
define action ac_hightemp trigger=sg_hightemp
  set variable temperature {{$ble.Kitchen.temperature}}
  send event ev_hightemp
  speak "High temperature detected at {{$variables.temperature}}"

define action ac_lowtemp trigger=sg_lowtemp
  set variable temperature {{$ble.Kitchen.temperature}}
  send event ev_lowtemp
  speak "Low temperature detected at {{$variables.temperature}}"

define action ac_tempchng [email protected]
  set variable temperature {{$ble.Kitchen.temperature}}
  send event ev_tmpchg
  speak "Temperature change to {{$variables.temperature}}"

define action ac_movement trigger=sg_movement
  set variable movement {{$ble.E7973F682A94.movement}}
  send event ev_movement
  speak "Movement detected at {{$variables.movement}}"

Blazon Drum Rotation BLE Sensor

# - Signals
define signal sg_stopped $ble.BlazonDRS.rpm == 0
define signal sg_mixing $ble.BlazonDRS.rpm > 0
define signal sg_pouring $ble.BlazonDRS.rpm < 0
define signal sg_lowbat $ble.BlazonDRS.battery < 20
define signal sg_fullbat $ble.BlazonDRS.battery > 90
define signal sg_hightemp $ble.BlazonDRS.temperature > 30
define signal sg_lowtemp $ble.BlazonDRS.temperature < 10

# - Events
# trigger when the BlazonDRS is stopped
define event ev_stop group=tracking fieldset=default label=stop code=70 trigger=sg_stopped

# trigger when the BlazonDRS is mixing
define event event ev_mixing group=tracking fieldset=default label=mixing code=71 trigger=sg_mixing

# trigger when the BlazonDRS is pouring
define event ev_pouring group=tracking fieldset=default label=pouring code=72 trigger=sg_pouring

# trigger when the BlazonDRS has low battery (< 20)
define event ev_lowbat group=tracking fieldset=default label=lowbat code=73 trigger=sg_lowbat

# trigger when the BlazonDRS has full battery (> 90)
define event ev_fullbat group=tracking fieldset=default label=fullbat code=74 trigger=sg_fullbat

# trigger when the BlazonDRS has high temperature (> 30)
define event ev_hightemp group=tracking fieldset=default label=hightemp code=75 trigger=sg_hightemp

# trigger when the BlazonDRS has low temperature (< 10)
define event ev_lowtemp group=tracking fieldset=default label=lowtemp code=76 trigger=sg_lowtemp

Counters and Timers

Actions and Signals List

Syrus supports configuring many counters for different use cases, here's a breakdown:

Counter TypeDescriptionUse Case
Metric countersCounts of common metricsCount the total odometer, hourmeter, speeding time, etc.
Signal countersCounts, durations, and distances of signalsCount the total occurrences, duration, or distance while a signal is active
TimersCreate one-shot or repeated timersCreate timers for a specified amount of time that can be delayed or repeat and take actions when it reaches a specified time
VariablesDefine custom valuesDefine variables that increase and decreased based on your criteria and take actions when it reaches a value
Tracking ResolutionTime, distance, and heading periodic reportsCreate a tracking criteria that will report periodically when it reaches a specified distance, time, or heading change

Metric counters

Syrus has built-in metric counters that include counts for common metrics such as:

  • Total Distance Traveled
  • Total Ignition ON Time
  • Total Time While Idling
  • Total Time Overspeeding
  • etc...

To create a metric counter use:
define counters name

This automatically creates an internal count of the following fields.

FieldDescription
odometerTotal distance traveled with ignition ON (meters)
ignition_timeTotal ignition time (seconds)
idle_timeTotal time spent in idling (seconds)
over_speedTotal time spent over speed (seconds)
over_rpmTotal time spent over RPMs (seconds)
hard_brakesTotal amount of hard brake events (count)
harsh_fwd_accelerationTotal amount of harsh forward acceleration events (count)
distanceTotal distance traveled with ignition ON or OFF (meters)

Initializing
By default, these fields start at 0 but can be initialized from any value on the first time it's defined.

define counters name [odometer] [ignition_time] [idle_time] [over_speed] [over_rpm] [hard_brakes] [harsh_fwd_acceleration] [distance]

🚧

Initialize counters

Note that once counters are initialized they can't be modified with the same definition.

# initialize counters
define counters globals odometer=0 
   ignition_time=0 
   idle_time=0 
   over_speed=0 
   over_rpm=0 
   hard_brakes=0 
   harsh_fwd_acceleration=0

to modify use the set commands

# modify thresholds
set counters globals speed_threshold=80
set counters globals begin_idle_time=15min
set counters globals rpm_threshold=1600

Thresholds
The speed, rpm and idling times are controlled by the following threshold values:

FieldDefault thresholdDescription
speed_threshold50Default units: km/h. The over_speed counter will increase for every second the device is above this speed
rpm_threshold3000Default units: rpm. The over_rpm counter will increase for every second the device is above this rpm
begin_idle_time5Default units: minutes. The idle_time counter begins to increase after (no movement detected AND ignition ON) for longer than the begin_idle_time - this time is in minutes.

You can obtain the values using the following signals:

Signals
$counters.globals.odometer
$counters.globals.ignition_time
$counters.globals.idle_time
$counters.globals.over_speed
$counters.globals.over_rpm

Reporting built-in counters

# built-in counters for "driver1"
define counters driver1 odometer=50925

# fieldset for driver1
define fieldset driver_1 fields=
	distance:$counters.driver1.odometer,
	ignition:$counters.driver1.ignition_time

If you're using TAIP you must use the following fieldset:

define fieldset default fields=$io, 
	VO:$counters.globals.odometer,
	CE:$counters.globals.ignition_time,
	CL:$counters.globals.idle_time,
	CS:$counters.globals.over_speed,
	CR:$counters.globals.over_rpm
FieldTAIP Equivalent
odometerVO
ignition_timeCE
idle_timeCI
over_speedCS
over_rpmCR

Signal counters

Syrus can also build counters based on custom signals, these can be used to count the:

  • Number of times a signal occurred
  • Accumulated time (total time) in seconds
  • Difference in time since last event (delta)
  • Traveled distance (total distance) in meters
  • Difference in distance since the last event (delta)

When you create a counter for a custom signal Syrus will automatically create an internal count of the following fields.

FieldDescriptionUnits
total_countTotal amount of times the signal has been trueCount
total_timeTotal duration that the signal is trueSeconds
time_incrementTime passed while a signal is true since its last eventSeconds
total_distanceTotal distance traveled while the signal is trueMeters
distance_incrementDistance passed while a signal is true since its last eventMeters

To create a signal counter you just need to define the signal, then create the counter:

# start by defining the signal 
define signal sg_in1_on $io.in1

# create a counter for this signal
define counters input1_counts signal=sg_in1_on start=true

Fieldset

The fieldsets can be defined with

field_name:$counters.name.field

# custom counters for signal: input1_counts
define counters input1_counts signal=sg_in1_on start=true

# fieldset for input1 
define fieldset input1_fieldset fields=
	total_in1_count:$counters.input1_counts.total_count,
	total_in1_duration:$counters.input1_counts.total_time,
	total_in1_distance:$counters.input1_counts.total_distance

Transmitting to Pegasus over TAIP
If you are transmitting to Pegasus Gateway you'll need to define the following fieldset fields

FieldTAIP Equivalent
hard_brakesUse a CV counter like CV00, (CV00-CV49 available)
harsh_fwd_accelerationUse a CV counter like CV01, (CV00-CV49 available)
total_countUse a CV counter like CV02, (CV00-CV49 available)
total_timeUse a CV counter like CV03, (CV00-CV49 available)
time_incrementUse a CV counter like CV04, (CV00-CV49 available)
total_distanceUse a CV counter like CV05, (CV00-CV49 available)
distance_incrementUse a CV counter like CV06, (CV00-CV49 available)
define fieldset peg fields=
	CV00:$counters.driver1.hard_brakes,
	CV01:$counters.driver1.harsh_fwd_acceleration,
	CV02:$counters.input1_counts.total_count,
	CV03:$counters.input1_counts.total_time,
	CV04:$counters.input1_counts.time_increment,
	CV05:$counters.input1_counts.total_distance,
	CV06:$counters.input1_counts.distance_increment

Actions

The following actions can be performed over counters:

ActionDescription
startStarts/resumes a counter
stopStops a counter
resetResets counter values back to 0.
resetallResets all counter values back to 0 and changes the thresholds to the default values.
deleteDeletes a counter definition (make sure it's not being used in a fieldset)

The format is:
action counters name

These actions can be added to an action definition, for example:

## Built-in Counter Example

# start counters when signal john_connected is detected
define action trigger=john_connected start counters john

# stop counters when signal john_connected is not detected
define action trigger=john_connected,not stop counters john

## Custom Counter Example

# stop custom counter
define action ac_stop_in1_count trigger=sg_in1_count stop counters input1_counts

Signals

You can define signals with the counter values as follow:

## Built-in Counter Example

# signal when the ignition_time reaches 200 hours
define signal hourmeter200 $counters.john.ignition_time > 720000

# signal when the odometer reaches 20km
define signal odometer20km $counters.john.odometer > 20000

# fire respective events
define event hourmeter group=default fieldset=default ack=seq label=200hr code=25 trigger=hourmeter200
define event odometer group=default fieldset=default ack=seq label=20km code=25 trigger=odometer20km

## Custom Counter Example

# signal when a value is reached
define signal sg_input1_duration_limit $counters.input1_counts.total_time >= 60

# signal when number of times is >= 10
define signal sg_input1_amount_of_times $counters.input1_counts.total_count >= 10

Head to the deploy section to see an example showcasing the counters with HoS.


Engine Control Unit (ECU)

Actions and Signals List

The ECU gives you the ability to read any engine parameter that a vehicle reports through its CAN bus interface.
To configure and set up the ECU please visit the management tool section and read the corresponding ECU documentation.

Get Values

Once the ECU is reading data from the CAN bus you can retrieve values with:

get value $ecu.$id
get value $ecu.$name

get value $ecu.fef4_1

get value $ecu.tires_provisioning

The $name and $id values come from the ECU directory from the SDK, if the parameter name is not listed then you'll always have the option to use the $id.

Signals

Signals can be constructed in 2 main ways, either using the name of the parameter along with an operator and a value, or a change using delta parameter.

Using the name along with the operator and value allows you to do things like: detect when the odometer is greater than or equal to 100,000km, while the delta changes allow you to do things like: detect when the fuel value drops by 15% in 2 minutes.

Signals with operators

To construct signals in the traditional way using operators use the same convention as above, either the $name or $id from the ECU directory

define signal my_signal $ecu.$id
define signal my_signal $ecu.$name

# signal definition using $id
define signal low_fuel $ecu.fefc_2 < 10

# signal definition using $name
define signal low_fuel $ecu.fuel_level < 10

:::tip πŸ’‘ πŸ’‘
parameters with Count units are reported in numerical decimal values, for example, seat belt switch
:::

StateSyruslang equivalentMeaning
000NOT Buckled
011OK - Seat Belt is buckled
102Error - Switch state cannot be determined
113Not Available
# true when the coolant temperature is > 100Β°C
define signal sg_coolant_temp $ecu.coolant_temp > 100

# true when the oil level is below 20%
define signal sg_oil_level $ecu.oil_level < 20

# true when the vehicle battery is < 8V
define signal sg_battery_power $ecu.battery_power < 8

# true when the the seat belt is buckled
define signal sg_seat_belt_buckled $ecu.seat_belt == 1
Delta changes

To define signals using the deltas (changes) in values, refer to the following section in the ECU development.
It explains how to create a file that allows you to detect changes for particular parameters when the value increases or decreases by X value in Y seconds.

Assuming we have the following: ecuparams.conf.json

{
    "fefc_2": {
        "warnings": [
            "delta?time=60&value=10",
            "delta?time=120&value=-10"
        ]
    } 
}

We can trigger the signals like so:

define signal fuel_refill @ecu_warning.fefc_2.delta?time=60&value=10

define signal fuel_theft @ecu_warning.fefc_2.delta?time=120&value=-10

and trigger the accompanying events like this

define event ev_fuel_theft group=tracking fieldset=default ack=seq label=excsvfl code=90 trigger=fuel_theft

define event ev_fuel_refill group=tracking fieldset=default ack=seq label=flrfl code=91 trigger=fuel_refill

Diagnostic Trouble Codes

The diagnostic trouble codes for the ECU can be constructed using the field: $ecu.error_codes.

The fields to keep in mind are:

FieldDescription
$ecu.error_codes.spnSuspect Parameter Number
$ecu.error_codes.fmiFailure Mode Identifier
$ecu.error_codes.cmSPN Conversion Method
$ecu.error_codes.ocOccurrence Count

An example of the fields reported can look like this:

{
	...
	"$ecu.error_codes.spn": 177,
	"$ecu.error_codes.fmi": 3,
	"$ecu.error_codes.cm": 0,
	"$ecu.error_codes.oc": 126
}

Thus you can use this to construct signals based on specific error codes detected.

# Engine Pre-filter Oil Pressure
define signal spn_oil_pressure $ecu.error_codes.spn == 1208

# FMI Voltage above normal
define signal fmi_voltage_above $ecu.error_codes.fmi == 3

# Event for Engine Oil Pressure Voltage Above Normal
define event engine_oil_pressure_voltage_above_normal group=tracking ack=seq label=diagoilpsi trigger=spn_oil_pressure,fmi_voltage_above,and

Fieldset

When working with TAIP protocol, you can set the fieldset $ecu and the ECU parameters read will automatically be transmitted as the corresponding TAIP values to an endpoint.
You can also define your own fieldsets

define fieldset default fields="fuel_level":$ecu.fefc_2,"rpm":$ecu.rpm
{
  ...
  "fuel_level": 80,
  "rpm": 1430
}

DMS / Fatigue Sensor

Actions and Signals List

The fatigue sensor accessory can alert if a driver is falling asleep, depending on which fatigue sensor you install you could capture photos or videos that can be uploaded to an ftp server.
For more information on video media click here.

Signals

The following table describes the list of signals compatible with all fatigue sensor accessories that Syrus can interact with. Some signals are exclusive to a particular accessory, while some signals are fired by multiple accessories.

Fatigue Signals and Media Supported

Check the Fatigue Sensor's connect page for the accessories that support each type of media.

Normal events
DescriptionFatigue Sensor SignalPhotoVideoRecommended label
Driver fatigue warning (yawning)@fatigue_sensor.fatigue_warningβœ…βœ…ftgwarning
Driver fatigue reminder@fatigue_sensor.fatigue_remindβœ…πŸš«ftgwarning
Driver fatigue alarm (drowsiness)@fatigue_sensor.fatigue_alarmβœ…βœ…ftgalarm
Driver distracted@fatigue_sensor.distractionβœ…βœ…ftgdistrct
Driver not detected@fatigue_sensor.no_portraitβœ…πŸš«ftgnodrivr
Driver on phone@fatigue_sensor.phoneπŸš«βœ…ftgcamphon
Driving with no seatbelt@fatigue_sensor.seatbelt_offπŸš«βœ…ftgnosblt
Driver smoking@fatigue_sensor.smokingπŸš«βœ…ftgcamsmok
Driver identified@fatigue_sensor.driver_identifiedπŸš«βœ…ftgdrvid
Driver changed@fatigue_sensor.driver_changedπŸš«βœ…ftgdrvchg
Driver unknown@fatigue_sensor.unknown_driverπŸš«βœ…ftgukwdrv
Driver missing@fatigue_sensor.driver_missingπŸš«βœ…ftgdrvmis
Camera blocked@fatigue_sensor.camera_blockedπŸš«βœ…ftgcamblck
Ignition ON@fatigue_sensor.ignition_onπŸš«βœ…ftgignon
Ignition OFF@fatigue_sensor.ignition_offπŸš«βœ…ftgignoff
Tamper alert@fatigue_sensor.tamper_alertπŸš«βœ…ftgtamper
Photo captured@fatigue_sensor.photoβœ…πŸš«ftgphoto
Diagnostic events

Compatible with Cipia FS-10 DMS only

Note that by default the fatigue diagnostic events come with no video or photo evidence, to add it you have to edit the camera's configuration.

     "SystemBootFailure": {
       "Activation": true,
       "FeedbackAudio": true,
       "FeedbackOutput": false,
       "FeedbackSpeech": false,
       "FeedbackVisual": true,
       "ReportEvent": true,
       "ReportFootage": false,   # set to true to record a video
       "ReportImage": false      # set to true to capture an image
     }
DescriptionFatigue Sensor SignalPhotoVideoRecommended label
Device successful system tests after bootup@fatigue_sensor.system_boot🚫🚫ftgsboot
Detection of any error in built-in system tests after boot@fatigue_sensor.system_boot_failure🚫🚫ftgsbootfl
Recovery from any system error code@fatigue_sensor.system_ok🚫🚫ftgok
Generated post system boot after a self-reset event.@fatigue_sensor.system_reset🚫🚫ftgsrst
System boot failure due to Embedded Multimedia Card@fatigue_sensor.system_error.emmc_failed🚫🚫ftgerr
Camera detected an overexposure (note that this can be considered tampering)@fatigue_sensor.system_error.over_exposure🚫🚫ftgtamper
Camera detected a blurred_image (note that this can be considered tampering)@fatigue_sensor.system_error.blurred_image 🚫🚫ftgtamper
Camera detected a dark image (note that this can be considered tampering)@fatigue_sensor.system_error.dark_image🚫🚫ftgtamper
Camera detected an unrecognized image (note that this can be considered tampering)@fatigue_sensor.system_error.unrecognized🚫🚫ftgtamper
Camera is not calibrated@fatigue_sensor.system_error.device_not_calibrated🚫🚫ftgerrcal
Camera power lost@fatigue_sensor.system_error.power_lost🚫🚫ftgpwr
Camera mcu upgraded ok@fatigue_sensor.system_error.mcu_upgrade_ok🚫🚫ftgok
Camera shifted locations@fatigue_sensor.system_error.device_shifted🚫🚫ftgshft
Camera cable disconnected@fatigue_sensor.system_error.cable_disconected🚫🚫ftgdisc
Camera over heating@fatigue_sensor.system_error.overheat🚫🚫ftgerr
Camera lost gps@fatigue_sensor.system_error.gps_loss🚫🚫ftgnogps
Camera sd card malfunction@fatigue_sensor.system_error.sdcard_hw_malfunction🚫🚫ftgerr
Camera mcu overheat@fatigue_sensor.system_error.mcu_overheat🚫🚫ftgmcuheat
Camera mcu version error@fatigue_sensor.system_error.mcu_version🚫🚫ftgmcuverr
Camera mcu version 'a' or hw number error@fatigue_sensor.system_error.mcu_version_a_hw_number🚫🚫ftgerr
Camera cpu overheat@fatigue_sensor.system_error.cpu_overheat🚫🚫ftgcpuheat
Camera invalid config rejected@fatigue_sensor.system_error.invalid_confg🚫🚫ftginvcnfg
Camera damage led@fatigue_sensor.system_error.damage_led🚫🚫ftgled

Fieldsets

The fatigue sensor fields can be added with the$fatigue_sensor for json protocol, if you're using taip there's no need to add fieldsets as it is done automatically whenever a photo is captured.

Sample payload

{
	"fatigue_sensor": {
		"state": "connected",
		"sensitivity": 3,
		"speaker_volume": 2,
		"min_speed": 10,
		"speeding": 50,
		"max_photos": 50,
		"nbr_photos": 24,
		"latest_photo": "1616442180-photo.jpeg"
	}
}

When using the CAN bus interface the sample payload will look like this

{
	"$ecu": {
		"yawning": 1,
		"drowsiness": 0,
		"distraction": 0,
		"driver_absence": 0,
		"phone": 0,
		"smoking": 0,
		"camera_blocked": 0,
		"fefc_2": 10
		...
	}
}

You can also build a payload to include fatigue sensor information

define fieldset fatigue fields=fatigue_alert:$ecu.fatigue_drowsiness

Events

Fatigue sensor events can have media such as a photo or video clip attached to it.

Photos

To specify a photo use the photo param on the event definition:
photo=photo_source where photo_source can be

  • fatigue_sensor - for the last photo captured by the fatigue sensor
  • fatigue_sensor.fatigue_remind
  • fatigue_sensor.fatigue_warning
  • fatigue_sensor.fatigue_alarm
  • fatigue_sensor.no_portrait
  • fatigue_sensor.distraction
  • fatigue_sensor.photo

Example events:

define event any_photo group=tracking 
	ack=seq label=ftgphoto
	photo=fatigue_sensor 
	trigger=@fatigue_sensor.signal

define event distracted group=tracking 
	ack=seq label=ftgdistrct
	photo=fatigue_sensor.distraction 
	trigger=@fatigue_sensor.distraction

define event nodriver group=tracking 
	ack=seq label=ftgnodrivr
	photo=fatigue_sensor.no_portrait 
	trigger=@fatigue_sensor.no_portrait

Videos

Refer to the Fatigue Sensor Comparison to see the compatible video events per accessory.

To attach a video clip to an event for Cipia FS-10 or Movon MDSM7 sensors you need to define the event with the signal trigger that you need, and attach it to a video with $fatigue_sensor.media.event

# Fatigue Sensor (Manufacturer: Cipia, Model: FS-10)
# Fatigue Sensor (Manufacturer: Movon, Model: MDSM-7)
##NOTE: video is attached with $fatigue_sensor.media.event
define event ev_fatigue_alarm_video group=tracking
	ack=seq label=ftgalrmvid code=88
	fieldset=default
	video=$fatigue_sensor.media.event
	trigger=@fatigue_sensor.fatigue_alarm

define event ev_fatigue_phone_use group=tracking
	ack=seq label=ftgphonvid code=89
	fieldset=default
	video=$fatigue_sensor.media.event
	trigger=@fatigue_sensor.phone

# -- 
# Fatigue Sensor (Manufacturer: Cipia, Model: FS-10)
## NOTE: this event is exclusive for this sensor ^
define event ev_fatigue_driver_changed_video group=tracking
	ack=seq label=ftgdrvchng code=90
	fieldset=default
	video=$fatigue_sensor.media.event
	trigger=@fatigue_sensor.driver_changed

# Send a delayed video clip (waits for an ack from the server to upload it)
define event ev_fatigue_driver_distraction group=tracking
	ack=seq label=ftgdistrct code=91
	fieldset=default
	video=$fatigue_sensor.media.event
	upload=ondemand
	trigger=@fatigue_sensor.distraction

Videos and Photos

You can capture both a video and a photo by specifying both on the event as follow.
This is compatible with the Cipia FS-10 camera, and you must specify in the camera's configuration that you want to capture both video and photo.

# DMS Camera (Manufacturer: Cipia, Model: FS-10)
define event ev_fatigue_alarm group=tracking
    ack=seq label=ftgalarm code=92
    fieldset=default
    video=$fatigue_sensor.media.event
    photo=fatigue_sensor.fatigue_alarm
    trigger=@fatigue_sensor.fatigue_alarm

# -- 
# DMS Camera (Manufacturer: Cipia, Model: FS-10)
# Fatigue tampering detection
#   photo uploaded automatically
#   video uploaded on demand (requires an ack from the server to upload it)
define event ev_fatigue_tamper group=tracking
    ack=seq label=ftgtamper code=93
    fieldset=default
    video=$fatigue_sensor.media.event
    photo=fatigue_sensor.fatigue_alarm
    upload=ondemand
    camera=cipia
    trigger=@fatigue_sensor.tamper_alert

Actions

Fatigue sensor actions allow you to configure some fatigue sensor's parameters, or help you capture videos.

For the serial interface fatigue sensor accessory these are the list of compatible commands you can add to an action:

CommandDescription
capture fatigue_sensor photoCaptures a photo with the fatigue sensor camera
upload fatigue_sensor photosManually upload all photos to an ftp destination
set fatigue_sensor sensitivityChange sensitivity (Range: 2-11)
set fatigue_sensor speaker_volumeChange the speaker volume (Range: 0-2)
set fatigue_sensor minimum_speedChange the minimum speed to trigger fatigue alerts (Range: 10-60)kph
set fatigue_sensor speeding_alarmChange the speeding alarm (Range: 0-255)kph
set fatigue_sensor buffer_sizeChange the max photos that can be captured (Range: 10-100)
set fatigue_sensor autouploadManage the auto upload of photos to the DCT ftp directory, default is 0
clear fatigue_sensor bufferDeletes all photos in the fatigue_sensor directory

For the ethernet interface fatigue sensor accessory you can capture a video using an action with the create video command.

The create video command takes two parameters, the name of the video --name= (it's useful to have a timestamp as the start of the name of the video clip, $gnss.timestamp) and --time_win which is the time window back and forward in seconds to record a clip for.

# Ethernet Fatigue Sensor (Manufacturer: Movon, Model: MDSM-7)
define action ac_fatigue_alarm_drowsiness trigger=@fatigue_sensor.fatigue_alarm
	create video --name={{$gnss.timestamp}}-drowsiness --time_win=-5,+5

define action ac_fatigue_distraction trigger=@fatigue_sensor.distraction
	create video --name={{$gnss.timestamp}}-distraction --time_win=-5,+5

define action ac_fatigue_warning_yawning trigger=@fatigue_sensor.fatigue_warning
	create video --name={{$gnss.timestamp}}-yawning --time_win=-5,+5

define action ac_fatigue_phone trigger=@fatigue_sensor.phone
	create video --name={{$gnss.timestamp}}-phone --time_win=-5,+5

define action ac_fatigue_smoking trigger=@fatigue_sensor.smoking
	create video --name={{$gnss.timestamp}}-smoking --time_win=-5,+5

define action ac_fatigue_cam_blocked trigger=@fatigue_sensor.camera_blocked
	create video --name={{$gnss.timestamp}}-cam_blocked --time_win=-5,+5

Fuel Sensor (Technoton)

Actions and Signals List / Connect Guide

The Fuel Sensor feature is available through a serial accessory that's capable getting fuel readings and take actions over the values.

Signals

The signals that can be triggered include one-shot and states

signaldescription
@fuel.eventTriggered when any fuel event is detected
@fuel.stateTriggered when a state arrives
@fuel.fuelingTriggered when a fueling notification arrives
@fuel.warningTriggered when a discharge warning notification arrives
@fuel.connectedTriggered when a transition from disconnected to connected is detected
@fuel.disconnectedTriggered when a transition from connected to disconnected is detected
$fuel.connectedStores the last connected state (boolean)
$fuel.levelStores the last fuel level (number)
$fuel.temperatureStores the last temperature level (number)
$fuel.frequencyStores the last frequency (number)
$fuel.timestampStores the last notification timestamp (epoch)
$fuel.eventStores the last event (string)
# possible fuel theft event
define event fuel_theft group=tracking fieldset=default label=fuelloss [email protected]

# low fuel level event
define event low_fuel group=tracking fieldset=default label=lwfuel trigger=$fuel.level < 20

πŸ“˜

Fuel level

Note that the fuel level units are variable and depend on how the sensor is configured; SyrusJS treats the fuel value as the raw value.

Geofences

Actions and Signals List

Geofences definitions are managed by the apx-geofences tool, up to 3000 of them.

Syruslang will manage 1 namespace.
Geofences can be defined in Syruslang the following format:

# circle
define geofence geofence_name [group=group_name] radius=50mts lon,lat

#polygon
define geofence geofence_name [group=group_name] lon1,lat1 lon2,lat2 lon3,lat3, ...

If no group is defined, the geofences will automatically belong to a group called: default.

The radius consists of a number, minimum 50 meters or 165 feet, followed by one of the following units mts, ft, km, mile for meters, feet, kilometers, and miles respectively.

Polygons consists of a minimum 3 coordinate pairs, up to 500 coordinate pairs.

geofence_name & group_name

The name and group of the geofence has to follow these guidelines:

  • Case sensitive
  • 3 to 50 characters
  • πŸ›‘ cannot start with a number!
  • _ and - are the only allowed special characters
  • [a-Z0-9][a-Z0-9_-]{3,50}

Once a geofence is defined the event engine evalutes the following signals constantly:

signalTypeDescription
$geofences.geofence_name.insidebooleanTrue if the geofence is inside
$geofences.geofence_name.timenumberEpoch timestamp of last geofence state change
$geofences.$groups.group_name.insidebooleanTrue if geofence is inside any geofence in the group group_name
$geofences.$groups.group_name.outsidebooleanTrue if the geofence is outside all geofences in the group group_name

There is also a fixed-signal @last_geofence which contains the last geofence that was modified, either by entering or exiting:

signalTypeDescription
@last_geofence.nameStringName of the last geofence that was modified
@last_geofence.stateStringinside or outside state of the last geofence
@last_geofence.timeNumberEpoch timestamp of the last state change

geofences:

# two geofences in same group
define geofence hilton_blue_lagoon group=hotels radius=150mts -80.27856,25.78155
define geofence hilton_miami group=hotels radius=165ft -80.18867,25.79092

# one geofence in different group
define geofence dolphin_mall group=malls -80.38476,25.79042 -80.37606,25.79044 -80.37613,25.784339 -80.38449,25.78506

signals

# reference 1 geofence
define signal in_mall_for_30 min_duration=30min $geofences.dolphin_mall.inside

# reference any hotel
define signal in_any_hotel min_duration=20sec $geofences.$groups.hotels.inside

actions

# speak to a paired bluetooth speaker
define action parked_in_mall trigger=in_mall_for_30 speak 'welcome to {{@last_geofence.name}}'

# activate output 2
define action visit_hotel trigger=in_any_hotel set $io.out2 on

events

# entered hotel
define event arrived_at_hotel group=tracking fieldset=default ack=seq label=hotel code=40 trigger=in_any_hotel

# stay in mall
define event in_mall group=tracking fieldset=default ack=seq label=mall code=41 trigger=in_mall_for_30

Geofence Speed Limits

Geofences can have a speed limit assigned to them. These speed limits can even be fired depending on the vehicle's GNSS heading direction (N, S, E, W, etc.). With this, you can achieve having different speed limits depending on which way the vehicle is traveling.

Read the following application note for more information

define fieldset geospd fields=$geospeed

define event spd_any_speeding fieldset=geospd group=tracking ack=seq label=spd_test_all code=15 trigger=@geofences.*.*.*.speeding
define event spd_any_group fieldset=geospd group=tracking ack=seq label=spd_any_nmsp code=16 trigger=@geofences.*.NAME.ALIAS.speeding
define event spd_any_name fieldset=geospd group=tracking ack=seq label=spd_any_grp code=17 [email protected].*.ALIAS.speeding
define event spd_any_alias fieldset=geospd group=tracking ack=seq label=spd_any_al code=18 [email protected].*.speeding

define signal sg_init_geospeed $geospeed.warning == true
define signal sg_finish_geospeed $geospeed.warning == false

define event geo_speed_init fieldset=geospd group=tracking ack=seq label=spd_init code=19 trigger=sg_init_geospeed
define event geo_speed_finish fieldset=geospd group=tracking ack=seq label=spd_finish code=20 trigger=sg_finish_geospeed

define signal sg_inside $geofences.GEOFENCE_NAME.inside == true
define signal sg_outside $geofences.GEOFENCE_NAME.inside == false

define event geo_in fieldset=geospd group=tracking ack=seq label=geo_in code=21 trigger=sg_inside
define event geo_out fieldset=geospd group=tracking ack=seq label=geo_out code=22 trigger=sg_outside
Geofence Speed Warning

The $geospeed fieldset generates an extended tag named gsw. More info information Syrus-3-protocol-taip

# events fields generated with the GSW tag
epoch: Timestamp of speeding event in seconds
type: Type of warning [speeding]
state: Current state [in_progress | finished_by_speed | finished_by_geofence | finished_by_gps]
namespace: Namespace of geofence definitions
group: Geofence group
name: Defined name of geofence
elapsed_time: Elapsed time speeding inside the geofence
elapsed_distance: Elapsed distance speeding inside the geofence
th_alias: Defined Alias for the speed limit
th_speed: Defined speed threshold
s_speed: Speed at start of speed limit
s_heading: Heading at start of speed limit
s_lo: Longitude coordinate at start of speed limit
s_lat: Latitude coordinate at start of speed limit
e_speed: Finishing speed [m/s]
e_heading: Finishing heading [degrees]
e_lon: Finishing longitude
e_lat: Finishing latitude
m_speed: Maximum speed inside reached
m_heading: Heading at the maximum speed
m_lon: Longitude coordinate at maximum speed
m_lat: Latitude cordinate at maximum speed

GNSS (Event Data Recorder)

Actions and Signals List

The GNSS of the Syrus 4 allows you to obtain location information of the device.

One of the important features of the GNSS is the ability to act as a blackbox, allowing you to record second-by-second location data before and after a certain point, this feature is also referred to as Event Data Recorder.

Event Data Recording

In order to record event data second by second you need to use the apx-gps backlog command as part of an action.
To associate the action to an event you need to have a common variable between them.

# action that executes a gps backlog of last 20 seconds and next 5 seconds
define action ac_backlog [email protected]_fwd_acceleration.signal
	set variable accel_backlog {{$gnss.timestamp}}-accel_backlog
	exec apx-gps backlog create --name={{$variables.accel_backlog}} --time-win=-20,+5
	send event ev_ac_backlog

# event that's sent when the backlog is triggered
define event ev_ac_backlog group=tracking
	code=60 label=backlog
	backlog=$variables.accel_backlog

Note that in TAIP protocol extended tags are not supported yet for the GPS backlog.

The maximum time that support --time-win is -150,+150.

IButton

Actions and Signals List

The ibutton is a onewire compatible accessory that is useful for driver identification. It is a key fob with a unique ID allowing you to 'add' or 'authorize' a particular ibutton on the device to take actions with. Note that a total of 500 onewire devices can be defined, this list is shared with the temperature sensor accessory.

The following examples will look at how to use the ibutton to identify drivers, for information on how to connect and configure the ibutton head to our accessories section.

To authorize an ibutton in syruslang use the following format:

add ibutton alias_name id

add ibutton driver1 91000014A0707F01

Once added, you can use the 'whitelisted' signal to take an action when that particular ibutton is presented since it's now authorized

# authorized driver
define signal auth_ibutton $ibutton.connected.whitelisted

# unauthorized driver
define signal unauth_ibutton $ibutton.connected.whitelisted == false

# action to deactivate output1 if driver authorized
define action auth_driver_deactivate_out trigger=auth_ibutton set out1 off

# action to activate output2 if driver is unauthorized
define action unauth_activate_out trigger=unauth_ibutton set out2 on

You may also choose to clear the last known ibutton when the ignition is turned off for example.

# clear last ibutton when ignition is OFF
define action clear_ib trigger=ign_on,not clear ibutton

Fieldset

In order to append ibutton data to your event fields you can use the $ibutton field for JSON protocol.

define fieldset json_ibutton fields=$ibutton
{
	"$ibuttons": [
		{
			"alias": "driver1",
			"id": "123456789012345",
			"whitelisted": true,
			"connected": true,
			"conn_epoch": 1608048266,
			"disc_epoch": 1608048273
		}
	]
}

for TAIP protocol you have two possibilities, either the last value read, or the current value.

define fieldset taip_current_ibutton fields=IB:$ibutton.connected.id
define fieldset taip_last_ibutton fields=IS:$ibutton.last.id

Inputs/Outputs

Actions & Signals List

The device's inputs and outputs can be used to sense the state of things or activate others. For more information on the installation refer to connect docs.

Virtual Ignition

Note that you can virtualize the ignition of the device so that it uses a different signal as the "Ignition" detection.
To virtualize use the apx-io system tool.

# Set virtual ignition with Analog Input 2
# Detects ON when the value is above 5000mV for 5 seconds, OFF when below 5000 for 5 seconds
exec apx-io set virtualign --signal=AN2 --on_threshold=5000 --off_threshold=5000 --on_time=5 --off_time=5

Once set this will allow you to use the io.ign signal like normal, just that underneath it's being treated as a different signal, also keep in mind that this will affect the counters that depend on this signal.

# the signal for ignition ON would be detected once Analog Input 2 is above 5V for 5 seconds
define signal sg_ignition_on $io.ign == true

# counters affected by the virtual ignition are: odometer, ignition_time, idle_time
define counters name odometer=0 ignition_time=0 idle_time=0

IO Expander

IOs Expander allows additional inputs and outputs in Syrus4G.

Actions & Signals List

Example

# - Signals
define signal sg_iox_connected $iox.connected == true
define signal sg_iox_disconnected $iox.connected == false
define signal sg_iox_in1_true $iox.in1 == true
define signal sg_iox_out1_true $iox.out1 == true

# - Events
define event ev_iox_conn group=tracking fieldset=default label=ioxcon code=90 trigger=sg_iox_connected
define event ev_iox_disc group=tracking fieldset=default label=ioxdis code=91 trigger=sg_iox_disconnected
define event ev_iox_in1 group=tracking fieldset=default label=ioxdis code=92 trigger=sg_iox_in1_true
define event ev_iox_out1 group=tracking fieldset=default label=ioxdis code=92 trigger=sg_iox_out1_true

# - Actions - Activate expanded out1 when in1 true
define action ac_iox_out1 trigger=sg_iox_in1_true
    sudo apx-onewire iosexpander set OUT1 true

Safe immobilization

You can enable the activation of output 1 safely using the safe-engine-cut-off mechanism - apx-seco.

Syruslang sets a variable called $safe_immo when it receives the command: >SXASES1<. With this we are able to trigger the action to enable safe engine immobilization using the apx-seco command.

# enable safe immobilization mechanism
exec apx-seco set --mode=enable

# execute a safe immobilization after receiving the command
define signal sg_safeimmo $variables.$safe_immo == 1

define action ac_seco_activate trigger=sg_safeimmo
    exec apx-seco set --trigger=enable

# disable a safe immobilization
define action ac_seco_deactivate trigger=sg_safeimmo,not
    exec apx-seco set --trigger=disable

# report an event when the output is activated or deactivated
define signal out1_active $io.out1 == true

define event seco_on group=tracking 
    fieldset=default label=immoon code=10 trigger=out1_active

define event seco_off group=tracking 
    fieldset=default label=immooff code=11 trigger=out1_active,not

# enable safe immobilization mechanism
exec apx-seco set --mode=enable

# activate output safely after ignition is OFF
define signal ignition_off $io.ign == false

define action seco_activate trigger=ignition_off
    exec apx-seco set --trigger=enable

# report an event when the output is activated
define signal out1_active $io.out1 == true

define event incoming_message group=tracking 
    fieldset=default label=out1on code=10 trigger=out1_active

# deactivate the output when an ibutton is presented
define signal auth_ibutton $ibutton.connected.whitelisted

define action ib_out1off trigger=auth_ibutton 
    exec apx-seco set --trigger=disable

Jamming

Actions & Signals List

Jamming refers to the deliberate blocking or interference with wireless communication signals. Syrus can detect jamming with built in signals:

Signals

  • @modem.jamming_detected - Triggered when a jamming condition is detected
  • @modem.jamming_persistence - Triggered when the jamming condition persist for one minute
  • @modem.jamming_ended - Triggered when the jamming action stops

States

  • $modem.jamming.state - The jamming state [ JAMMED | NOT_JAMMING ]
  • $modem.jamming_detected - The jamming state [ true | false ]
  • $modem.jamming_persistence - The persistence flag state [ true | false]
  • $modem.jamming_ended - The ended flag state [ true | false ]

Events

define event ev_jamming group=tracking fieldset=tracking 
    ack=seq label=jammed code=90 
    [email protected]_detected

define event ev_jampers group=tracking fieldset=tracking 
    ack=seq label=jampers code=91 
    [email protected]_persistence

define event ev_not_jamming group=tracking fieldset=tracking 
    ack=seq label=jammend code=92 
    [email protected]_ended

MDT / Serial

Actions and Signals List

MDT or Mobile Data Terminal is a mode that the Syrus can be configured in which allows you to receive data via the device's rs-232 serial port, encapsulate it and send it to a destination.

To get started make sure you follow the installation instructions in our connect page.

Once you have the serial accessory connected and it's transmitting data periodically via the serial port you can configure an event upon an incoming mdt message with the following signal @mdt.message.

Note, it's recommended that you do not mix this with other signals
​

# Generates an event when a message is received while in mdt mode
define event incoming_mdt_message group=mdt label=mdtrx fieldset=default code=90 [email protected]

# Generates an event when a message is received while in console mode
define event incoming_serial_message group=mdt label=msgrx fieldset=default code=91 [email protected]

When a message is received the event will generate and the data appended to a json message will come in $mdt message

{
	"$mdt": {
		"message": "hello syrus"
	}
}

For TAIP protocol you don't need to add the field, as long as you define the event with @mdt.message it will generate and send to the server.

Actions

You can set the MDT settings with the set mdt command, and send a message with send mdt message

set mdt '115200 x 1 5 0 0 0 0'
define action ignition_on_send_msg trigger=sg_ign_on 
  exec apx-serial send --msg="hello syrus"
  
# send a message over TAIP
define action ignition_on_send_msg trigger=sg_ign_on 
  exec apx-serial send --msg=">RTXmessage<"

πŸ‘

Sending special characters over serial port

If you want to send special characters over the serial port it's recommended to save the message in a variable and use that to send it

# create a variable with the format to send 
# example: [ibutton ID] with a carriage return and line feed
# [iButton 7D000002CFCDCA01]\0D\0A
define variable send_cmd "[iButton {{$ibutton.connected.id}}]\0D\0A"

define action ac_send_ibutton trigger=sg_ibtn_on exec apx-serial-user send --msg={{$variables.send_cmd}}

People Counting

Actions and Signals List, System Tool

The people counting camera counts how many people enter and exit a given area with the help of an overhead camera.

You can build signals to count the amount of adults and children that have entered and exited giving you a total head count and take actions over it.

Events

The signals can be used to build an event whenever something specific occurs.

Possible signals

signaldescriptio