Advanced Notecard Configuration
The Notecard provides a number of advanced configuration features that you can use to query the state and status of the Notecard, customize its behavior, set its Notehub service location, and configure the available AUX pins for use in your application.
Issue Maintenance Requests
The Notecard API provides requests you can use to query the Notecard for version and status information, restart the Notecard, or factory reset it completely.
Getting the Notecard Version
To obtain version information from the Notecard, send card.version
request.
This request is sent without arguments, and returns the Notecard brand and
model for the name
, Notecard version
, the sku
, device
UID, device
type
, and a body
with version and build details for programmatic access.
{
"req": "card.version"
}
J *req = NoteNewRequest("card.version");
NoteRequest(req);
req = {"req": "card.version"}
card.Transaction(req)
{
"version": "notecard-5.3.1",
"device": "dev:000000000000000",
"name": "Blues Wireless Notecard",
"sku": "NOTE-NBGL-500",
"board": "1.11",
"cell": true,
"gps": true,
"api": 5,
"body": {
"org": "Blues Wireless",
"product": "Notecard",
"target": "r5",
"version": "notecard-5.3.1",
"ver_major": 5,
"ver_minor": 3,
"ver_patch": 1,
"ver_build": 371,
"built": "Sep 5 2023 12:21:30"
}
}
Setting the Notecard API Major Version
If you need to specify the major version of the Notecard API your host expects,
you can do so by adding an api
argument to a card.version
request. All
subsequent requests to the Notecard will use the API contract of that major
version. This capability allows you to freely update your Notecard firmware
to get fixes and improvements without needing to update your host application.
{
"req": "card.version",
"api": 1
}
J *req = NoteNewRequest("card.version");
JAddNumberToObject(req, "api", 1);
NoteRequest(req);
req = {"req": "card.version"}
req["api"] = 1
rsp = card.Transaction(req)
Getting Notecard Status
To obtain information about the current operating status of the Notecard,
use the card.status
request. This request is sent without arguments, and
returns a status
string, a usb
field if the Notecard is currently powered
by USB, the percentage of storage
used on the Notecard, The UNIX Epoch time
the Notecard obtained the time after starting up, and a connected
field if the
Notecard is connected to Notehub.
{
"req": "card.status"
}
J *req = NoteNewRequest("card.status");
NoteRequest(req);
req = {"req": "card.status"}
card.Transaction(req)
{
"status": "{normal}",
"usb": true,
"storage": 8,
"time": 1599067096,
"connected": true
}
Setting Card Contact information
The card.contact
request can be used to set or retrieve information about the
Notecard maintainer. Once set, this information is synched to Notehub. When
setting this information, any or all of the following values can be provided:
name
org
role
email
{
"req": "card.contact",
"name": "Tom Turkey",
"org": "Blues Inc.",
"role": "Head of Security",
"email": "tom@blues.com"
}
J *req = NoteNewRequest("card.contact");
JAddStringToObject(req, "name", "Tom Turkey");
JAddStringToObject(req, "org", "Blues Inc.");
JAddStringToObject(req, "role", "Head of Security");
JAddStringToObject(req, "email", "tom@blues.com");
NoteRequest(req);
req = {"req": "card.contact"}
req["name"] = "Tom Turkey"
req["org"] = "Blues Inc."
req["role"] = "Head of Security"
req["email"] = "tom@blues.com"
rsp = card.Transaction(req)
When sent with no arguments, card.contact
returns all of the previously
set contact values:
{
"req": "card.contact"
}
J *req = NoteNewRequest("card.contact");
NoteRequest(req);
req = {"req": "card.contact"}
card.Transaction(req)
{
"name": "Tom Turkey",
"org": "Blues Inc.",
"role": "Head of Security",
"email": "tom@blues.com"
}
Restarting the Notecard
To power-cycle the Notecard, send a card.restart
request with no arguments.
This request returns an empty JSON object ({}
) before restarting.
{
"req": "card.restart"
}
J *req = NoteNewRequest("card.restart");
NoteRequest(req);
req = {"req": "card.restart"}
card.Transaction(req)
Calls to card.restart
are not supported for use in production applications as
they can cause increased cellular data and consumption credit usage.
Factory Resetting the Notecard
To perform a factory reset on the Notecard, send a card.restore
request. This
request can be made with no arguments, which restores the Notecard to its
factory state but preserves its configuration settings, Notefile templates, and
environment variables.
To delete configuration settings, set the delete
argument to true
.
To remove any Notefile templates and environment variables used by this device,
set the connected
argument to true
. Conversely, if connected
is false (or
omitted), then the Notecard's environment variables and data will be restored
from Notehub the next time the Notecard connects to the previously used Notehub
project.
This request returns an empty JSON object ({}
) before restoring the device and
restarting.
Setting delete
to true
will also remove the ProductUID on the Notecard, and
the Notecard will not be able to re-connect to Notehub until a new Product UID
is set.
{
"req": "card.restore",
"delete": true,
"connected": true
}
J *req = NoteNewRequest("card.restore");
JAddBoolToObject(req, "delete", true);
JAddBoolToObject(req, "connected", true);
NoteRequest(req);
req = {"req": "card.restore"}
req["delete"] = True
req["connected"] = True
card.Transaction(req)
Change the Notehub Service Host
If your Notecard needs to be configured to connect to a new Notehub host, use
the hub.set
request and provide the url of the new host in the host
argument. This request returns an empty JSON object ({}
).
{
"req": "hub.set",
"host": "a.mynotehub.net"
}
J *req = NoteNewRequest("hub.set");
JAddStringToObject(req, "host", "a.mynotehub.net");
NoteRequest(req);
req = {"req": "hub.set"}
req["host"] = "a.mynotehub.net"
card.Transaction(req)
To
reset
your host back to the default Notehub host, use a single dash (-
) in the host
argument.
{
"req": "hub.set",
"host": "-"
}
J *req = NoteNewRequest("hub.set");
JAddStringToObject(req, "host", "-");
NoteRequest(req);
req = {"req": "hub.set"}
req["host"] = "-"
card.Transaction(req)
View and Customize Modem behavior
The card.wireless
request can be used to view details about the last known
network, or customize the behavior of the Notecard's modem, if needed. A
card.wireless
request with no arguments returns network state information,
including the current connection status
, count
of bars of signal quality,
and net
object that contains detailed modem, access technology and signal
strength information.
{
"req": "card.wireless"
}
J *req = NoteNewRequest("card.wireless");
NoteRequest(req);
req = {"req": "card.wireless"}
card.Transaction(req)
{
"status": "{modem-off}",
"count": 1,
"net": {
"iccid": "00000000000000000000",
"imsi": "000000000000000",
"imei": "000000000000000",
"modem": "EG91NAXGAR07A03M1G_BETA0415_01.001.01.001",
"band": "LTE BAND 2",
"rat": "lte",
"rssir": -69,
"rssi": -70,
"rsrp": -105,
"sinr": 86,
"rsrq": -17,
"bars": 1,
"mcc": 310,
"mnc": 410,
"lac": 28681,
"cid": 211150856,
"updated": 1599225076
}
}
To customize the behavior of the modem on the Notecard, use the mode
argument
in a card.wireless
request, which accepts the following values:
auto
to select automatic band scan mode.m
to restrict the modem to Cat-M1.nb
to restrict the modem to Cat-NB1.gprs
to restrict the modem to EGPRS.-
to reset the modem configuration to the Notecard default.
When the mode
argument is used, card.wireless
returns the same fields
as a no argument request.
{
"req": "card.wireless",
"mode": "nb"
}
J *req = NoteNewRequest("card.wireless");
JAddStringToObject(req, "mode", "nb");
NoteRequest(req);
req = {"req": "card.wireless"}
req["mode"] = "nb"
rsp = card.Transaction(req)
Modes m
, nb
, and gprs
are only applicable on the "narrowband" Notecard
SKUs (e.g. SKUs that start with NOTE-NB
).
If you prefer to use the Notecard with an external 3rd party SIM, you can
use the apn
argument to instruct the Notecard to connect to a different
Access Point Name (APN) when establishing a network connection.
{
"req": "card.wireless",
"apn": "myapn.nb"
}
J *req = NoteNewRequest("card.wireless");
JAddStringToObject(req, "apn", "myapn.nb");
NoteRequest(req);
req = {"req": "card.wireless"}
req["apn"] = "myapn.nb"
rsp = card.Transaction(req)
Setting the mode
or apn
arguments may cause the Notecard to lose its
cellular connection and be unable to reconnect until it has been reconfigured.
Be careful when using this setting to select a mode that you know will work for
the Notecard's physical location.
Change the Notecard I2C Address
If the default I2C address of the Notecard (0x17
) conflicts with another
device in your product, you can change the Notecard address with a card.io
request. This request takes an i2c
argument with a decimal value of the new
I2C address and returns an empty JSON object ({}
).
For example, this request passes a decimal value of 24
, which corresponds to
the I2C address of 0x18
:
{
"req": "card.io",
"i2c": 24
}
J *req = NoteNewRequest("card.io");
JAddNumberToObject(req, "i2c", 24);
NoteRequest(req);
req = {"req": "card.io"}
req["i2c"] = 24
card.Transaction(req)
To
reset
the Notecard to the default I2C address, use -1
as the i2c
argument value:
{
"req": "card.io",
"i2c": -1
}
J *req = NoteNewRequest("card.io");
JAddNumberToObject(req, "i2c", -1);
NoteRequest(req);
req = {"req": "card.io"}
req["i2c"] = -1
card.Transaction(req)
Be sure to issue this request over a UART or USB connection. Changing the I2C address while connected to the Notecard I2C may cause unexpected results.
Functions that Require Setting Time
The Notecard will not enable certain functions until it has made a successful network connection upon startup to obtain the current time. Once the Notecard has the time, these functions are available for use, regardless of the state of the network connection going forward.
If the Notecard is power cycled, it will have to re-establish a successful network connection to obtain the current time.
These are the functions that require the current time:
- GPS location tracking
- Motion/asset tracking
- Notecard and host MCU DFU
- A
note.add
request - Cell tower and Wi-Fi triangulation
- A
card.time
request - Notecard data usage tracking for usage analysis requests
- Voltage monitoring for voltage analysis requests
- Inbound/outbound sync scheduling calculations
- Certain AUX counter features
Validate Notecard Responses
As of Notecard firmware v5.3.1, you may validate responses from the Notecard using a Cyclic Redundancy Check (CRC). In extremely rare cases, dropped or altered bytes on I2C or UART interfaces could result in JSON parse errors on the Notecard.
The latest versions of
note-arduino
,
note-c
, and
note-go
all apply the CRC checks described
below, and additionally perform automatic retries on I/O errors. If you're using
one of these libraries make sure you update to the latest version, and Notecard
response validation will happen automatically with no extra work required.
CRC Usage
The crc
argument can be supplied to any Notecard API. The format of the
argument is "crc":"SSSS:CCCCCCCC"
:
- SSSS = An arbitrary sequence number chosen by the host (this matches responses to requests).
- CCCCCCCC = CRC-32 as ASCII Hex (IEEE 802.3 polynomial 0x04C11DB7 Init:0xFFFFFFFF).
The CRC-32 should be calculated on the JSON request without the CRC argument, but with the closing brace. For example with this request:
{"req":"hub.get"}
The crc32
value is 0xE37F7D23
. See the
Online CRC Calculator and select "CRC-32" for more
details.
CRC Example
Consider the following Notecard request:
{"req":"note.add","body":{"foo":"bar"}}
Without using crc
, in an extremely rare circumstance with dropped or altered
bytes on the I2C or UART interfaces, the request could become the following,
with no error reported:
{"req":"note.add","body":{"fxx":"bx"}}
However, with crc
enabled:
{"req":"note.add","body":{"foo":"bar"},"crc":"1234:9F27DC43"}
{"total":2,"crc":"1234:3EE67BF0"}
The error would have been caught:
{"req":"note.add","body":{"fxx":"bx"},"crc":"1234:9F27DC43"}
{"err":"CRC error in request {io}"}
APIs and Arguments for Robustness Testing
The Notecard API includes an additional request and the ability to use "universal arguments" (meaning usable with any Notecard API) that can help to test the robustness of Notecard requests.
These are generally only useful if not using one of the Blues-supported Notecard firmware libraries.
echo
API
The echo
API takes everything in the request, except for the req
field, and
returns it in the response. Each argument in the request must correspond to an
existing argument available in any other Notecard API (and also must match the
data type).
This is included for robustness testing of I2C and serial hardware communications, generally to make sure that pull-ups and lines are behaving properly at high velocity.
For example:
{
"req": "echo",
"deleted": true,
"start": true,
"signals": 752408723,
"max": -1006377422,
"status": "open"
}
Will return:
{
"cmd": "echo",
"deleted": true,
"start": true,
"signals": 752408723,
"max": -1006377422,
"status": "open"
}
id
Argument
If an id
argument (integer) is passed with a request, the same id
will be
returned in the response. This is included for serial protocol robustness
testing, as a way to ensure that a given response correlates to a given request.
For example:
{
"req": "hub.get",
"id": 123456
}
Will return:
{
"id": 123456,
"secure": true,
"mode": "continuous",
"host": "a.notefile.net",
"product": "com.blues.testing:testing",
"device": "dev:860322068012345",
"sync": true
}
pad
Argument
If an integer value >= 20
is supplied to the pad
argument, it is guaranteed
that the first [n] bytes of the reply will look like {"len":n ...
(potentially
filled out to [n] bytes with spaces if the total request length is < pad
).
This is useful in a serial driver or OS environment where ONLY blocking I/Os
are supported, as you can read the response in a reliable manner using blocking
I/O.
The following are steps you could take to utilize the pad
argument in C:
- Send an API request with
"pad":20
. - Perform a blocking read of
20
bytes intobuf
, waiting for the reply. - Perform the following length calculation:
unsigned remainingLen = atoi(&buf[7]) - 20
. - Perform a blocking read of
remainingLen
bytes into&buf[20]
. This will read the entire JSON reply intobuf
.
The following is an example request in plain JSON:
{
"pad": 20,
"req": "card.time"
}
Will return:
{
"len": 169,
"minutes": -240,
"lat": 42.512662499999978,
"lon": -70.910546875000009,
"area": "Salem MA",
"country": "US",
"zone": "EDT,America/New_York",
"time": 1625711237
}
In the above example, len
is 169
because of the \r\n
that is not visible.