All of the scenarios discussed so far in this guide are focused on performing requests directly against the Notecard from a host, and synching data from the Notecard to Notehub. This type of data is called "outbound data" because it is data that starts on the Notecard and is synchronized to Notehub. In other words it is "outbound" from the perspective of the Notecard.
Many solutions, however, will need to initiate data or requests from a cloud app or external service, and propagate that request down to the Notecard. This data is called "inbound data" because it is data that originates somewhere else and is synchronized to the Notecard. In other words, it is "inbound" from the perspective of the Notecard.
Using the API requests detailed below, you can perform inbound requests to:
- Share state between the Notecard and Notehub.
- Notify the host that new data is available.
Once available, a host can retrieve inbound data from the Notecard, and respond accordingly.
Sending Data Through Notehub
Inbound requests are requests that originate somewhere other than the Notecard, and are sent to the Notecard from Notehub. These requests are created either directly in the Notehub UI or by using the Notehub API.
Adding Inbound Notes in Notehub
To add a Note that will sync to the Notecard from the Notehub UI, navigate to
the Devices dashboard, select your device, and click the "+ Note" button. In
the modal, select the Notefile for your Note (the default is data.qi
) and add
the Note body
as a JSON object.
This approach only supports adding inbound queue files with the .qi
or .qis
extensions. If you need to add Notes to a DB file, use the Notehub API, as
described below.
Also, inbound Notes MUST use Note Templates (defined on the Notecard) if using with Notecard LoRa or NTN mode with Starnote.
Adding Notes for Secure Transport
If you want to ensure that Notes are sent over encrypted TLS to the Notecard,
use the .qis
extension when specifying the Notefile. .qis
signifies that the
Notefile is a secure inbound queue.
Adding Inbound Notes with the Notehub.io API
Alternatively, you may use the
Notehub API to add inbound notes
to Notehub. This approach works for both .qi/.qis
and .db
Notefiles.
For example, here's how to add a Note to the default data.qi
file using curl.
curl -X POST
-L 'https://api.notefile.net/v1/projects/<projectUID>/devices/<deviceUID>/notes/data.qi'
-H 'Authorization: Bearer <access_token>'
-d '{"body":{"key-1":"val-1"}}'
Here's an example for adding a new Note named sync-settings
to a DB file named
my-settings.db
:
curl -X PUT
-L 'https://api.notefile.net/v1/projects/<projectUID>/devices/<deviceUID>/notes/my-settings.db/sync-settings'
-H 'Authorization: Bearer <access_token>'
-d '{"body": {"interval": 60 }}'
Notehub API requests are authorized via OAuth bearer tokens. Consult the Notehub API documentation for more information.
Using Inbound Notefiles with Starnote
As a data-constrained satellite communication device, using NTN mode with
Starnote requires the user to specifically request a check for inbound Notefiles
from Notehub to minimize data usage. This is handled with the "in":true
argument in the
hub.sync API:
{
"req": "hub.sync",
"in": true
}
Also, as mentioned above, inbound Notefiles must use Note Templates that are pre-defined on the Notecard when using NTN mode with Starnote.
Handling Inbound Notes
After a successful sync, inbound Notes and Notefiles are available to your
Notecard. To get an overview of new data across all of your files, use the
file.changes
request with no arguments.
{
"req": "file.changes"
}
J *req = NoteNewRequest("file.changes");
NoteRequest(req);
req = {"req": "file.changes"}
rsp = card.Transaction(req)
When passed with no arguments, file.changes
returns an object with the total
number of new notes across all files, and the totals for each file, by name.
{
"total": 2,
"info": {
"my-settings.db": {
"total": 2
},
"data.qi": {
"total": 1
}
}
}
To obtain a summary of changes across a subset of available files, use the
files
argument and an array containing the file or files you're interested in.
{
"req": "file.changes",
"files": ["data.qi"]
}
J *req = NoteNewRequest("file.changes");
J *files = JAddArrayToObject(req, "files");
JAddItemToArray(files, JCreateString("data.qi"));
NoteRequest(req);
req = {"req": "file.changes"}
req["files"] = ["data.qi"]
rsp = card.Transaction(req)
The response object is similar to the previous request, but returns only data for the files you specified.
{
"total": 1,
"info": {
"data.qi": {
"total": 1
}
}
}
Once you've confirmed that inbound Notes are available, use the note.get
request to retrieve them. Use the file
argument to specify the name of the
Notefile, or omit it to fetch a single Note from the data.qi
Notefile.
{
"req": "note.get",
"file": "requests.qi"
}
J *req = NoteNewRequest("note.get");
JAddStringToObject(req, "file", "requests.qi");
NoteRequest(req);
req = {"req": "note.get"}
req["file"] = "requests.qi"
rsp = card.Transaction(req)
Following queuing semantics, this request will return oldest available Note in
the requests.qi
Notefile, and the time it was created in Notehub.
{
"body": {
"api-key1": "api-val1"
},
"time": 1598909219
}
note.get
does not, by default, remove a Note when you request it, so repeated
calls will return the same Note, even if multiple Notes are available in the
Notefile. To delete a Note after retrieval, use the delete
argument.
Subsequent requests will return and delete successive Notes in the Notefile.
{
"req": "note.get",
"file": "requests.qi",
"delete": true
}
J *req = NoteNewRequest("note.get");
JAddStringToObject(req, "file", "requests.qi");
JAddBoolToObject(req, "delete", true);
NoteRequest(req);
req = {"req": "note.get"}
req["file"] = "requests.qi"
req["delete"] = True
rsp = card.Transaction(req)
Using Database Files for Replicated State
Queued Notefiles (.qo
, .qos
, .qi
, and .qis
) are uni-directional in
nature, and are not ideal for replicating state or settings between the Notecard
and Notehub. For replicated state, use DB Notefiles. These files, which have a
.db
or .dbs
extension, are synchronized between the Notecard and Notehub,
and contain Notes that can be individually read and updated.
Adding and Updating Notes in DB Notefiles
Add Notes to a DB file with the note.add
request. In addition to a Notefile
ID (file
), adding Notes to a DB file requires a Note ID (note
). The Note ID
is used to manage the Note directly, because DB Notefiles hold shared state that
is synchronized between the Notecard and Notehub.
See the Bash
tabs in the
note Requests API docs for
examples on adding/managing Notefiles with the Notehub API.
{
"req": "note.add",
"file": "my-settings.db",
"note": "measurements",
"body": {"interval": 10}
}
J *req = NoteNewRequest("note.add");
JAddStringToObject(req, "file", "my-settings.db");
JAddStringToObject(req, "note", "measurements");
J *body = JCreateObject();
JAddNumberToObject(body, "interval", 10);
JAddItemToObject(req, "body", body);
NoteRequest(req);
req = {"req": "note.add"}
req["file"] = "my-settings.db"
req["note"] = "measurements"
req["body"] = {"interval": 10 }
rsp = card.Transaction(req)
As with other note.add
requests, a payload
can be provided instead of, or in
addition to, a body
.
{
"req": "note.add",
"file": "my-settings.db",
"note": "measurements",
"payload": "ewogICAgInRlbXAiOiAyMy4xMzQKfQ=="
}
J *req = NoteNewRequest("note.add");
JAddStringToObject(req, "file", "my-settings.db");
JAddStringToObject(req, "note", "measurements");
JAddStringToObject(req, "payload", "ewogICAgInRlbXAiOiAyMy4xMzQKfQ==");
NoteRequest(req);
req = {"req": "note.add"}
req["file"] = "my-settings.db"
req["note"] = "measurements"
req["payload"] = "ewogICAgInRlbXAiOiAyMy4xMzQKfQ=="
rsp = card.Transaction(req)
To update a Note in a DB Notefile, use the note.update
request. Provide a new
body
or payload
to replace the existing Note content.
{
"req": "note.update",
"file": "my-settings.db",
"note": "measurements",
"body": {"interval": 60 }
}
J *req = NoteNewRequest("note.update");
JAddStringToObject(req, "file", "my-settings.db");
JAddStringToObject(req, "note", "measurements");
J *body = JCreateObject();
JAddNumberToObject(body, "interval", 60);
JAddItemToObject(req, "body", body);
NoteRequest(req);
req = {"req": "note.update"}
req["file"] = "my-settings.db"
req["note"] = "measurements"
req["body"] = {"interval": 60 }
card.Transaction(req)
Fetching Notes from DB Notefiles
To retrieve a Note from a DB Notefile, use the note.get
request and provide
the file
and note
arguments with the Notefile ID and Note ID, respectively.
{
"req": "note.get",
"file": "my-settings.db",
"note": "measurements"
}
J *req = NoteNewRequest("note.get");
JAddStringToObject(req, "file", "my-settings.db");
JAddStringToObject(req, "note", "measurements");
NoteRequest(req);
req = {"req": "note.get"}
req["file"] = "my-settings.db"
req["note"] = "measurements"
rsp = card.Transaction(req)
The request above will return the measurements
Note in the my-settings.db
Notefile and the time of creation or the most recent update (shown below).
{
"note": "measurements",
"body": {
"interval": 60
},
"time": 1598916085
}
Deleting Notes from a DB Notefile
To delete a DB Note after retrieval, use the delete
argument.
{
"req": "note.get",
"file": "my-settings.db",
"note": "measurements",
"delete": true
}
J *req = NoteNewRequest("note.get");
JAddStringToObject(req, "file", "my-settings.db");
JAddStringToObject(req, "note", "measurements");
JAddBoolToObject(req, "delete", true);
NoteRequest(req);
req = {"req": "note.get"}
req["file"] = "my-settings.db"
req["note"] = "measurements"
req["delete"] = True
rsp = card.Transaction(req)
Alternatively, if you do not need to retrieve the Note, delete the
Note with the note.delete
request. If successful, this request will return
an empty JSON object ({}
).
{
"req": "note.delete",
"file": "my-settings.db",
"note": "measurements"
}
J *req = NoteNewRequest("note.delete");
JAddStringToObject(req, "file", "my-settings.db");
JAddStringToObject(req, "note", "measurements");
NoteRequest(req);
req = {"req": "note.delete"}
req["file"] = "my-settings.db"
req["note"] = "measurements"
card.Transaction(req)
Because DB Notefiles are shared between the Notecard and Notehub, updates and deletions made by either are reconciled during each sync.
Using Database Notefiles for Local-Only State
Sometimes, your host may wish to use the Notecard to store application state or
configuration, but you do not want that state to be synchronized to Notehub.
For these cases, you can use the .dbx
extension to create a Local-only
Notefile. The semantics for adding, updating, and deleting local-only Database
Notefiles is the same as detailed above for replicated Database files.
{
"req": "note.add",
"file": "local-config.dbx",
"note": "sensor-types",
"body": {"temp": "si7201", "gas": "bme680"}
}
J *req = NoteNewRequest("note.add");
JAddStringToObject(req, "file", "local-config.dbx");
JAddStringToObject(req, "note", "sensor-types");
J *body = JCreateObject();
JAddStringToObject(body, "temp", "si7201");
JAddStringToObject(body, "gas", "bme680");
JAddItemToObject(req, "body", body);
NoteRequest(req);
req = {"req": "note.add"}
req["file"] = "local-config.dbx"
req["note"] = "sensor-types"
req["body"] = {"temp": "si7201", "gas": "bme680"}
rsp = card.Transaction(req)
Using Change Trackers with Inbound Data
If your host needs to work with inbound data on a regular basis within and
across Notefiles, you can use a change tracker to incrementally work with
inbound data. A change tracker is identified by a developer-defined string,
like my_inbound_requests
, and used to associate additions and deletions
to Notefiles.
Change trackers are associated with their respective files. Once a change tracker is created, it will consume resources until the changes have been queried. As a result, change trackers should not be created without a plan to consume the accumulated changes, and should be removed when no longer needed.
Change trackers are not supported on Notecard LoRa.
Configuring a Change Tracker for a Notefile
To set-up a change tracker for a single file, use the note.changes
request
with the Notefile ID as file
, and a change tracker ID in the tracker
argument.
{
"req": "note.changes",
"file": "my-settings.db",
"tracker": "my_inbound_requests"
}
J *req = NoteNewRequest("note.changes");
JAddStringToObject(req, "file", "my-settings.db");
JAddStringToObject(req, "tracker", "my_inbound_requests");
NoteRequest(req);
req = {"req": "note.changes"}
req["file"] = "my-settings.db"
req["tracker"] = "my_inbound_requests"
rsp = card.Transaction(req)
This request returns an object with the total number of Notes in the Notefile, the total number of Notes changed since the change tracker was started, and an object containing each Note body, organized by ID.
{
"changes": 4,
"total": 4,
"notes": {
"setting-one": { "body": { "foo": "bar" }, "time": 1598918235 },
"setting-two": { "body": { "foo": "bat" }, "time": 1598918245 },
"setting-three": { "body": { "foo": "baz" }, "time": 1598918225 },
"setting-four": { "body": { "foo": "foo" }, "time": 1598910532 }
}
}
On the first call, a tracker is instantiated, and the inbound tracker lists all existing Notes in a Notefile. When a tracker is instantiated, the state changes from zero Notes being tracked, to all the Notes in a Notefile being tracked. As a result, the list of changes, or all notes, are displayed.
Change trackers on inbound queue Notefiles (.qi/.qis)
Using a change tracker on an inbound queue .qi./.qis
is not recommended.
Notes in queues are expected to be consumed completely, making change trackers
unnecessary. When used in such a manner, you may perform a note.get
to check
whether the queue is empty to detect if a change has occurred.
If you find you need long-lived data and your usage pattern does not align with the pattern outlined above, then your application by be better suited for use with a DB Notefile or environment variables.
However, if you elect to use a change tracker with .qi/.qis
Notefiles, then be
aware the Note ID is a system-generated,
internal ID. Whereas in DB Notefiles, the Note ID is developer-specified.
.qi
/.qis
Tracker Response Example:
{
"changes": 1,
"total": 1,
"notes": {
"1:495": {...}
}
}
Continuing with the example above, assume three more settings have been added to
the DB Notefile, my-settings.db
.
Use the max
argument to limit the number of notes returned when querying a
change tracker.
{
"req": "note.changes",
"file": "my-settings.db",
"tracker": "my_inbound_requests",
"max": 2
}
J *req = NoteNewRequest("note.changes");
JAddStringToObject(req, "file", "my-settings.db");
JAddStringToObject(req, "tracker", "my_inbound_requests");
JAddNumberToObject(req, "max", 2);
NoteRequest(req);
req = {"req": "note.changes"}
req["file"] = "my-settings.db"
req["tracker"] = "my_inbound_requests"
req["max"] = 2
rsp = card.Transaction(req)
Subsequent calls to note.changes
will display changed files only, while hiding
previously viewed changes.
// First Request
{
"changes": 3,
"total": 7,
"notes": {
"setting-five": {"body":{"bim": "bam"},"time":1598912838},
"setting-six": {"body":{"bing": "bong"},"time":1598923484}
}
}
// Second Request
{
"changes": 1,
"total": 7,
"notes": {
"setting-seven": {"body":{"zip": "zap"},"time":1598927365}
}
}
// Third Request
{"total":7}
Notes will be retrieved incrementally until all Notes are returned, at which
point an object with only the total
field is returned.
By default, Notes returned in note.changes
are not deleted. If you want to
delete them from the Notefile set the delete
argument to true
.
{
"req": "note.changes",
"file": "my-settings.db",
"tracker": "my_inbound_requests",
"delete": true
}
J *req = NoteNewRequest("note.changes");
JAddStringToObject(req, "file", "my-settings.db");
JAddStringToObject(req, "tracker", "my_inbound_requests");
JAddBoolToObject(req, "delete", true);
NoteRequest(req);
req = {"req": "note.changes"}
req["file"] = "my-settings.db"
req["tracker"] = "my_inbound_requests"
req["delete"] = True
rsp = card.Transaction(req)
Resetting a Change Tracker
If changes need to be reprocessed for any given reason, the reset
parameter
allows you to reset the change counter and tracker to their original states.
To reset a change tracker, perform a request to note.changes
with the
Notefile and change tracker id, and set the reset
argument to true
.
{
"req": "note.changes",
"file": "my-settings.db",
"tracker": "my_inbound_requests",
"reset": true
}
J *req = NoteNewRequest("note.changes");
JAddStringToObject(req, "file", "my-settings.db");
JAddStringToObject(req, "tracker", "my_inbound_requests");
JAddBoolToObject(req, "reset", true);
NoteRequest(req);
req = {"req": "note.changes"}
req["file"] = "my-settings.db"
req["tracker"] = "my_inbound_requests"
req["reset"] = True
rsp = card.Transaction(req)
Deleting a Change Tracker
Change trackers are meant to be long-lived and enable you to easily scan for changes on the Notecard at any time. As such, you won't often need to delete a change tracker unless the needs of your application change.
To delete a change tracker, perform a request to note.changes
with the
Notefile and change tracker id, and set the stop
argument to true
.
{
"req": "note.changes",
"file": "my-settings.db",
"tracker": "my_inbound_requests",
"stop": true
}
J *req = NoteNewRequest("note.changes");
JAddStringToObject(req, "file", "my-settings.db");
JAddStringToObject(req, "tracker", "my_inbound_requests");
JAddBoolToObject(req, "stop", true);
NoteRequest(req);
req = {"req": "note.changes"}
req["file"] = "my-settings.db"
req["tracker"] = "my_inbound_requests"
req["stop"] = True
rsp = card.Transaction(req)
Using Change Trackers Across Multiple Notefiles
To use a change tracker with multiple files, use the tracker
argument with the
file.changes
request, and provide a list of files to track.
Analogous to note.changes
, the first request will create trackers of the same
name on each of the Notefiles listed, and each subsequent request will query
those existing trackers and return the results as a single response.
{
"req": "file.changes",
"tracker": "multi-file-tracker",
"files": ["my-settings.db", "other-settings.db"]
}
J *req = NoteNewRequest("file.changes");
JAddStringToObject(req, "tracker", "multi-file-tracker");
J *files = JAddArrayToObject(req, "files");
JAddItemToArray(files, JCreateString("other-settings.db"));
JAddItemToArray(files, JCreateString("my-settings.db"));
NoteRequest(req);
req = {"req": "file.changes"}
req["tracker"] = "multi-file-tracker"
req["files"] = ["my-settings.db", "other-settings.db"]
rsp = card.Transaction(req)
The response returns the number of changes per file, as well as the total changes across all files.
{
"changes": 5,
"total": 5,
"info": {
"my-settings.db": { "changes": 3, "total": 3 },
"other-settings.db": { "changes": 2, "total": 2 }
}
}
Using the file.changes
tracker syntax provides an efficient way to quickly
query several files and determine which files have changed. Once the changed
files are known, you can process those individual Notefiles using the
note.changes
API outlined above.
Handling Notecard Interrupts
Host applications that interface with the Notecard often need to determine if
the Notecard has received inbound data for the host to process. This can be
achieved through periodic polling and the use of change trackers, as described
in
Using Change Trackers with Inbound Data.
However, this approach can be power-intensive on the host and difficult to
optimize for low-power applications. As such, the Notecard exposes a hardware
pin called ATTN
(referred to as the "attention pin"), which is used to notify
the host that the Notecard has detected an event of interest. The card.attn
request is used to configure the behavior of the ATTN
pin.
Depending upon its configuration, the Notecard can notify the host MCU in one or more of the following scenarios:
- When the Notecard receives a Note in specified Notefiles.
- When the Notecard connects to Notehub.
- When the Notecard detects motion.
- When the Notecard detects a location change.
- When the Notecard detects a change to its network state.
- When the Notecard is configured as a Watchdog timer.
Interrupt behavior
Arming the interrupt causes the Notecard to pull the ATTN
pin LOW
. When
armed, the GPIO connected to the Notecard attention pin will also read LOW
,
unless one of the monitored events occurs, in which case the pin will read
HIGH
. The interrupt is a latching interrupt. This means once it is armed, it
will stay LOW
until it has been disarmed or fired, and conversely, once fired
it will remain HIGH
until it has been rearmed.
In order to take full advantage of this behavior, you must correctly configure
your host microcontroller. The two most common configurations, are attaching the
Notecard's ATTN
pin to an interrupt capable GPIO pin or to the chip enable
(EN
) pin on the host MCU. In either case, your host MCU should respond by
obtaining inbound file changes, rearming the interrupt, or performing other
application specific actions.
Configuring the Attention Pin
In a card.attn
request, the mode
argument is the primary interface for
configuring the attention configurations described below. In addition, this
argument is used to arm and disarm the attention pin, ATTN
. The mode
argument accepts both single arguments, and a comma-separated list of keywords
that enable the configurations described below.
Disarming the Attention Pin
To disarm the pin, pass disarm
into the mode
argument. Disarming the
attention pin pulls the pin HIGH
.
{
"req": "card.attn",
"mode": "disarm"
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "disarm");
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "disarm"
card.Transaction(req)
As of Notecard firmware v3.2.1, if you have multiple attention modes
configured as detailed below, you can disarm all of these at once with the
-all
flag.
{
"req": "card.attn",
"mode": "disarm,-all"
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "disarm,-all");
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "disarm,-all"
card.Transaction(req)
Arming the Attention Pin
To arm the attention pin, pass arm
into the mode
argument of a card.attn
request, along with the optional keywords or parameters that correspond with
your desired configuration.
Setting an Attention Timeout
The simplest attention mode configuration is to arm the pin, and instruct the
Notecard to bring the pin HIGH
after a timeout of n
seconds. You can do
this with the seconds
argument, and by setting mode
to arm
.
{
"req": "card.attn",
"mode": "arm",
"seconds": 10
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "arm");
JAddNumberToObject(req, "seconds", 10);
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "arm"
req["seconds"] = 10
card.Transaction(req)
This request will return an empty JSON object ({}
). Then, after the timeout
has elapsed, the attention pin will be pulled HIGH
by the Notecard. You can
confirm that the attention pin has fired by making a request to card.attn
with no arguments.
{
"req": "card.attn"
}
J *req = NoteNewRequest("card.attn");
NoteRequest(req);
req = {"req": "card.attn"}
card.Transaction(req)
This request will return an object with a boolean, set
, reflecting the state
of the ATTN
pin and a files
array. The files
array contains the timeout
keyword, reflecting a timeout has occurred.
{
"files": ["timeout"],
"set": true
}
If the attention pin has not fired, a request to card.attn
will return an
empty JSON object ({}
).
The files
parameter is used as an input/output parameter with a list of files
to watch for changes, and also to receive a list of Notefile IDs that have
changed when using files
mode.
Watching for File Changes
If you want your host to be notified when the Notecard detects file changes, use
files
in the mode
argument, as well as the files
argument to provide an
array of one or more Notefiles to watch.
{
"req": "card.attn",
"mode": "arm,files",
"files": ["data.qi", "my-settings.db"]
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "arm, files");
J *files = JAddArrayToObject(req, "files");
JAddItemToArray(files, JCreateString("data.qi"));
JAddItemToArray(files, JCreateString("my-settings.db"));
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "arm, files"
req["files"] = ["data.qi", "my-settings.db"]
card.Transaction(req)
Alternatively, pass an empty string array to the files
argument to watch all
Notefiles on the Notecard.
{
"req": "card.attn",
"mode": "arm,files",
"files": [""]
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "arm, files");
J *files = JAddArrayToObject(req, "files");
JAddItemToArray(files, JCreateString(""));
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "arm, files"
req["files"] = [""]
card.Transaction(req)
The interrupt fires when the Notecard detects a change to a watched file. You
can use a no argument card.attn
request to determine which file has changed.
The response object will contain the name of the modified file, so you can issue
a note.changes
request to get new or modified Notes.
{
"files": ["data.qi", "modified"],
"set": true
}
To disable file mode, issue another card.attn
request, and add a dash before
the files
string in the mode
argument to indicate that it should be
disabled.
{
"req": "card.attn",
"mode": "-files"
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "-files");
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "-files"
card.Transaction(req)
Watching for Service Connections
The attention pin can be set to fire whenever the Notecard successfully connects
to Notehub with the connected
string in the mode
argument.
{
"req": "card.attn",
"mode": "arm,connected"
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "arm,connected");
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "arm,connected"
card.Transaction(req)
The interrupt fires the next time the Notecard connects. You can use a no
argument, card.attn
request to confirm the reason. In connection mode, the
files
array in a card.attn
response object will include the connected
string.
{
"files": ["connected"],
"set": true
}
To disable connection mode, issue another card.attn
request, and add a dash
before the connected
string in the mode
argument to indicate that it should
be disabled.
{
"req": "card.attn",
"mode": "-connected"
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "-connected");
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "-connected"
card.Transaction(req)
Watching for Notecard Motion
The attention pin can be set to fire whenever the Notecard accelerometer detects
motion with the motion
string in the mode
argument.
{
"req": "card.attn",
"mode": "arm,motion"
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "arm,motion");
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "arm,motion"
card.Transaction(req)
The interrupt fires when the accelerometer detects movement. You can use a no
argument card.attn
request to confirm the reason. In motion mode, the files
array in a card.attn
response object will include the motion
string.
{
"files": ["motion"],
"set": true
}
To disable motion mode, issue another card.attn
request, and add a dash
before the motion
string in the mode
argument to indicate that it should
be disabled.
{
"req": "card.attn",
"mode": "-motion"
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "-motion");
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "-motion"
card.Transaction(req)
Watching for Notecard Location Updates
The attention pin can be set to fire whenever the Notecard GPS/GNSS module
detects a location update with the location
string in the mode
argument.
{
"req": "card.attn",
"mode": "arm,location"
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "arm,location");
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "arm,location"
card.Transaction(req)
The interrupt fires when a location change is detected. You can use a no
argument card.attn
request to confirm the reason. In location mode, the
files
array in a card.attn
response object will include the location
string.
{
"files": ["location"],
"set": true
}
To disable location mode, issue another card.attn
request, and add a dash
before the location
string in the mode
argument to indicate that it should
be disabled.
{
"req": "card.attn",
"mode": "-location"
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "-location");
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "-location"
card.Transaction(req)
Watching for Environment Variable Changes
The attention pin can be set to fire whenever the Notecard detects an
Environment Variable update with the env
string in the mode
argument.
{
"req": "card.attn",
"mode": "arm,env"
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "arm,env");
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "arm,env"
card.Transaction(req)
The interrupt fires when an Environment Variable change is detected. You can use
a no argument card.attn
request to confirm the reason. In env mode, the
files
array in a card.attn
response object will include the env
string.
{
"files": ["env"],
"set": true
}
To disable env mode, issue another card.attn
request, and add a dash
before the env
string in the mode
argument to indicate that it should
be disabled.
{
"req": "card.attn",
"mode": "-env"
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "-env");
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "-env"
card.Transaction(req)
Watching for Notecard Network Status Changes
The attention pin can be set to fire whenever the Notecard detects a change in
the network status it communicates via the card.wireless
request.
{
"req": "card.attn",
"mode": "arm,wireless"
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "arm,wireless");
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "arm,wireless"
card.Transaction(req)
The interrupt fires when a network status change is detected. You can use a no
argument
card.wireless
request
to inspect the change. In wireless mode, the files
array in a card.attn
response object will include the wireless
string.
{
"files": ["wireless"],
"set": true
}
To disable wireless mode, issue another card.attn
request, and add a dash
before the wireless
string in the mode
argument to indicate that it should
be disabled.
{
"req": "card.attn",
"mode": "-wireless"
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "-wireless");
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "-wireless"
card.Transaction(req)
Using Multiple Modes Together
The modes described above are not mutually-exclusive, and can be used together.
Simply provide a comma between each watch mode when calling card.attn
:
{
"req": "card.attn",
"mode": "arm,files,connected,location",
"files": ["data.qi"]
}
J *req = NoteNewRequest("card.attn");
JAddStringToObject(req, "mode", "arm,files,connected,location");
J *files = JAddArrayToObject(req, "files");
JAddItemToArray(files, JCreateString("data.qi"));
NoteRequest(req);
req = {"req": "card.attn"}
req["mode"] = "arm,files,connected,location"
req["files"] = ["data.qi"]
card.Transaction(req)
When multiple modes are used together, no argument calls to card.attn
will
identify all of the modes and files that caused the pin to fire.
{
"files": ["data.qi", "motion", "connected"],
"set": true
}
Miscellaneous File Requests
To obtain information about local Notefiles on the Notecard, use the
file.stats
request.
{
"req": "file.stats"
}
This request returns a total number of notes across all Notefiles, a count of
the number of Notes pending sync to Notehub (changes
), if any, and a sync
field of true
if a sync is recommended based on the number of pending Notes.
This field should be considered false
, if not present.
{
"changes": 1,
"total": 4
}
For details on Notes pending sync, use the file.changes.pending
request.
{
"req": "file.changes.pending"
}
This request returns a pending
boolean indicating whether any Notes are
pending sync, total notes and changes across all files, as well as a per-file
listing of pending changes.
{
"changes": 2,
"total": 2,
"pending": true,
"info": {
"sensors.qo": {
"changes": 1,
"total": 1
},
"data.qo": {
"changes": 1,
"total": 1
}
}
}
Finally, to delete a Notefile and all of the Notes contained within, use the
file.delete
request. This request accepts a single argument files
, which
is an array of Notefiles to delete. If successful, this request will return an
empty JSON object ({}
).
{
"req": "file.delete",
"files" ["sensors.qo"]
}