Minimizing Latency
Latency is defined as, "The time interval between initiating a query, transmission, or process, and receiving or detecting the results."
The goal of this guide is to discuss options for minimizing the latency experienced between Notehub.io and a given Notecard. Minimizing latency typically comes at a trade-off in power draw (and potentially data usage - depending on your use case). However, when configured correctly, the Notecard will be opened to a whole new realm of possibilities.
Overview
When modeling the flow of information between a Notecard and Notehub.io, you must first take into consideration the following maxim...
All synchronization operations are initiated from the device in a "push/pull" manner; the service is passive.
When you begin to think of a transaction in this manner, the capabilities and limitations of operations will become obvious. As a result, you will gain an intuitive understanding of what steps must occur in order to achieve your desired outcome.
Above, the Notecard is operating in continuous
mode with sync
set to
true
. This configuration initiates two separate, simultaneous connections;
one dedicated to Note delivery and the other dedicated to notifications.
Database Connection
As previously stated, any time the Notecard and Notehub communicate, that
communication must be initiated by the Notecard. Therefore, in order for the
Notecard to gather new information from Notehub.io, the Notecard would need
to issue requests to Notehub.io. The frequency of this polling request interval
is specified by using the inbound
parameter.
Ideally, you wish for the synchronization to occur as close as possible to the
moment any data changes. In order to minimize latency by using the inbound
parameter alone, the interval must be specified to be as small as possible.
However, doing so would ultimately result in great inefficiencies for both data
usage and power draw.
Fortunately, this limitation can be overcome by the introduction of a secondary communication channel dedicated exclusively to notifications.
Notification Connection
Providing Notehub.io with a mechanism to alert the Notecard of new Notes, while still initiating the transaction from the Notecard itself, has a more elegant and simple solution than you may have guessed.
When sync
is set to true
, the Notecard establishes a secondary connection,
one dedicated to the notification of new Notes. This connection utilizes HTTP
long polling to request the set of changes, and the server will only respond
once changes become available. Now, when the Notecard becomes aware of any new
Notes, it can immediately synchronize the Note queues on the primary connection.
Configuring Notehub Interactions
To configure your Notecard to use this secondary connection, you must send
a hub.set
request with the
following values.
hub.set
Request
{
"req": "hub.set",
"mode": "continuous",
"sync": true,
"inbound": <Number: polling interval in minutes>
}
mode: "continuous"
Parameter
Once mode
is set to continuous
, a continuous connection is established
between the Notecard and Notehub.io. Maintaining a continuous connection
requires significantly more power than polling at a periodic interval, but the
Notecard will have much faster response times as a result. A continuous
connection prevents the Notecard from being required to power on,
connect to a cellular tower (or a Wi-Fi access point for the Notecard WiFi),
and open a connection to Notehub.io with each
transaction. All told, this can minimize the amount of data required for each
transaction, as well as the time required to send messages in either direction.
sync: true
Parameter
When sync
is set to true
, a secondary connection is established with the
express purpose of allowing Notehub.io to signal that new data has arrived for
the Notecard to process.
When Notes are received on Notehub.io, Notehub will send a list of the filenames that were modified to the Notecard. Then, the Notecard will issue a request for changes over the primary connection, and pull the new Notes from Notehub.io to the Notecard. Once they have arrived on the Notecard, then they can be operated on by your program.
If your application can benefit from knowing as soon as information becomes
available on Notehub.io, then utilizing sync:true
is the most efficient way
to expedite Note arrival. Depending on your desired polling interval, operating
in this manner can even result in power and data savings.
inbound: <Number: polling interval in minutes>
Parameter
Inbound polling will force a synchronization at the specified interval, regardless of whether or not data is known to be queued on Notehub.io.
Theoretically, inbound
would have no value when sync:true
is enabled.
However, in practice, inbound
is a necessary evil, and must be used as a
backstop to safeguard against connection failures or any other gaps in the
secondary, notification connection. Scheduling an inbound interval provides a
brute force guarantee to ensure queued data will be never be older than the
specified interval.
Each inbound event will necessarily require a connection with Notehub.io, so it can perform a polling request. This transaction will consume both energy and data at the specified polling interval (i.e. for each transaction), so any interval should be selected with care and tailored to the needs of the application.
Outbound Operations
Due to the fact the Notecard is the originator of all transactions between the Notecard and Notehub.io, it stands to reason the outbound operations should be considered separately from the inbound operations. Therefore, minimizing the latency on an outbound transaction is much more simple because the Notecard controls the connection.
note.add
Request
The easiest way to send low-latency outbound data from the Notecard is with
the note.add
request, making
sure to set the request's sync
parameter to true
.
When sync
is set to true
, the Notecard will immediately send the queued
changes to Notehub.io. Otherwise, when not specified, or set to false
, the
Notecard will wait for the outbound
interval to send the request.
{
"req": "note.add",
"body": { "your-key": "your-data" },
"sync": true
}
Unlike inbound transactions, there is no need to specify an outbound
interval
as a fail-safe. This is because the transaction does not rely on a
network or external signal to indicate whether or not it should attempt to
synchronize queued Notes.
web.post
Request
Another option for sending outbound data is the web.post
request.
The web.post
request sends data directly to a proxy Route in Notehub, and does not
store your data in a Notefile.
Because the web.post
request skips the processing associated with storing and
retrieving data, it runs faster than note.add
. However, because web.post
does
not use Notefiles, you lose some of the reliability that Notefiles guarantee, such
as reliably sending data even if the Notecard loses connectivity, and the ability
to view notes as events in Notehub.
Because of these limitations, we recommend using web.post
when you need outbound
data to come through as fast as possible, and when it's not mission critical for 100%
of requests to come through—especially when operating with limited connectivity.
{
"req": "web.post",
"body": { "your-key": "your-data" },
"route": "your-proxy-route-name"
}
Here, the "route"
argument is the Alias of a proxy route that you must set up in
Notehub. To create a proxy route, first go to the Routes section on a Notehub project, and
create a new Proxy for Device Web Requests route using the Select button below.
Next, configure your route using the form below. The Alias you provide here must match
the route
you provide in your web.post
requests.
With everything configured, Notehub will automatically forward your web.post
requests
to the endpoint you provide in your proxy route.
Using Inbound Signals
Signals are low-latency notes you can send from Notehub to a Notecard. Signals transmit fast because they are not stored in Notefiles, and do not appear as events in Notehub. Because of these processing efficiencies, signals are the fastest way to send inbound data from Notehub to a Notecard.
Signals are only sent to devices that are actively connected to Notehub. If a
signal's target device is not connected, Notehub will discard the signal. If you
need data to reliably transmit regardless of connectivity, use the
note.add
request
to send data from Notehub to a Notecard.
Please also note that inbound signals are always sent over an unencrypted socket.
Sending Signals
You can use the
Send Signal
Notehub API to send signals from Notehub to a Notecard. Signals must contain a
JSON body
, which can contain any valid JSON you wish to send.
For example, the following request sends a signal to a Notecard with a
DeviceUID of dev:123456
, and which is within
a Notehub project with a projectUID of
app:123456
.
curl -X POST
-L 'https://api.notefile.net/v1/projects/app:123456/devices/dev:123456/signal'
-H 'Authorization: Bearer <your-authentication-token>'
-d '{"body":{"example-key":"example-value"}}'
You can refer to the Notehub API documentation for instructions on generating a bearer token.
Receiving Signals
Once you have sent a signal, you'll need to retrieve it on your Notecard. There are two different approaches you can take for retrieving signals.
Option #1: AUX
As a first option, you can configure your Notecard to stream data from its
AUXRX
/ AUXTX
pins to a host device's TX
/ RX
pins. This option is the
absolute fastest way to receive signals, as signal data gets streamed directly
to your host as the Notecard receives it.
To create this setup you need to complete the following steps.
- Wire a Notecard's
AUXRX
pin to a host'sTX
pin. - Wire a Notecard's
AUXTX
pin to a host'sRX
pin. - Ensure the Notecard's
AUXEN
pin is powered, which enables the Notecard's AUX mode. You can do this by wiring the Notecard'sAUXEN
pin to its3V3
pin. - Send a
hub.set
request to the Notecard, ensuring you set the"mode"
to"continuous"
, and"sync"
totrue
. - Send a
{"req": "card.aux.serial","mode": "notify,signals"}
request to the Notecard, which tells the Notecard to start streaming incoming signals toAUXRX
/AUXTX
.
With these steps complete, the Notecard will automatically detect incoming
signals and stream them to your host device's TX
/ RX
pins for further
processing.
Option #2: ATTN
As a second option, you can configure your Notecard to perform an interrupt every time it receives a new signal. To set this workflow up you need to complete the following steps.
- Wire a Notecard's
ATTN
pin to a GPIO pin on your host. If you want your host to only wake on incoming signals, connectATTN
to your host'sEN
pin. - Send a
hub.set
request to the Notecard, ensuring you set the"mode"
to"continuous"
, and"sync"
totrue
. - Send a
{"req": "card.attn", "mode": "arm,signal"}
request to the Notecard. This configures the Notecard so thatATTN
wakes up the host when it receives an inbound signal. - When the host receives the interrupt, send a
{"req": "hub.signal"}
request to the Notecard to dequeue the signal. The signals comes back in"body":{"your-key":"your-value"}
format.
If there are multiple signals to process, the response will include
"signals": N
, where N
is the number of signals remaining.
With these steps complete, the Notecard will detect incoming signals, queue them
in memory, and disarm the ATTN
pin to alert the host to process the signal.